From 8fd22c8fd16520b237a81d5d48a67aa852190cee Mon Sep 17 00:00:00 2001 From: Gioacchino Mazzurco Date: Mon, 29 Oct 2018 05:50:11 +0100 Subject: [PATCH] Safer rsGxsChannel API Protect data members with mutexes Print messages when errors happens --- libretroshare/src/gxs/gxstokenqueue.cc | 33 +-- libretroshare/src/gxs/gxstokenqueue.h | 2 +- libretroshare/src/gxs/rsgenexchange.cc | 2 +- libretroshare/src/gxs/rsgxsdataaccess.cc | 41 ++- libretroshare/src/retroshare/rsgxschannels.h | 23 +- libretroshare/src/services/p3gxschannels.cc | 275 ++++++++++--------- libretroshare/src/services/p3gxschannels.h | 24 +- 7 files changed, 204 insertions(+), 196 deletions(-) diff --git a/libretroshare/src/gxs/gxstokenqueue.cc b/libretroshare/src/gxs/gxstokenqueue.cc index c5ebf87fd..c9eb8ef92 100644 --- a/libretroshare/src/gxs/gxstokenqueue.cc +++ b/libretroshare/src/gxs/gxstokenqueue.cc @@ -36,20 +36,17 @@ bool GxsTokenQueue::queueRequest(uint32_t token, uint32_t req_type) void GxsTokenQueue::checkRequests() { { - RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/ - if (mQueue.empty()) - { - return; - } + RS_STACK_MUTEX(mQueueMtx); + if (mQueue.empty()) return; } // Must check all, and move to a different list - for reentrant / good mutex behaviour. std::list toload; std::list::iterator it; - bool stuffToLoad = false; + { - RsStackMutex stack(mQueueMtx); /********** STACK LOCKED MTX ******/ + RS_STACK_MUTEX(mQueueMtx); for(it = mQueue.begin(); it != mQueue.end();) { uint32_t token = it->mToken; @@ -62,29 +59,29 @@ void GxsTokenQueue::checkRequests() stuffToLoad = true; #ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token << " Complete"; - std::cerr << std::endl; + std::cerr << "GxsTokenQueue::checkRequests() token: " << token + << " Complete" << std::endl; #endif ++it; } else if (status == RsTokenService::FAILED) { // maybe we should do alternative callback? - std::cerr << "GxsTokenQueue::checkRequests() ERROR Request Failed: " << token; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " ERROR Request Failed! " + << " token: " << token << std::endl; it = mQueue.erase(it); } else { #ifdef GXS_DEBUG - std::cerr << "GxsTokenQueue::checkRequests() token: " << token << " is unfinished, status: " << status; - std::cerr << std::endl; + std::cerr << "GxsTokenQueue::checkRequests() token: " << token + << " is unfinished, status: " << status << std::endl; #endif ++it; } } - } + } // RS_STACK_MUTEX(mQueueMtx) END if (stuffToLoad) { @@ -95,11 +92,3 @@ void GxsTokenQueue::checkRequests() } } - // This must be overloaded to complete the functionality. -void GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type) -{ - std::cerr << "GxsTokenQueue::handleResponse(" << token << "," << req_type << ") ERROR: NOT HANDLED"; - std::cerr << std::endl; -} - - diff --git a/libretroshare/src/gxs/gxstokenqueue.h b/libretroshare/src/gxs/gxstokenqueue.h index 0b58f7c3d..c6c32262e 100644 --- a/libretroshare/src/gxs/gxstokenqueue.h +++ b/libretroshare/src/gxs/gxstokenqueue.h @@ -54,7 +54,7 @@ public: protected: /// This must be overloaded to complete the functionality. - virtual void handleResponse(uint32_t token, uint32_t req_type); + virtual void handleResponse(uint32_t token, uint32_t req_type) = 0; private: RsGenExchange *mGenExchange; diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index 1ffaf793a..183751356 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -1925,7 +1925,7 @@ void RsGenExchange::setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grp void RsGenExchange::setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString) { - RS_STACK_MUTEX(mGenMtx) ; + RS_STACK_MUTEX(mGenMtx); token = mDataAccess->generatePublicToken(); GrpLocMetaData g; diff --git a/libretroshare/src/gxs/rsgxsdataaccess.cc b/libretroshare/src/gxs/rsgxsdataaccess.cc index a72123f92..a945829f7 100644 --- a/libretroshare/src/gxs/rsgxsdataaccess.cc +++ b/libretroshare/src/gxs/rsgxsdataaccess.cc @@ -39,14 +39,16 @@ RsGxsDataAccess::~RsGxsDataAccess() for(std::map::const_iterator it(mRequests.begin());it!=mRequests.end();++it) delete it->second ; } -bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, - const std::list &groupIds) +bool RsGxsDataAccess::requestGroupInfo( + uint32_t &token, uint32_t ansType, const RsTokReqOptions &opts, + const std::list &groupIds ) { - if(groupIds.empty()) - { - std::cerr << "(WW) Group Id list is empty" << std::endl; - return false; - } + if(groupIds.empty()) + { + std::cerr << __PRETTY_FUNCTION__ << " (WW) Group Id list is empty!" + << std::endl; + return false; + } GxsRequest* req = NULL; uint32_t reqType = opts.mReqType; @@ -76,19 +78,19 @@ bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const req = gir; } - if(req == NULL) - { - std::cerr << "RsGxsDataAccess::requestGroupInfo() request type not recognised, type " - << reqType << std::endl; - return false; - }else - { - generateToken(token); + if(!req) + { + std::cerr << __PRETTY_FUNCTION__ << " request type not recognised, " + << "reqType: " << reqType << std::endl; + return false; + } + + generateToken(token); #ifdef DATA_DEBUG - std::cerr << "RsGxsDataAccess::requestGroupInfo() gets Token: " << token << std::endl; + std::cerr << "RsGxsDataAccess::requestGroupInfo() gets token: " << token + << std::endl; #endif - } setReq(req, token, ansType, opts); storeRequest(req); @@ -130,11 +132,8 @@ bool RsGxsDataAccess::requestGroupInfo(uint32_t &token, uint32_t ansType, const void RsGxsDataAccess::generateToken(uint32_t &token) { - RsStackMutex stack(mDataMutex); /****** LOCKED *****/ - + RS_STACK_MUTEX(mDataMutex); token = mNextToken++; - - return; } diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h index cc95cf0bd..4f81f7a96 100644 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ b/libretroshare/src/retroshare/rsgxschannels.h @@ -153,6 +153,16 @@ public: */ virtual bool createPost(RsGxsChannelPost& post) = 0; + /** + * @brief Subscrbe to a channel. Blocking API + * @jsonapi{development} + * @param[in] channelId Channel id + * @param[in] subscribe true to subscribe, false to unsubscribe + * @return false on error, true otherwise + */ + virtual bool subscribeToChannel( const RsGxsGroupId &channelId, + bool subscribe ) = 0; + /* Specific Service Data * TODO: change the orrible const uint32_t &token to uint32_t token @@ -174,24 +184,24 @@ public: uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0; /** - * @brief Enable or disable auto-download for given channel + * @brief Enable or disable auto-download for given channel. Blocking API * @jsonapi{development} - * @param[in] groupId channel id + * @param[in] channelId channel id * @param[in] enable true to enable, false to disable * @return false if something failed, true otherwhise */ virtual bool setChannelAutoDownload( - const RsGxsGroupId &groupId, bool enable) = 0; + const RsGxsGroupId& channelId, bool enable) = 0; /** * @brief Get auto-download option value for given channel * @jsonapi{development} - * @param[in] groupId channel id - * @param[in] enabled storage for the auto-download option value + * @param[in] channelId channel id + * @param[out] enabled storage for the auto-download option value * @return false if something failed, true otherwhise */ virtual bool getChannelAutoDownload( - const RsGxsGroupId &groupId, bool& enabled) = 0; + const RsGxsGroupId& channelId, bool& enabled) = 0; /** * @brief Set download directory for the given channel @@ -228,7 +238,6 @@ public: * @brief Request subscription to a group. * The action is performed asyncronously, so it could fail in a subsequent * phase even after returning true. - * @jsonapi{development} * @param[out] token Storage for RsTokenService token to track request * status. * @param[in] groupId Channel id diff --git a/libretroshare/src/services/p3gxschannels.cc b/libretroshare/src/services/p3gxschannels.cc index 3897cbb2a..d5ff4ac4e 100644 --- a/libretroshare/src/services/p3gxschannels.cc +++ b/libretroshare/src/services/p3gxschannels.cc @@ -76,6 +76,8 @@ p3GxsChannels::p3GxsChannels( RsGenExchange( gds, nes, new RsGxsChannelSerialiser(), RS_SERVICE_GXS_TYPE_CHANNELS, gixs, channelsAuthenPolicy() ), RsGxsChannels(static_cast(*this)), GxsTokenQueue(this), + mSubscribedGroupsMutex("GXS channels subscribed groups cache"), + mKnownChannelsMutex("GXS channels known channels timestamp cache"), mSearchCallbacksMapMutex("GXS channels search") { // For Dummy Msgs. @@ -174,7 +176,10 @@ bool p3GxsChannels::saveList(bool &cleanup, std::list&saveList) RsGxsForumNotifyRecordsItem *item = new RsGxsForumNotifyRecordsItem ; - item->records = mKnownChannels ; + { + RS_STACK_MUTEX(mKnownChannelsMutex); + item->records = mKnownChannels; + } saveList.push_back(item) ; return true; @@ -191,8 +196,9 @@ bool p3GxsChannels::loadList(std::list& loadList) RsGxsForumNotifyRecordsItem *fnr = dynamic_cast(item) ; - if(fnr != NULL) + if(fnr) { + RS_STACK_MUTEX(mKnownChannelsMutex); mKnownChannels.clear(); for(auto it(fnr->records.begin());it!=fnr->records.end();++it) @@ -228,7 +234,7 @@ void p3GxsChannels::notifyChanges(std::vector &changes) std::cerr << "p3GxsChannels::notifyChanges() : " << changes.size() << "changes to notify" << std::endl; #endif - p3Notify *notify = NULL; + p3Notify* notify = nullptr; if (!changes.empty()) { notify = RsServer::notify(); @@ -271,9 +277,8 @@ void p3GxsChannels::notifyChanges(std::vector &changes) std::cerr << "p3GxsChannels::notifyChanges() Msgs for Group: " << mit->first; std::cerr << std::endl; #endif - bool enabled = false ; - - if (autoDownloadEnabled(mit->first, enabled) && enabled) + bool enabled = false; + if (autoDownloadEnabled(mit->first, enabled) && enabled) { #ifdef GXSCHANNELS_DEBUG std::cerr << "p3GxsChannels::notifyChanges() AutoDownload for Group: " << mit->first; @@ -306,6 +311,7 @@ void p3GxsChannels::notifyChanges(std::vector &changes) /* group received */ std::list &grpList = grpChange->mGrpIdList; std::list::iterator git; + RS_STACK_MUTEX(mKnownChannelsMutex); for (git = grpList.begin(); git != grpList.end(); ++git) { if(mKnownChannels.find(*git) == mKnownChannels.end()) @@ -338,15 +344,15 @@ void p3GxsChannels::notifyChanges(std::vector &changes) /* shouldn't need to worry about groups - as they need to be subscribed to */ } - request_SpecificSubscribedGroups(unprocessedGroups); + if(!unprocessedGroups.empty()) + request_SpecificSubscribedGroups(unprocessedGroups); RsGxsIfaceHelper::receiveChanges(changes); } void p3GxsChannels::service_tick() { - -static rstime_t last_dummy_tick = 0; + static rstime_t last_dummy_tick = 0; if (time(NULL) > last_dummy_tick + 5) { @@ -414,75 +420,84 @@ bool p3GxsChannels::groupShareKeys( * at the moment - fix it up later */ -bool p3GxsChannels::getPostData(const uint32_t &token, std::vector &msgs, std::vector &cmts) +bool p3GxsChannels::getPostData( + const uint32_t &token, std::vector &msgs, + std::vector &cmts ) { #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::getPostData()"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << std::cerr << std::endl; #endif GxsMsgDataMap msgData; - bool ok = RsGenExchange::getMsgData(token, msgData); - - if(ok) + if(!RsGenExchange::getMsgData(token, msgData)) { - GxsMsgDataMap::iterator mit = msgData.begin(); - - for(; mit != msgData.end(); ++mit) + std::cerr << __PRETTY_FUNCTION__ <<" ERROR in request" << std::endl; + return false; + } + + GxsMsgDataMap::iterator mit = msgData.begin(); + + for(; mit != msgData.end(); ++mit) + { + std::vector& msgItems = mit->second; + std::vector::iterator vit = msgItems.begin(); + + for(; vit != msgItems.end(); ++vit) { - std::vector& msgItems = mit->second; - std::vector::iterator vit = msgItems.begin(); + RsGxsChannelPostItem* postItem = + dynamic_cast(*vit); - for(; vit != msgItems.end(); ++vit) + if(postItem) { - RsGxsChannelPostItem* postItem = dynamic_cast(*vit); - - if(postItem) + RsGxsChannelPost msg; + postItem->toChannelPost(msg, true); + msgs.push_back(msg); + delete postItem; + } + else + { + RsGxsCommentItem* cmtItem = + dynamic_cast(*vit); + if(cmtItem) { - RsGxsChannelPost msg; - postItem->toChannelPost(msg, true); - msgs.push_back(msg); - delete postItem; + RsGxsComment cmt; + RsGxsMsgItem *mi = (*vit); + cmt = cmtItem->mMsg; + cmt.mMeta = mi->meta; +#ifdef GXSCOMMENT_DEBUG + std::cerr << "p3GxsChannels::getPostData Found Comment:" << std::endl; + cmt.print(std::cerr," ", "cmt"); +#endif + cmts.push_back(cmt); + delete cmtItem; } else { - RsGxsCommentItem* cmtItem = dynamic_cast(*vit); - if(cmtItem) - { - RsGxsComment cmt; - RsGxsMsgItem *mi = (*vit); - cmt = cmtItem->mMsg; - cmt.mMeta = mi->meta; -#ifdef GXSCOMMENT_DEBUG - std::cerr << "p3GxsChannels::getPostData Found Comment:" << std::endl; - cmt.print(std::cerr," ", "cmt"); -#endif - cmts.push_back(cmt); - delete cmtItem; - } - else - { - RsGxsMsgItem* msg = (*vit); - //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; - //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; - //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; - std::cerr << "Not a GxsChannelPostItem neither a RsGxsCommentItem" - << " PacketService=" << std::hex << (int)msg->PacketService() << std::dec - << " PacketSubType=" << std::hex << (int)msg->PacketSubType() << std::dec - << " , deleting!" << std::endl; - delete *vit; - } + RsGxsMsgItem* msg = (*vit); + //const uint16_t RS_SERVICE_GXS_TYPE_CHANNELS = 0x0217; + //const uint8_t RS_PKT_SUBTYPE_GXSCHANNEL_POST_ITEM = 0x03; + //const uint8_t RS_PKT_SUBTYPE_GXSCOMMENT_COMMENT_ITEM = 0xf1; + std::cerr << __PRETTY_FUNCTION__ + << " Not a GxsChannelPostItem neither a " + << "RsGxsCommentItem PacketService=" << std::hex + << (int)msg->PacketService() << std::dec + << " PacketSubType=" << std::hex + << (int)msg->PacketSubType() << std::dec + << " , deleting!" << std::endl; + delete *vit; } } } } - else - { - std::cerr << "p3GxsChannels::getPostData() ERROR in request"; - std::cerr << std::endl; - } - return ok; + return true; +} + +bool p3GxsChannels::getPostData( + const uint32_t& token, std::vector& posts ) +{ + std::vector cmts; + return getPostData(token, posts, cmts); } //Not currently used @@ -548,21 +563,6 @@ bool p3GxsChannels::getPostData(const uint32_t &token, std::vector::iterator it; + RS_STACK_MUTEX(mSubscribedGroupsMutex); + std::map::iterator it; it = mSubscribedGroups.find(groupId); if (it == mSubscribedGroups.end()) { @@ -626,6 +627,8 @@ bool p3GxsChannels::getChannelDownloadDirectory(const RsGxsGroupId & groupId,std std::cerr << "p3GxsChannels::getChannelDownloadDirectory(" << id << ")" << std::endl; #endif + RS_STACK_MUTEX(mSubscribedGroupsMutex); + std::map::iterator it; it = mSubscribedGroups.find(groupId); @@ -668,7 +671,8 @@ void p3GxsChannels::request_AllSubscribedGroups() } -void p3GxsChannels::request_SpecificSubscribedGroups(const std::list &groups) +void p3GxsChannels::request_SpecificSubscribedGroups( + const std::list &groups ) { #ifdef GXSCHANNELS_DEBUG std::cerr << "p3GxsChannels::request_SpecificSubscribedGroups()"; @@ -681,8 +685,19 @@ void p3GxsChannels::request_SpecificSubscribedGroups(const std::listrequestGroupInfo(token, ansType, opts, groups); - GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META); + if(!RsGenExchange::getTokenService()-> + requestGroupInfo(token, ansType, opts, groups)) + { + std::cerr << __PRETTY_FUNCTION__ << " Failed requesting groups info!" + << std::endl; + return; + } + + if(!GxsTokenQueue::queueRequest(token, GXSCHANNELS_SUBSCRIBED_META)) + { + std::cerr << __PRETTY_FUNCTION__ << " Failed queuing request!" + << std::endl; + } } @@ -746,6 +761,7 @@ void p3GxsChannels::updateSubscribedGroup(const RsGroupMetaData &group) std::cerr << std::endl; #endif + RS_STACK_MUTEX(mSubscribedGroupsMutex); mSubscribedGroups[group.mGroupId] = group; } @@ -757,9 +773,8 @@ void p3GxsChannels::clearUnsubscribedGroup(const RsGxsGroupId &id) std::cerr << std::endl; #endif - //std::map mSubscribedGroups; + RS_STACK_MUTEX(mSubscribedGroupsMutex); std::map::iterator it; - it = mSubscribedGroups.find(id); if (it != mSubscribedGroups.end()) { @@ -838,24 +853,20 @@ void p3GxsChannels::request_GroupUnprocessedPosts(const std::list } -void p3GxsChannels::load_SpecificUnprocessedPosts(const uint32_t &token) +void p3GxsChannels::load_SpecificUnprocessedPosts(uint32_t token) { #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SpecificUnprocessedPosts"; - std::cerr << std::endl; + std::cerr << "p3GxsChannels::load_SpecificUnprocessedPosts" << std::endl; #endif std::vector posts; if (!getPostData(token, posts)) { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::load_SpecificUnprocessedPosts ERROR"; - std::cerr << std::endl; -#endif + std::cerr << __PRETTY_FUNCTION__ << " ERROR getting post data!" + << std::endl; return; } - std::vector::iterator it; for(it = posts.begin(); it != posts.end(); ++it) { @@ -893,29 +904,24 @@ void p3GxsChannels::load_GroupUnprocessedPosts(const uint32_t &token) void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) { #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handleUnprocessedPost() GroupId: " << msg.mMeta.mGroupId << " MsgId: " << msg.mMeta.mMsgId; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " GroupId: " << msg.mMeta.mGroupId + << " MsgId: " << msg.mMeta.mMsgId << std::endl; #endif if (!IS_MSG_UNPROCESSED(msg.mMeta.mMsgStatus)) { - std::cerr << "p3GxsChannels::handleUnprocessedPost() Msg already Processed"; - std::cerr << std::endl; - std::cerr << "p3GxsChannels::handleUnprocessedPost() ERROR - this should not happen"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " ERROR Msg already Processed!" + << std::endl; return; } - bool enabled = false ; - /* check that autodownload is set */ - if (autoDownloadEnabled(msg.mMeta.mGroupId,enabled) && enabled ) + bool enabled = false; + if (autoDownloadEnabled(msg.mMeta.mGroupId, enabled) && enabled) { - - #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handleUnprocessedPost() AutoDownload Enabled ... handling"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " AutoDownload Enabled... handling" + << std::endl; #endif /* check the date is not too old */ @@ -928,8 +934,7 @@ void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) // MORE THOUGHT HAS TO GO INTO THAT STUFF. #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::handleUnprocessedPost() START DOWNLOAD"; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " START DOWNLOAD" << std::endl; #endif std::list::const_iterator fit; @@ -951,8 +956,11 @@ void p3GxsChannels::handleUnprocessedPost(const RsGxsChannelPost &msg) rsFiles->FileRequest(fname, hash, size, localpath, flags, srcIds); } - else - std::cerr << "WARNING: Channel file is not auto-downloaded because its size exceeds the threshold of " << CHANNEL_MAX_AUTO_DL << " bytes." << std::endl; + else + std::cerr << __PRETTY_FUNCTION__ << "Channel file is not auto-" + << "downloaded because its size exceeds the threshold" + << " of " << CHANNEL_MAX_AUTO_DL << " bytes." + << std::endl; } } @@ -1079,6 +1087,15 @@ bool p3GxsChannels::createPost(RsGxsChannelPost& post) return false; } +bool p3GxsChannels::subscribeToChannel( + const RsGxsGroupId& groupId, bool subscribe ) +{ + uint32_t token; + if( !subscribeToGroup(token, groupId, subscribe) + || waitToken(token) != RsTokenService::COMPLETE ) return false; + return true; +} + //////////////////////////////////////////////////////////////////////////////// /// Blocking API implementation end @@ -1096,16 +1113,13 @@ bool p3GxsChannels::autoDownloadEnabled(const RsGxsGroupId &groupId,bool& enable std::cerr << std::endl; #endif + RS_STACK_MUTEX(mSubscribedGroupsMutex); std::map::iterator it; - it = mSubscribedGroups.find(groupId); if (it == mSubscribedGroups.end()) { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::autoDownloadEnabled() No Entry"; - std::cerr << std::endl; -#endif - + std::cerr << __PRETTY_FUNCTION__ << " ERROR requested channel is not " + << "subscribed" << std::endl; return false; } @@ -1190,23 +1204,20 @@ std::string SSGxsChannelGroup::save() const return output; } -bool p3GxsChannels::setAutoDownload(const RsGxsGroupId &groupId, bool enabled) +bool p3GxsChannels::setAutoDownload(const RsGxsGroupId& groupId, bool enabled) { #ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setAutoDownload() id: " << groupId << " enabled: " << enabled; - std::cerr << std::endl; + std::cerr << __PRETTY_FUNCTION__ << " id: " << groupId + << " enabled: " << enabled << std::endl; #endif + RS_STACK_MUTEX(mSubscribedGroupsMutex); std::map::iterator it; - it = mSubscribedGroups.find(groupId); if (it == mSubscribedGroups.end()) { -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setAutoDownload() Missing Group"; - std::cerr << std::endl; -#endif - + std::cerr << __PRETTY_FUNCTION__ << " ERROR requested channel: " + << groupId.toStdString() << " is not subscribed!" << std::endl; return false; } @@ -1215,27 +1226,21 @@ bool p3GxsChannels::setAutoDownload(const RsGxsGroupId &groupId, bool enabled) ss.load(it->second.mServiceString); if (enabled == ss.mAutoDownload) { - /* it should be okay! */ -#ifdef GXSCHANNELS_DEBUG - std::cerr << "p3GxsChannels::setAutoDownload() WARNING setting looks okay already"; - std::cerr << std::endl; -#endif - + std::cerr << __PRETTY_FUNCTION__ << " WARNING mAutoDownload was already" + << " properly set to: " << enabled << " for channel:" + << groupId.toStdString() << std::endl; + return false; } - /* we are just going to set it anyway. */ ss.mAutoDownload = enabled; std::string serviceString = ss.save(); + uint32_t token; + RsGenExchange::setGroupServiceString(token, groupId, serviceString); + + if(waitToken(token) != RsTokenService::COMPLETE) return false; it->second.mServiceString = serviceString; // update Local Cache. - RsGenExchange::setGroupServiceString(token, groupId, serviceString); // update dbase. - - /* now reload it */ - std::list groups; - groups.push_back(groupId); - - request_SpecificSubscribedGroups(groups); return true; } diff --git a/libretroshare/src/services/p3gxschannels.h b/libretroshare/src/services/p3gxschannels.h index 327444509..0d2cbf561 100644 --- a/libretroshare/src/services/p3gxschannels.h +++ b/libretroshare/src/services/p3gxschannels.h @@ -83,7 +83,7 @@ public: virtual bool getGroupData(const uint32_t &token, std::vector &groups); virtual bool getPostData(const uint32_t &token, std::vector &posts, std::vector &cmts); -virtual bool getPostData(const uint32_t &token, std::vector &posts) { std::vector cmts; return getPostData( token, posts, cmts);} +virtual bool getPostData(const uint32_t &token, std::vector &posts); //Not currently used //virtual bool getRelatedPosts(const uint32_t &token, std::vector &posts); @@ -186,6 +186,10 @@ virtual bool ExtraFileRemove(const RsFileHash &hash); /// Implementation of @see RsGxsChannels::createPost virtual bool createPost(RsGxsChannelPost& post); + /// Implementation of @see RsGxsChannels::subscribeToChannel + virtual bool subscribeToChannel( const RsGxsGroupId &groupId, + bool subscribe ); + protected: // Overloaded from GxsTokenQueue for Request callbacks. virtual void handleResponse(uint32_t token, uint32_t req_type); @@ -201,7 +205,7 @@ static uint32_t channelsAuthenPolicy(); void load_SubscribedGroups(const uint32_t &token); void request_SpecificUnprocessedPosts(std::list > &ids); - void load_SpecificUnprocessedPosts(const uint32_t &token); + void load_SpecificUnprocessedPosts(uint32_t token); void request_GroupUnprocessedPosts(const std::list &grouplist); void load_GroupUnprocessedPosts(const uint32_t &token); @@ -214,11 +218,6 @@ static uint32_t channelsAuthenPolicy(); bool setAutoDownload(const RsGxsGroupId &groupId, bool enabled); bool autoDownloadEnabled(const RsGxsGroupId &groupId, bool &enabled); - - - std::map mSubscribedGroups; - - // DUMMY DATA, virtual bool generateDummyData(); @@ -246,14 +245,21 @@ bool generateGroup(uint32_t &token, std::string groupName); RsGxsMessageId mMsgId; }; + std::map mSubscribedGroups; + RsMutex mSubscribedGroupsMutex; + + /** G10h4ck: Is this stuff really used? And for what? BEGIN */ uint32_t mGenToken; bool mGenActive; int mGenCount; std::vector mGenRefs; RsGxsMessageId mGenThreadId; + /** G10h4ck: Is this stuff really used? And for what? END */ - p3GxsCommentService *mCommentService; - std::map mKnownChannels; + p3GxsCommentService* mCommentService; + + std::map mKnownChannels; + RsMutex mKnownChannelsMutex; /** Store search callbacks with timeout*/ std::map<