From 2c2c7936e576c45d1f773576a69b1ba95d30325b Mon Sep 17 00:00:00 2001 From: electron128 Date: Sun, 7 Feb 2016 14:09:33 +0100 Subject: [PATCH] libresapi: make list of chat lobby participants available at chat/lobby_participants/ --- libresapi/src/api/ChatHandler.cpp | 93 ++++++++++++++++++++++++++++++- libresapi/src/api/ChatHandler.h | 9 +++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/libresapi/src/api/ChatHandler.cpp b/libresapi/src/api/ChatHandler.cpp index 4a40bb38c..cadaae810 100644 --- a/libresapi/src/api/ChatHandler.cpp +++ b/libresapi/src/api/ChatHandler.cpp @@ -97,6 +97,39 @@ StreamBase& operator << (StreamBase& left, ChatHandler::ChatInfo& info) return left; } +class SendLobbyParticipantsTask: public GxsResponseTask +{ +public: + SendLobbyParticipantsTask(RsIdentity* idservice, ChatHandler::LobbyParticipantsInfo pi): + GxsResponseTask(idservice, 0), mParticipantsInfo(pi) + { + const std::map& map = mParticipantsInfo.participants; + for(std::map::const_iterator mit = map.begin(); mit != map.end(); ++mit) + { + requestGxsId(mit->first); + } + } +private: + ChatHandler::LobbyParticipantsInfo mParticipantsInfo; +protected: + virtual void gxsDoWork(Request &req, Response &resp) + { + resp.mDataStream.getStreamToMember(); + const std::map& map = mParticipantsInfo.participants; + for(std::map::const_iterator mit = map.begin(); mit != map.end(); ++mit) + { + StreamBase& stream = resp.mDataStream.getStreamToMember(); + double last_active = mit->second; + stream << makeKeyValueReference("last_active", last_active); + streamGxsId(mit->first, stream.getStreamToMember("identity")); + } + resp.mStateToken = mParticipantsInfo.state_token; + resp.setOk(); + done(); + } + +}; + ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, RsPeers* peers, RsIdentity* identity, UnreadMsgNotify* unread): mStateTokenServer(sts), mNotify(notify), mRsMsgs(msgs), mRsPeers(peers), mRsIdentity(identity), mUnreadMsgNotify(unread), mMtx("ChatHandler::mMtx") { @@ -111,6 +144,7 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, addResourceHandler("lobbies", this, &ChatHandler::handleLobbies); addResourceHandler("subscribe_lobby", this, &ChatHandler::handleSubscribeLobby); addResourceHandler("unsubscribe_lobby", this, &ChatHandler::handleUnsubscribeLobby); + addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants); addResourceHandler("messages", this, &ChatHandler::handleMessages); addResourceHandler("send_message", this, &ChatHandler::handleSendMessage); addResourceHandler("mark_chat_as_read", this, &ChatHandler::handleMarkChatAsRead); @@ -170,9 +204,46 @@ void ChatHandler::tick() l.is_broadcast = false; l.gxs_id = info.gxs_id; lobbies.push_back(l); + + // update the lobby participants list + // maybe it causes to much traffic to do this in every tick, + // because the client would get the whole list every time a message was received + // we could reduce the checking frequency + std::map::iterator mit = mLobbyParticipantsInfos.find(*lit); + if(mit == mLobbyParticipantsInfos.end()) + { + mLobbyParticipantsInfos[*lit].participants = info.gxs_ids; + mLobbyParticipantsInfos[*lit].state_token = mStateTokenServer->getNewToken(); + } + else + { + LobbyParticipantsInfo& pi = mit->second; + if(!std::equal(pi.participants.begin(), pi.participants.end(), info.gxs_ids.begin())) + { + pi.participants = info.gxs_ids; + mStateTokenServer->replaceToken(pi.state_token); + } + } } } + // remove participants info of old lobbies + std::vector participants_info_to_delete; + for(std::map::iterator mit = mLobbyParticipantsInfos.begin(); + mit != mLobbyParticipantsInfos.end(); ++mit) + { + if(std::find(subscribed_ids.begin(), subscribed_ids.end(), mit->first) == subscribed_ids.end()) + { + participants_info_to_delete.push_back(mit->first); + } + } + for(std::vector::iterator vit = participants_info_to_delete.begin(); vit != participants_info_to_delete.end(); ++vit) + { + LobbyParticipantsInfo& pi = mLobbyParticipantsInfos[*vit]; + mStateTokenServer->discardToken(pi.state_token); + mLobbyParticipantsInfos.erase(*vit); + } + { Lobby l; l.name = "BroadCast"; @@ -496,11 +567,31 @@ void ChatHandler::handleSubscribeLobby(Request &req, Response &resp) resp.setFail("lobby join failed. (See console for more info)"); } -void ChatHandler::handleUnsubscribeLobby(Request &req, Response &/*resp*/) +void ChatHandler::handleUnsubscribeLobby(Request &req, Response &resp) { ChatLobbyId id = 0; req.mStream << makeKeyValueReference("id", id); mRsMsgs->unsubscribeChatLobby(id); + resp.setOk(); +} + +ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp) +{ + RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + + ChatId id(req.mPath.top()); + if(!id.isLobbyId()) + { + resp.setFail("Path element \""+req.mPath.top()+"\" is not a ChatLobbyId."); + return 0; + } + std::map::const_iterator mit = mLobbyParticipantsInfos.find(id.toLobbyId()); + if(mit == mLobbyParticipantsInfos.end()) + { + resp.setFail("lobby not found"); + return 0; + } + return new SendLobbyParticipantsTask(mRsIdentity, mit->second); } void ChatHandler::handleMessages(Request &req, Response &resp) diff --git a/libresapi/src/api/ChatHandler.h b/libresapi/src/api/ChatHandler.h index bb15cf2f1..931e10514 100644 --- a/libresapi/src/api/ChatHandler.h +++ b/libresapi/src/api/ChatHandler.h @@ -81,6 +81,12 @@ public: } }; + class LobbyParticipantsInfo{ + public: + StateToken state_token; + std::map participants; + }; + class ChatInfo{ public: bool is_broadcast; @@ -96,6 +102,7 @@ private: void handleLobbies(Request& req, Response& resp); void handleSubscribeLobby(Request& req, Response& resp); void handleUnsubscribeLobby(Request& req, Response& resp); + ResponseTask* handleLobbyParticipants(Request& req, Response& resp); void handleMessages(Request& req, Response& resp); void handleSendMessage(Request& req, Response& resp); void handleMarkChatAsRead(Request& req, Response& resp); @@ -124,6 +131,8 @@ private: StateToken mLobbiesStateToken; std::vector mLobbies; + std::map mLobbyParticipantsInfos; + StateToken mUnreadMsgsStateToken; };