From 2ab755bb5c3cc8355e23cecc94a01e27e78ed966 Mon Sep 17 00:00:00 2001 From: electron128 <electron128@yahoo.com> Date: Sun, 14 Feb 2016 14:57:41 +0100 Subject: [PATCH] libresapi: added chat/receive_status usage: $ curl http://<host:port>/localhost:8080/api/v2/chat/receive_status/<chat_id> --- libresapi/src/api/ChatHandler.cpp | 195 +++++++++++++------------- libresapi/src/api/ChatHandler.h | 22 ++- libresapi/src/api/GxsResponseTask.cpp | 1 + libresapi/src/api/GxsResponseTask.h | 2 +- 4 files changed, 121 insertions(+), 99 deletions(-) diff --git a/libresapi/src/api/ChatHandler.cpp b/libresapi/src/api/ChatHandler.cpp index 9d4062271..598db5c09 100644 --- a/libresapi/src/api/ChatHandler.cpp +++ b/libresapi/src/api/ChatHandler.cpp @@ -149,7 +149,7 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, addResourceHandler("send_message", this, &ChatHandler::handleSendMessage); addResourceHandler("mark_chat_as_read", this, &ChatHandler::handleMarkChatAsRead); addResourceHandler("info", this, &ChatHandler::handleInfo); - addResourceHandler("typing_label", this, &ChatHandler::handleTypingLabel); + addResourceHandler("receive_status", this, &ChatHandler::handleReceiveStatus); addResourceHandler("send_status", this, &ChatHandler::handleSendStatus); addResourceHandler("unread_msgs", this, &ChatHandler::handleUnreadMsgs); } @@ -166,20 +166,21 @@ void ChatHandler::notifyChatMessage(const ChatMessage &msg) mRawMsgs.push_back(msg); } -// to be removed -/* -ChatHandler::Lobby ChatHandler::getLobbyInfo(ChatLobbyId id) +void ChatHandler::notifyChatStatus(const ChatId &chat_id, const std::string &status) { - tick(); - - RS_STACK_MUTEX(mMtx); // ********* LOCKED ********** - for(std::vector<Lobby>::iterator vit = mLobbies.begin(); vit != mLobbies.end(); ++vit) - if(vit->id == id) - return *vit; - std::cerr << "ChatHandler::getLobbyInfo Error: Lobby not found" << std::endl; - return Lobby(); + RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + locked_storeTypingInfo(chat_id, status); +} + +void ChatHandler::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type, + const RsGxsId &nickname, const std::string& any_string) +{ + RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + if(event_type == RS_CHAT_LOBBY_EVENT_PEER_STATUS) + { + locked_storeTypingInfo(ChatId(lobby_id), any_string, nickname); + } } -*/ void ChatHandler::tick() { @@ -510,6 +511,15 @@ void ChatHandler::getPlainText(const std::string& in, std::string &out, std::vec } } +void ChatHandler::locked_storeTypingInfo(const ChatId &chat_id, std::string status, RsGxsId lobby_gxs_id) +{ + TypingLabelInfo& info = mTypingLabelInfo[chat_id]; + info.timestamp = time(0); + info.status = status; + mStateTokenServer->replaceToken(info.state_token); + info.author_id = lobby_gxs_id; +} + void ChatHandler::handleWildcard(Request &/*req*/, Response &resp) { RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ @@ -664,89 +674,6 @@ void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp) mStateTokenServer->replaceToken(mUnreadMsgsStateToken); } -// to be removed -// we do now cache chat info, to be able to include it in new message notify easily -/* -class InfoResponseTask: public GxsResponseTask -{ -public: - InfoResponseTask(ChatHandler* ch, RsPeers* peers, RsIdentity* identity): GxsResponseTask(identity, 0), mChatHandler(ch), mRsPeers(peers), mState(BEGIN){} - - enum State {BEGIN, WAITING}; - ChatHandler* mChatHandler; - RsPeers* mRsPeers; - State mState; - bool is_broadcast; - bool is_gxs_id; - bool is_lobby; - bool is_peer; - std::string remote_author_id; - std::string remote_author_name; - virtual void gxsDoWork(Request& req, Response& resp) - { - ChatId id(req.mPath.top()); - if(id.isNotSet()) - { - resp.setFail("not a valid chat id"); - done(); - return; - } - if(mState == BEGIN) - { - is_broadcast = false; - is_gxs_id = false; - is_lobby = false; - is_peer = false; - if(id.isBroadcast()) - { - is_broadcast = true; - } - else if(id.isGxsId()) - { - is_gxs_id = true; - remote_author_id = id.toGxsId().toStdString(); - requestGxsId(id.toGxsId()); - } - else if(id.isLobbyId()) - { - is_lobby = true; - remote_author_id = ""; - remote_author_name = mChatHandler->getLobbyInfo(id.toLobbyId()).name; - } - else if(id.isPeerId()) - { - is_peer = true; - remote_author_id = id.toPeerId().toStdString(); - remote_author_name = mRsPeers->getPeerName(id.toPeerId()); - } - else - { - std::cerr << "Error in InfoResponseTask::gxsDoWork(): unhandled chat_id=" << id.toStdString() << std::endl; - } - mState = WAITING; - } - else - { - if(is_gxs_id) - remote_author_name = getName(id.toGxsId()); - resp.mDataStream << makeKeyValueReference("remote_author_id", remote_author_id) - << makeKeyValueReference("remote_author_name", remote_author_name) - << makeKeyValueReference("is_broadcast", is_broadcast) - << makeKeyValueReference("is_gxs_id", is_gxs_id) - << makeKeyValueReference("is_lobby", is_lobby) - << makeKeyValueReference("is_peer", is_peer); - resp.setOk(); - done(); - } - } -}; - -ResponseTask *ChatHandler::handleInfo(Request &req, Response &resp) -{ - return new InfoResponseTask(this, mRsPeers, mRsIdentity); -} -*/ - void ChatHandler::handleInfo(Request &req, Response &resp) { RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ @@ -766,9 +693,83 @@ void ChatHandler::handleInfo(Request &req, Response &resp) resp.setOk(); } -void ChatHandler::handleTypingLabel(Request &/*req*/, Response &/*resp*/) +class SendTypingLabelInfo: public GxsResponseTask { +public: + SendTypingLabelInfo(RsIdentity* identity, RsPeers* peers, ChatId id, const ChatHandler::TypingLabelInfo& info): + GxsResponseTask(identity), mState(BEGIN), mPeers(peers),mId(id), mInfo(info) {} +private: + enum State {BEGIN, WAITING_ID}; + State mState; + RsPeers* mPeers; + ChatId mId; + ChatHandler::TypingLabelInfo mInfo; +protected: + void gxsDoWork(Request& /*req*/, Response& resp) + { + if(mState == BEGIN) + { + // lobby and distant require to fetch a gxs_id + if(mId.isLobbyId()) + { + requestGxsId(mInfo.author_id); + } + else if(mId.isDistantChatId()) + { + DistantChatPeerInfo dcpinfo ; + rsMsgs->getDistantChatStatus(mId.toDistantChatId(), dcpinfo); + requestGxsId(dcpinfo.to_id); + } + mState = WAITING_ID; + } + else + { + std::string name = "BUG: case not handled in SendTypingLabelInfo"; + if(mId.isPeerId()) + { + name = mPeers->getPeerName(mId.toPeerId()); + } + else if(mId.isDistantChatId()) + { + DistantChatPeerInfo dcpinfo ; + rsMsgs->getDistantChatStatus(mId.toDistantChatId(), dcpinfo); + name = getName(dcpinfo.to_id); + } + else if(mId.isLobbyId()) + { + name = getName(mInfo.author_id); + } + else if(mId.isBroadcast()) + { + name = mPeers->getPeerName(mId.broadcast_status_peer_id); + } + uint32_t ts = mInfo.timestamp; + resp.mDataStream << makeKeyValueReference("author_name", name) + << makeKeyValueReference("timestamp", ts) + << makeKeyValueReference("status_string", mInfo.status); + resp.mStateToken = mInfo.state_token; + resp.setOk(); + done(); + } + } +}; +ResponseTask* ChatHandler::handleReceiveStatus(Request &req, Response &resp) +{ + RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + ChatId id(req.mPath.top()); + if(id.isNotSet()) + { + resp.setFail("\""+req.mPath.top()+"\" is not a valid chat id"); + return 0; + } + std::map<ChatId, TypingLabelInfo>::iterator mit = mTypingLabelInfo.find(id); + if(mit == mTypingLabelInfo.end()) + { + locked_storeTypingInfo(id, ""); + mit = mTypingLabelInfo.find(id); + } + return new SendTypingLabelInfo(mRsIdentity, mRsPeers, id, mit->second); } void ChatHandler::handleSendStatus(Request &req, Response &resp) diff --git a/libresapi/src/api/ChatHandler.h b/libresapi/src/api/ChatHandler.h index 931e10514..e16aa445b 100644 --- a/libresapi/src/api/ChatHandler.h +++ b/libresapi/src/api/ChatHandler.h @@ -26,6 +26,13 @@ public: // note: this may get called from the own and from foreign threads virtual void notifyChatMessage(const ChatMessage& msg); + // typing label for peer, broadcast and distant chat + virtual void notifyChatStatus (const ChatId& /* chat_id */, const std::string& /* status_string */); + + //typing label for lobby chat, peer join and leave messages + virtual void notifyChatLobbyEvent (uint64_t /* lobby id */, uint32_t /* event type */ , + const RsGxsId& /* nickname */,const std::string& /* any string */); + // from tickable virtual void tick(); @@ -97,6 +104,15 @@ public: std::string remote_author_name; }; + class TypingLabelInfo{ + public: + time_t timestamp; + std::string status; + StateToken state_token; + // only for lobbies + RsGxsId author_id; + }; + private: void handleWildcard(Request& req, Response& resp); void handleLobbies(Request& req, Response& resp); @@ -107,11 +123,13 @@ private: void handleSendMessage(Request& req, Response& resp); void handleMarkChatAsRead(Request& req, Response& resp); void handleInfo(Request& req, Response& resp); - void handleTypingLabel(Request& req, Response& resp); + ResponseTask *handleReceiveStatus(Request& req, Response& resp); void handleSendStatus(Request& req, Response& resp); void handleUnreadMsgs(Request& req, Response& resp); void getPlainText(const std::string& in, std::string &out, std::vector<Triple> &links); + // last parameter is only used for lobbies! + void locked_storeTypingInfo(const ChatId& chat_id, std::string status, RsGxsId lobby_gxs_id = RsGxsId()); StateTokenServer* mStateTokenServer; RsNotify* mNotify; @@ -128,6 +146,8 @@ private: std::map<ChatId, ChatInfo> mChatInfo; + std::map<ChatId, TypingLabelInfo> mTypingLabelInfo; + StateToken mLobbiesStateToken; std::vector<Lobby> mLobbies; diff --git a/libresapi/src/api/GxsResponseTask.cpp b/libresapi/src/api/GxsResponseTask.cpp index 581f38ba6..dcb4ebb51 100644 --- a/libresapi/src/api/GxsResponseTask.cpp +++ b/libresapi/src/api/GxsResponseTask.cpp @@ -62,6 +62,7 @@ bool GxsResponseTask::doWork(Request &req, Response &resp) { more = false; // pause when an id failed, to give the service time tim fetch the data ready = false; + // TODO: remove identities which failed many times from list, to avoid blocking when ids fail } } if(!ready) diff --git a/libresapi/src/api/GxsResponseTask.h b/libresapi/src/api/GxsResponseTask.h index 7e133cdb9..8200b3eee 100644 --- a/libresapi/src/api/GxsResponseTask.h +++ b/libresapi/src/api/GxsResponseTask.h @@ -15,7 +15,7 @@ class GxsResponseTask: public ResponseTask { public: // token service is allowed to be null if no token functions are wanted - GxsResponseTask(RsIdentity* id_service, RsTokenService* token_service); + GxsResponseTask(RsIdentity* id_service, RsTokenService* token_service = 0); virtual bool doWork(Request &req, Response& resp); protected: