diff --git a/libresapi/src/api/ApiServer.cpp b/libresapi/src/api/ApiServer.cpp index db642c020..db8b75d16 100644 --- a/libresapi/src/api/ApiServer.cpp +++ b/libresapi/src/api/ApiServer.cpp @@ -236,8 +236,8 @@ public: mForumHandler(ifaces.mGxsForums), mServiceControlHandler(ifaces.mServiceControl), mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles), - mFileSharingHandler(sts, ifaces.mFiles), - mTransfersHandler(sts, ifaces.mFiles, ifaces.mPeers), + mFileSharingHandler(sts, ifaces.mFiles, *ifaces.mNotify), + mTransfersHandler(sts, ifaces.mFiles, ifaces.mPeers, *ifaces.mNotify), mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler), mApiPluginHandler(sts, ifaces), mChannelsHandler(ifaces.mGxsChannels), diff --git a/libresapi/src/api/ChatHandler.cpp b/libresapi/src/api/ChatHandler.cpp index f77d45797..01d770cd1 100644 --- a/libresapi/src/api/ChatHandler.cpp +++ b/libresapi/src/api/ChatHandler.cpp @@ -45,6 +45,7 @@ StreamBase& operator << (StreamBase& left, ChatHandler::Msg& m) { left << makeKeyValueReference("incoming", m.incoming) << makeKeyValueReference("was_send", m.was_send) + << makeKeyValueReference("read", m.read) << makeKeyValueReference("author_id", m.author_id) << makeKeyValueReference("author_name", m.author_name) << makeKeyValueReference("msg", m.msg) @@ -112,6 +113,8 @@ StreamBase& operator << (StreamBase& left, ChatHandler::ChatInfo& info) { left << makeKeyValueReference("remote_author_id", info.remote_author_id) << makeKeyValueReference("remote_author_name", info.remote_author_name) + << makeKeyValueReference("own_author_id", info.own_author_id) + << makeKeyValueReference("own_author_name", info.own_author_name) << makeKeyValueReference("is_broadcast", info.is_broadcast) << makeKeyValueReference("is_distant_chat_id", info.is_distant_chat_id) << makeKeyValueReference("is_lobby", info.is_lobby) @@ -174,8 +177,13 @@ ChatHandler::ChatHandler(StateTokenServer *sts, RsNotify *notify, RsMsgs *msgs, addResourceHandler("get_invitations_to_lobby", this, &ChatHandler::handleGetInvitationsToLobby); addResourceHandler("answer_to_invitation", this, &ChatHandler::handleAnswerToInvitation); addResourceHandler("lobby_participants", this, &ChatHandler::handleLobbyParticipants); + addResourceHandler("get_default_identity_for_chat_lobby", this, &ChatHandler::handleGetDefaultIdentityForChatLobby); + addResourceHandler("set_default_identity_for_chat_lobby", this, &ChatHandler::handleSetDefaultIdentityForChatLobby); + addResourceHandler("get_identity_for_chat_lobby", this, &ChatHandler::handleGetIdentityForChatLobby); + addResourceHandler("set_identity_for_chat_lobby", this, &ChatHandler::handleSetIdentityForChatLobby); addResourceHandler("messages", this, &ChatHandler::handleMessages); - addResourceHandler("send_message", this, &ChatHandler::handleSendMessage); + addResourceHandler("send_message", this, &ChatHandler::handleSendMessage); + addResourceHandler("mark_message_as_read", this, &ChatHandler::handleMarkMessageAsRead); addResourceHandler("mark_chat_as_read", this, &ChatHandler::handleMarkChatAsRead); addResourceHandler("info", this, &ChatHandler::handleInfo); addResourceHandler("receive_status", this, &ChatHandler::handleReceiveStatus); @@ -194,13 +202,13 @@ ChatHandler::~ChatHandler() void ChatHandler::notifyChatMessage(const ChatMessage &msg) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mRawMsgs.push_back(msg); } void ChatHandler::notifyChatCleared(const ChatId &chat_id) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** //Remove processed messages std::list& msgs = mMsgs[chat_id]; msgs.clear(); @@ -219,14 +227,14 @@ void ChatHandler::notifyChatCleared(const ChatId &chat_id) void ChatHandler::notifyChatStatus(const ChatId &chat_id, const std::string &status) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + 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 **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** if(event_type == RS_CHAT_LOBBY_EVENT_PEER_STATUS) { locked_storeTypingInfo(ChatId(lobby_id), any_string, nickname); @@ -237,14 +245,14 @@ void ChatHandler::notifyListChange(int list, int /*type*/) { if(list == NOTIFY_LIST_CHAT_LOBBY_INVITATION) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->replaceToken(mInvitationsStateToken); } } void ChatHandler::tick() { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** // first fetch lobbies std::vector lobbies; @@ -429,16 +437,21 @@ void ChatHandler::tick() } else if(msg.chat_id.isDistantChatId()) { - RsIdentityDetails details; + RsIdentityDetails detailsRemoteIdentity; + RsIdentityDetails detailsOwnIdentity; DistantChatPeerInfo dcpinfo; if( !gxs_id_failed && rsMsgs->getDistantChatStatus( - msg.chat_id.toDistantChatId(), dcpinfo ) && - mRsIdentity->getIdDetails(dcpinfo.to_id, details) ) + msg.chat_id.toDistantChatId(), dcpinfo ) + && mRsIdentity->getIdDetails(dcpinfo.to_id, detailsRemoteIdentity) + && mRsIdentity->getIdDetails(dcpinfo.own_id, detailsOwnIdentity)) { - info.remote_author_id = details.mId.toStdString(); - info.remote_author_name = details.mNickname; + info.remote_author_id = detailsRemoteIdentity.mId.toStdString(); + info.remote_author_name = detailsRemoteIdentity.mNickname; + + info.own_author_id = detailsOwnIdentity.mId.toStdString(); + info.own_author_name = detailsOwnIdentity.mNickname; } else { @@ -862,7 +875,7 @@ void ChatHandler::locked_storeTypingInfo(const ChatId &chat_id, std::string stat void ChatHandler::handleWildcard(Request &/*req*/, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** resp.mDataStream.getStreamToMember(); for(std::map >::iterator mit = mMsgs.begin(); mit != mMsgs.end(); ++mit) { @@ -876,7 +889,7 @@ void ChatHandler::handleLobbies(Request &/*req*/, Response &resp) tick(); { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** resp.mDataStream.getStreamToMember(); for(std::vector::iterator vit = mLobbies.begin(); vit != mLobbies.end(); ++vit) { @@ -1015,7 +1028,7 @@ void ChatHandler::handleAnswerToInvitation(Request& req, Response& resp) ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** ChatId id(req.mPath.top()); if(!id.isLobbyId()) @@ -1032,6 +1045,82 @@ ResponseTask* ChatHandler::handleLobbyParticipants(Request &req, Response &resp) return new SendLobbyParticipantsTask(mRsIdentity, mit->second); } +void ChatHandler::handleGetDefaultIdentityForChatLobby(Request& req, Response& resp) +{ + RsGxsId gxsId; + mRsMsgs->getDefaultIdentityForChatLobby(gxsId); + resp.mDataStream << makeKeyValue("gxs_id", gxsId.toStdString()); + resp.setOk(); +} + +void ChatHandler::handleSetDefaultIdentityForChatLobby(Request& req, Response& resp) +{ + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + RsGxsId gxsId(gxs_id); + + if(gxsId.isNull()) + { + resp.setFail("Error: gxs_id must not be null"); + return; + } + + if(mRsMsgs->setDefaultIdentityForChatLobby(gxsId)) + resp.setOk(); + else + resp.setFail("Failure to change default identity for chat lobby"); +} + +void ChatHandler::handleGetIdentityForChatLobby(Request& req, Response& resp) +{ + RsGxsId gxsId; + std::string chat_id; + req.mStream << makeKeyValueReference("chat_id", chat_id); + ChatId chatId(chat_id); + + if(chatId.isNotSet()) + { + resp.setFail("Error: chat_id must not be null"); + return; + } + + if(mRsMsgs->getIdentityForChatLobby(chatId.toLobbyId(), gxsId)) + { + resp.mDataStream << makeKeyValue("gxs_id", gxsId.toStdString()); + resp.setOk(); + } + else + resp.setFail(); +} + +void ChatHandler::handleSetIdentityForChatLobby(Request& req, Response& resp) +{ + std::string chat_id; + req.mStream << makeKeyValueReference("chat_id", chat_id); + ChatId chatId(chat_id); + + if(chatId.isNotSet()) + { + resp.setFail("Error: chat_id must not be null"); + return; + } + + std::string gxs_id; + req.mStream << makeKeyValueReference("gxs_id", gxs_id); + RsGxsId gxsId(gxs_id); + + if(gxsId.isNull()) + { + resp.setFail("Error: gxs_id must not be null"); + return; + } + + if(mRsMsgs->setIdentityForChatLobby(chatId.toLobbyId(), gxsId)) + resp.setOk(); + else + resp.setFail(); +} + void ChatHandler::handleMessages(Request &req, Response &resp) { /* G10h4ck: Whithout this the request processing won't happen, copied from @@ -1040,7 +1129,7 @@ void ChatHandler::handleMessages(Request &req, Response &resp) tick(); { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** ChatId id(req.mPath.top()); // make response a list @@ -1082,9 +1171,47 @@ void ChatHandler::handleSendMessage(Request &req, Response &resp) resp.setFail("failed to send message"); } +void ChatHandler::handleMarkMessageAsRead(Request &req, Response &resp) +{ + std::string chat_id_string; + std::string msg_id; + req.mStream << makeKeyValueReference("chat_id", chat_id_string) + << makeKeyValueReference("msg_id", msg_id); + + ChatId chatId(chat_id_string); + if(chatId.isNotSet()) + { + resp.setFail(chat_id_string + " is not a valid chat id"); + return; + } + + std::map >::iterator mit = mMsgs.find(chatId); + if(mit == mMsgs.end()) + { + resp.setFail("chat not found. Maybe this chat does not have messages yet?"); + return; + } + + std::list& msgs = mit->second; + for(std::list::iterator lit = msgs.begin(); lit != msgs.end(); ++lit) + { + if(id((*lit)) == msg_id) + (*lit).read = true; + } + + // lobby list contains unread msgs, so update it + if(chatId.isLobbyId()) + mStateTokenServer->replaceToken(mLobbiesStateToken); + if(chatId.isPeerId() && mUnreadMsgNotify) + mUnreadMsgNotify->notifyUnreadMsgCountChanged(chatId.toPeerId(), 0); + + mStateTokenServer->replaceToken(mMsgStateToken); + mStateTokenServer->replaceToken(mUnreadMsgsStateToken); +} + void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** ChatId id(req.mPath.top()); if(id.isNotSet()) @@ -1109,12 +1236,13 @@ void ChatHandler::handleMarkChatAsRead(Request &req, Response &resp) if(id.isPeerId() && mUnreadMsgNotify) mUnreadMsgNotify->notifyUnreadMsgCountChanged(id.toPeerId(), 0); + mStateTokenServer->replaceToken(mMsgStateToken); mStateTokenServer->replaceToken(mUnreadMsgsStateToken); } void ChatHandler::handleInfo(Request &req, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** ChatId id(req.mPath.top()); if(id.isNotSet()) { @@ -1150,7 +1278,8 @@ protected: // lobby and distant require to fetch a gxs_id if(mId.isLobbyId()) { - requestGxsId(mInfo.author_id); + if(!mInfo.author_id.isNull()) + requestGxsId(mInfo.author_id); } else if(mId.isDistantChatId()) { @@ -1163,6 +1292,7 @@ protected: else { std::string name = "BUG: case not handled in SendTypingLabelInfo"; + RsGxsId author_id = mInfo.author_id; if(mId.isPeerId()) { name = mPeers->getPeerName(mId.toPeerId()); @@ -1172,6 +1302,7 @@ protected: DistantChatPeerInfo dcpinfo ; rsMsgs->getDistantChatStatus(mId.toDistantChatId(), dcpinfo); name = getName(dcpinfo.to_id); + author_id = dcpinfo.to_id; } else if(mId.isLobbyId()) { @@ -1183,6 +1314,7 @@ protected: } uint32_t ts = mInfo.timestamp; resp.mDataStream << makeKeyValueReference("author_name", name) + << makeKeyValue("author_id", author_id.toStdString()) << makeKeyValueReference("timestamp", ts) << makeKeyValueReference("status_string", mInfo.status); resp.mStateToken = mInfo.state_token; @@ -1194,7 +1326,7 @@ protected: ResponseTask* ChatHandler::handleReceiveStatus(Request &req, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** ChatId id(req.mPath.top()); if(id.isNotSet()) { @@ -1207,6 +1339,7 @@ ResponseTask* ChatHandler::handleReceiveStatus(Request &req, Response &resp) locked_storeTypingInfo(id, ""); mit = mTypingLabelInfo.find(id); } + return new SendTypingLabelInfo(mRsIdentity, mRsPeers, id, mit->second); } @@ -1228,7 +1361,7 @@ void ChatHandler::handleSendStatus(Request &req, Response &resp) void ChatHandler::handleUnreadMsgs(Request &/*req*/, Response &resp) { - RS_STACK_MUTEX(mMtx); /********** LOCKED **********/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** resp.mDataStream.getStreamToMember(); for( std::map >::const_iterator mit = mMsgs.begin(); @@ -1309,10 +1442,12 @@ void ChatHandler::handleCloseDistantChatConnexion(Request& req, Response& resp) { std::string distant_chat_hex; req.mStream << makeKeyValueReference("distant_chat_hex", distant_chat_hex); + ChatId chatId(distant_chat_hex); - DistantChatPeerId chat_id(distant_chat_hex); - if (mRsMsgs->closeDistantChatConnexion(chat_id)) resp.setOk(); - else resp.setFail("Failed to close distant chat"); + if (mRsMsgs->closeDistantChatConnexion(chatId.toDistantChatId())) + resp.setOk(); + else + resp.setFail("Failed to close distant chat"); } void ChatHandler::handleCreateLobby(Request& req, Response& resp) diff --git a/libresapi/src/api/ChatHandler.h b/libresapi/src/api/ChatHandler.h index cac28271d..4d6104592 100644 --- a/libresapi/src/api/ChatHandler.h +++ b/libresapi/src/api/ChatHandler.h @@ -104,6 +104,8 @@ public: bool is_distant_chat_id; bool is_lobby; bool is_peer; + std::string own_author_id; + std::string own_author_name; std::string remote_author_id; std::string remote_author_name; }; @@ -129,8 +131,13 @@ private: void handleAnswerToInvitation(Request& req, Response& resp); void handleClearLobby(Request& req, Response& resp); ResponseTask* handleLobbyParticipants(Request& req, Response& resp); + void handleGetDefaultIdentityForChatLobby(Request& req, Response& resp); + void handleSetDefaultIdentityForChatLobby(Request& req, Response& resp); + void handleGetIdentityForChatLobby(Request& req, Response& resp); + void handleSetIdentityForChatLobby(Request& req, Response& resp); void handleMessages(Request& req, Response& resp); - void handleSendMessage(Request& req, Response& resp); + void handleSendMessage(Request& req, Response& resp); + void handleMarkMessageAsRead(Request& req, Response& resp); void handleMarkChatAsRead(Request& req, Response& resp); void handleInfo(Request& req, Response& resp); ResponseTask *handleReceiveStatus(Request& req, Response& resp); diff --git a/libresapi/src/api/FileSearchHandler.cpp b/libresapi/src/api/FileSearchHandler.cpp index 5d3d2a86d..0382005df 100644 --- a/libresapi/src/api/FileSearchHandler.cpp +++ b/libresapi/src/api/FileSearchHandler.cpp @@ -31,7 +31,7 @@ FileSearchHandler::~FileSearchHandler() void FileSearchHandler::notifyTurtleSearchResult(uint32_t search_id, const std::list& files) { - RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX ********** + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** std::map::iterator mit = mSearches.find(search_id); if(mit == mSearches.end()) return; @@ -85,7 +85,7 @@ void FileSearchHandler::handleWildcard(Request &req, Response &resp) } { - RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX ********** + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** std::map::iterator mit = mSearches.find(id); if(mit == mSearches.end()) { @@ -115,7 +115,7 @@ void FileSearchHandler::handleWildcard(Request &req, Response &resp) else { // list searches - RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX ********** + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** resp.mDataStream.getStreamToMember(); for(std::map::iterator mit = mSearches.begin(); mit != mSearches.end(); ++mit) { @@ -221,7 +221,7 @@ void FileSearchHandler::handleCreateSearch(Request &req, Response &resp) } { - RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX ********** + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** Search& search = mSearches[search_id]; search.mStateToken = mStateTokenServer->getNewToken(); @@ -262,7 +262,7 @@ void FileSearchHandler::handleGetSearchResult(Request& req, Response& resp) } { - RsStackMutex stackMtx(mMtx); // ********** STACK LOCKED MTX ********** + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** std::map::iterator mit = mSearches.find(id); if(mit == mSearches.end()) { diff --git a/libresapi/src/api/FileSharingHandler.cpp b/libresapi/src/api/FileSharingHandler.cpp index d948a9511..b8645ec2a 100644 --- a/libresapi/src/api/FileSharingHandler.cpp +++ b/libresapi/src/api/FileSharingHandler.cpp @@ -21,8 +21,10 @@ namespace resource_api { -FileSharingHandler::FileSharingHandler(StateTokenServer *sts, RsFiles *files): - mStateTokenServer(sts), mRsFiles(files) +FileSharingHandler::FileSharingHandler(StateTokenServer *sts, RsFiles *files, + RsNotify& notify): + mStateTokenServer(sts), mRsFiles(files), mNotify(notify), + mMtx("FileSharingHandler Mtx") { addResourceHandler("*", this, &FileSharingHandler::handleWildcard); addResourceHandler("force_check", this, &FileSharingHandler::handleForceCheck); @@ -40,7 +42,30 @@ FileSharingHandler::FileSharingHandler(StateTokenServer *sts, RsFiles *files): addResourceHandler("download", this, &FileSharingHandler::handleDownload); - mStateToken = mStateTokenServer->getNewToken(); + mLocalDirStateToken = mStateTokenServer->getNewToken(); + mRemoteDirStateToken = mStateTokenServer->getNewToken(); + mNotify.registerNotifyClient(this); +} + +FileSharingHandler::~FileSharingHandler() +{ + mNotify.unregisterNotifyClient(this); +} + +void FileSharingHandler::notifyListChange(int list, int /* type */) +{ + if(list == NOTIFY_LIST_DIRLIST_LOCAL) + { + RS_STACK_MUTEX(mMtx); + mStateTokenServer->discardToken(mLocalDirStateToken); + mLocalDirStateToken = mStateTokenServer->getNewToken(); + } + else if(list == NOTIFY_LIST_DIRLIST_FRIENDS) + { + RS_STACK_MUTEX(mMtx); + mStateTokenServer->discardToken(mRemoteDirStateToken); + mRemoteDirStateToken = mStateTokenServer->getNewToken(); + } } void FileSharingHandler::handleWildcard(Request & /*req*/, Response & /*resp*/) @@ -104,6 +129,7 @@ void FileSharingHandler::handleGetSharedDir(Request& req, Response& resp) << makeKeyValue("name", dirDetails.name) << makeKeyValue("path", dirDetails.path) << makeKeyValue("hash", dirDetails.hash.toStdString()) + << makeKeyValue("peer_id", dirDetails.id.toStdString()) << makeKeyValue("parent_reference", *reinterpret_cast(&dirDetails.parent)) << makeKeyValue("reference", *reinterpret_cast(&dirDetails.ref)) << makeKeyValue("count", static_cast(dirDetails.count)) @@ -140,6 +166,8 @@ void FileSharingHandler::handleGetSharedDir(Request& req, Response& resp) << makeKeyValueReference("contain_folders", contain_folders); } } + + resp.mStateToken = mLocalDirStateToken; } void FileSharingHandler::handleSetSharedDir(Request& req, Response& resp) @@ -231,10 +259,16 @@ void FileSharingHandler::handleGetDirectoryParent(Request& req, Response& resp) FileSearchFlags flags; if(remote) + { flags |= RS_FILE_HINTS_REMOTE; + resp.mStateToken = mRemoteDirStateToken; + } if(local) + { flags |= RS_FILE_HINTS_LOCAL; + resp.mStateToken = mLocalDirStateToken; + } DirDetails dirDetails; mRsFiles->RequestDirDetails(ref, dirDetails, flags); @@ -282,6 +316,7 @@ void FileSharingHandler::handleGetDirectoryParent(Request& req, Response& resp) << makeKeyValue("name", dirDetails.name) << makeKeyValue("path", dirDetails.path) << makeKeyValue("hash", dirDetails.hash.toStdString()) + << makeKeyValue("peer_id", dirDetails.id.toStdString()) << makeKeyValue("parent_reference", *reinterpret_cast(&dirDetails.parent)) << makeKeyValue("reference", *reinterpret_cast(&dirDetails.ref)) << makeKeyValue("count", static_cast(dirDetails.count)) @@ -334,10 +369,16 @@ void FileSharingHandler::handleGetDirectoryChilds(Request& req, Response& resp) FileSearchFlags flags; if(remote) + { flags |= RS_FILE_HINTS_REMOTE; + resp.mStateToken = mRemoteDirStateToken; + } if(local) + { flags |= RS_FILE_HINTS_LOCAL; + resp.mStateToken = mLocalDirStateToken; + } DirDetails dirDetails; mRsFiles->RequestDirDetails(ref, dirDetails, flags); @@ -385,6 +426,7 @@ void FileSharingHandler::handleGetDirectoryChilds(Request& req, Response& resp) << makeKeyValue("name", dirDetails.name) << makeKeyValue("path", dirDetails.path) << makeKeyValue("hash", dirDetails.hash.toStdString()) + << makeKeyValue("peer_id", dirDetails.id.toStdString()) << makeKeyValue("parent_reference", *reinterpret_cast(&dirDetails.parent)) << makeKeyValue("reference", *reinterpret_cast(&dirDetails.ref)) << makeKeyValue("count", static_cast(dirDetails.count)) diff --git a/libresapi/src/api/FileSharingHandler.h b/libresapi/src/api/FileSharingHandler.h index 8b741e80d..0eb67764e 100644 --- a/libresapi/src/api/FileSharingHandler.h +++ b/libresapi/src/api/FileSharingHandler.h @@ -22,14 +22,23 @@ #include "StateTokenServer.h" #include +#include +#include namespace resource_api { -class FileSharingHandler: public ResourceRouter +class FileSharingHandler: public ResourceRouter, NotifyClient { public: - FileSharingHandler(StateTokenServer* sts, RsFiles* files); + FileSharingHandler(StateTokenServer* sts, RsFiles* files, RsNotify& notify); + ~FileSharingHandler(); + + /** + Derived from NotifyClient + This function may be called from foreign thread + */ + virtual void notifyListChange(int list, int type); private: void handleWildcard(Request& req, Response& resp); @@ -48,10 +57,22 @@ private: void handleDownload(Request& req, Response& resp); - StateToken mStateToken; + /// Token indicating change in local shared files + StateToken mLocalDirStateToken; + + /// Token indicating change in remote (friends') shared files + StateToken mRemoteDirStateToken; + StateTokenServer* mStateTokenServer; + /** + Protects mLocalDirStateToken and mRemoteDirStateToken that may be changed in foreign thread + @see FileSharingHandler::notifyListChange(...) + */ + RsMutex mMtx; + RsFiles* mRsFiles; + RsNotify& mNotify; }; } // namespace resource_api diff --git a/libresapi/src/api/IdentityHandler.cpp b/libresapi/src/api/IdentityHandler.cpp index 8d132dd85..ff5e50a1e 100644 --- a/libresapi/src/api/IdentityHandler.cpp +++ b/libresapi/src/api/IdentityHandler.cpp @@ -374,7 +374,7 @@ void IdentityHandler::handleAddContact(Request& req, Response& resp) mRsIdentity->setAsRegularContact(RsGxsId(gxs_id), true); { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->replaceToken(mStateToken); } @@ -389,7 +389,7 @@ void IdentityHandler::handleRemoveContact(Request& req, Response& resp) mRsIdentity->setAsRegularContact(RsGxsId(gxs_id), false); { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->replaceToken(mStateToken); } diff --git a/libresapi/src/api/PeersHandler.cpp b/libresapi/src/api/PeersHandler.cpp index e0792e355..66def7eab 100644 --- a/libresapi/src/api/PeersHandler.cpp +++ b/libresapi/src/api/PeersHandler.cpp @@ -250,6 +250,7 @@ PeersHandler::PeersHandler( StateTokenServer* sts, RsNotify* notify, addResourceHandler("set_network_options", this, &PeersHandler::handleSetNetworkOptions); addResourceHandler("get_pgp_options", this, &PeersHandler::handleGetPGPOptions); addResourceHandler("set_pgp_options", this, &PeersHandler::handleSetPGPOptions); + addResourceHandler("get_node_name", this, &PeersHandler::handleGetNodeName); addResourceHandler("get_node_options", this, &PeersHandler::handleGetNodeOptions); addResourceHandler("set_node_options", this, &PeersHandler::handleSetNodeOptions); addResourceHandler("examine_cert", this, &PeersHandler::handleExamineCert); @@ -266,9 +267,9 @@ PeersHandler::~PeersHandler() void PeersHandler::notifyListChange(int list, int /* type */) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ if(list == NOTIFY_LIST_FRIENDS) { + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->discardToken(mStateToken); mStateToken = mStateTokenServer->getNewToken(); } @@ -276,13 +277,13 @@ void PeersHandler::notifyListChange(int list, int /* type */) void PeersHandler::notifyPeerStatusChanged(const std::string& /*peer_id*/, uint32_t /*state*/) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->replaceToken(mStateToken); } void PeersHandler::notifyPeerHasNewAvatar(std::string /*peer_id*/) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->replaceToken(mStateToken); } @@ -294,7 +295,7 @@ void PeersHandler::tick() { mOnlinePeers = online; - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->discardToken(mStateToken); mStateToken = mStateTokenServer->getNewToken(); } @@ -305,7 +306,7 @@ void PeersHandler::tick() { status = statusInfo.status; - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->discardToken(mStringStateToken); mStringStateToken = mStateTokenServer->getNewToken(); } @@ -315,7 +316,7 @@ void PeersHandler::tick() { custom_state_string = custom_state; - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mStateTokenServer->discardToken(mCustomStateToken); mCustomStateToken = mStateTokenServer->getNewToken(); } @@ -323,7 +324,7 @@ void PeersHandler::tick() void PeersHandler::notifyUnreadMsgCountChanged(const RsPeerId &peer, uint32_t count) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** mUnreadMsgsCounts[peer] = count; mStateTokenServer->replaceToken(mStateToken); } @@ -459,7 +460,7 @@ void PeersHandler::handleWildcard(Request &req, Response &resp) { std::map unread_msgs; { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** unread_msgs = mUnreadMsgsCounts; } std::list statusInfo; @@ -1139,6 +1140,28 @@ void PeersHandler::handleSetPGPOptions(Request& req, Response& resp) resp.setOk(); } +void PeersHandler::handleGetNodeName(Request& req, Response& resp) +{ + std::string peer_id; + req.mStream << makeKeyValueReference("peer_id", peer_id); + + RsPeerId peerId(peer_id); + RsPeerDetails detail; + if(!mRsPeers->getPeerDetails(peerId, detail)) + { + resp.setFail(); + return; + } + + resp.mDataStream << makeKeyValue("peer_id", detail.id.toStdString()); + resp.mDataStream << makeKeyValue("name", detail.name); + resp.mDataStream << makeKeyValue("location", detail.location); + resp.mDataStream << makeKeyValue("pgp_id", detail.gpg_id.toStdString()); + resp.mDataStream << makeKeyValue("last_contact", detail.lastConnect); + + resp.setOk(); +} + void PeersHandler::handleGetNodeOptions(Request& req, Response& resp) { std::string peer_id; @@ -1258,7 +1281,7 @@ void PeersHandler::handleSetNodeOptions(Request& req, Response& resp) StateToken PeersHandler::getCurrentStateToken() { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** if(mStateToken.isNull()) mStateToken = mStateTokenServer->getNewToken(); return mStateToken; diff --git a/libresapi/src/api/PeersHandler.h b/libresapi/src/api/PeersHandler.h index b34e4db8a..d15705602 100644 --- a/libresapi/src/api/PeersHandler.h +++ b/libresapi/src/api/PeersHandler.h @@ -70,6 +70,7 @@ private: void handleGetPGPOptions(Request& req, Response& resp); void handleSetPGPOptions(Request& req, Response& resp); + void handleGetNodeName(Request& req, Response& resp); void handleGetNodeOptions(Request& req, Response& resp); void handleSetNodeOptions(Request& req, Response& resp); diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index 1e7f19b38..ebeadf986 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -57,7 +57,7 @@ RsControlModule::~RsControlModule() bool RsControlModule::processShouldExit() { - RsStackMutex stack(mExitFlagMtx); + RS_STACK_MUTEX(mExitFlagMtx); // ********** LOCKED ********** return mProcessShouldExit; } @@ -158,7 +158,7 @@ void RsControlModule::run() std::cerr << "RsControlModule::run() reseting passwd." << std::endl; #endif { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mPassword = ""; } @@ -182,7 +182,7 @@ void RsControlModule::run() std::cerr << "RsControlModule::run() while(wait_for_account_select) mLoadPeerId=" << mLoadPeerId << std::endl; #endif usleep(500*1000); - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** if(!mLoadPeerId.isNull()) { @@ -238,7 +238,7 @@ void RsControlModule::run() #endif { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mLoadPeerId.clear(); } } @@ -247,7 +247,7 @@ void RsControlModule::run() #endif { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mFixedPassword = mPassword; std::cerr << "***Reseting mPasswd " << std::endl; @@ -279,7 +279,7 @@ void RsControlModule::run() void RsControlModule::handleRunState(Request &, Response &resp) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** std::string state; switch(mRunState) { @@ -311,7 +311,7 @@ void RsControlModule::handleRunState(Request &, Response &resp) void RsControlModule::handleIdentities(Request &, Response &resp) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** if(mRunState == WAITING_INIT || mRunState == FATAL_ERROR) { resp.setFail("Retroshare is not initialised. Operation not possible."); @@ -337,7 +337,7 @@ void RsControlModule::handleIdentities(Request &, Response &resp) void RsControlModule::handleLocations(Request &, Response &resp) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** if(mRunState == WAITING_INIT || mRunState == FATAL_ERROR) { resp.setFail("Retroshare is not initialised. Operation not possible."); @@ -370,7 +370,7 @@ void RsControlModule::handleLocations(Request &, Response &resp) void RsControlModule::handlePassword(Request &req, Response &resp) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** std::string passwd; req.mStream << makeKeyValueReference("password", passwd); if(passwd != "")// && mWantPassword) @@ -398,7 +398,7 @@ void RsControlModule::handlePassword(Request &req, Response &resp) void RsControlModule::handleLogin(Request &req, Response &resp) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** if(mRunState != WAITING_ACCOUNT_SELECT) { resp.setFail("Operation not allowed in this runstate. Login is only allowed rigth after initialisation."); @@ -411,7 +411,7 @@ void RsControlModule::handleLogin(Request &req, Response &resp) void RsControlModule::handleShutdown(Request &, Response &resp) { - RsStackMutex stack(mExitFlagMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mExitFlagMtx); // ********** LOCKED ********** mProcessShouldExit = true; resp.setOk(); } @@ -514,7 +514,7 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp) std::string err_string; // give the password to the password callback { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mPassword = pgp_password; mFixedPassword = pgp_password; } @@ -522,7 +522,7 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp) // clear fixed password to restore normal password operation // { -// RsStackMutex stack(mDataMtx); // ********** LOCKED ********** +// RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** // mFixedPassword = ""; // } @@ -532,7 +532,7 @@ void RsControlModule::handleCreateLocation(Request &req, Response &resp) RsInit::LoadPassword(ssl_password); // trigger login in init thread { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mLoadPeerId = ssl_id; } resp.mDataStream << makeKeyValueReference("pgp_id", pgp_id) @@ -561,7 +561,7 @@ bool RsControlModule::askForDeferredSelfSignature(const void *data, const uint32 void RsControlModule::setRunState(RunState s, std::string errstr) { - RsStackMutex stack(mDataMtx); // ********** LOCKED ********** + RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** mRunState = s; mLastErrorString = errstr; mStateTokenServer->replaceToken(mStateToken); diff --git a/libresapi/src/api/StateTokenServer.cpp b/libresapi/src/api/StateTokenServer.cpp index b3c785bc6..6c113cdae 100644 --- a/libresapi/src/api/StateTokenServer.cpp +++ b/libresapi/src/api/StateTokenServer.cpp @@ -64,19 +64,19 @@ StateTokenServer::StateTokenServer(): StateToken StateTokenServer::getNewToken() { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** return locked_getNewToken(); } void StateTokenServer::discardToken(StateToken token) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** locked_discardToken(token); } void StateTokenServer::replaceToken(StateToken &token) { - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** locked_discardToken(token); token = locked_getNewToken(); } @@ -89,13 +89,13 @@ void StateTokenServer::registerTickClient(Tickable *c) // avoid double registration unregisterTickClient(c); - RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ + RS_STACK_MUTEX(mClientsMtx); // ********** LOCKED ********** mTickClients.push_back(c); } void StateTokenServer::unregisterTickClient(Tickable *c) { - RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ + RS_STACK_MUTEX(mClientsMtx); // ********** LOCKED ********** std::vector::iterator vit = std::find(mTickClients.begin(), mTickClients.end(), c); if(vit != mTickClients.end()) mTickClients.erase(vit); @@ -104,14 +104,14 @@ void StateTokenServer::unregisterTickClient(Tickable *c) void StateTokenServer::handleWildcard(Request &req, Response &resp) { { - RsStackMutex stack(mClientsMtx); /********** STACK LOCKED MTX ***********/ + RS_STACK_MUTEX(mClientsMtx); // ********** LOCKED ********** for(std::vector::iterator vit = mTickClients.begin(); vit != mTickClients.end(); ++vit) { (*vit)->tick(); } } - RsStackMutex stack(mMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** // want to lookpup many tokens at once, return a list of invalid tokens // TODO: make generic list serialiser/deserialiser resp.mDataStream.getStreamToMember(); diff --git a/libresapi/src/api/TransfersHandler.cpp b/libresapi/src/api/TransfersHandler.cpp index 5b6f43789..39e9c5875 100644 --- a/libresapi/src/api/TransfersHandler.cpp +++ b/libresapi/src/api/TransfersHandler.cpp @@ -6,8 +6,10 @@ namespace resource_api { -TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files, RsPeers *peers): - mStateTokenServer(sts), mFiles(files), mRsPeers(peers), mLastUpdateTS(0) +TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files, RsPeers *peers, + RsNotify& notify): + mStateTokenServer(sts), mFiles(files), mRsPeers(peers), mLastUpdateTS(0), mNotify(notify), + mMtx("TransfersHandler") { addResourceHandler("*", this, &TransfersHandler::handleWildcard); addResourceHandler("downloads", this, &TransfersHandler::handleDownloads); @@ -15,11 +17,23 @@ TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files, RsPeer addResourceHandler("control_download", this, &TransfersHandler::handleControlDownload); mStateToken = mStateTokenServer->getNewToken(); mStateTokenServer->registerTickClient(this); + mNotify.registerNotifyClient(this); } TransfersHandler::~TransfersHandler() { mStateTokenServer->unregisterTickClient(this); + mNotify.unregisterNotifyClient(this); +} + +void TransfersHandler::notifyListChange(int list, int /* type */) +{ + if(list == NOTIFY_LIST_TRANSFERLIST) + { + RS_STACK_MUTEX(mMtx); // ********** LOCKED ********** + mStateTokenServer->discardToken(mStateToken); + mStateToken = mStateTokenServer->getNewToken(); + } } const int UPDATE_PERIOD_SECONDS = 5; diff --git a/libresapi/src/api/TransfersHandler.h b/libresapi/src/api/TransfersHandler.h index 0c53f2cd7..7d07a7198 100644 --- a/libresapi/src/api/TransfersHandler.h +++ b/libresapi/src/api/TransfersHandler.h @@ -5,18 +5,26 @@ #include #include +#include namespace resource_api { -class TransfersHandler: public ResourceRouter, Tickable +class TransfersHandler: public ResourceRouter, Tickable, NotifyClient { public: - TransfersHandler(StateTokenServer* sts, RsFiles* files, RsPeers *peers); + TransfersHandler(StateTokenServer* sts, RsFiles* files, RsPeers *peers, RsNotify& notify); virtual ~TransfersHandler(); + /** + Derived from NotifyClient + This function may be called from foreign thread + */ + virtual void notifyListChange(int list, int type); + // from Tickable virtual void tick(); + private: void handleWildcard(Request& req, Response& resp); void handleControlDownload(Request& req, Response& resp); @@ -26,6 +34,13 @@ private: StateTokenServer* mStateTokenServer; RsFiles* mFiles; RsPeers* mRsPeers; + RsNotify& mNotify; + + /** + Protects mStateToken that may be changed in foreign thread + @see TransfersHandler::notifyListChange(...) + */ + RsMutex mMtx; StateToken mStateToken; time_t mLastUpdateTS;