diff --git a/libretroshare/src/gxs/rsgenexchange.cc b/libretroshare/src/gxs/rsgenexchange.cc index cbd3fa818..c2b0916b7 100644 --- a/libretroshare/src/gxs/rsgenexchange.cc +++ b/libretroshare/src/gxs/rsgenexchange.cc @@ -309,8 +309,6 @@ uint8_t RsGenExchange::createGroup(RsNxsGrp *grp, RsTlvSecurityKeySet& privateKe }else{ return CREATE_FAIL; } - - } int RsGenExchange::createGroupSignatures(RsTlvKeySignatureSet& signSet, RsTlvBinaryData& grpData, @@ -871,31 +869,34 @@ void RsGenExchange::receiveChanges(std::vector& changes) void RsGenExchange::msgsChanged(std::map >& msgs) { - RsStackMutex stack(mGenMtx); - - while(!mMsgChange.empty()) + if(mGenMtx.trylock()) { - RsGxsMsgChange* mc = mMsgChange.back(); - msgs = mc->msgChangeMap; - mMsgChange.pop_back(); - delete mc; + while(!mMsgChange.empty()) + { + RsGxsMsgChange* mc = mMsgChange.back(); + msgs = mc->msgChangeMap; + mMsgChange.pop_back(); + delete mc; + } } } void RsGenExchange::groupsChanged(std::list& grpIds) { - RsStackMutex stack(mGenMtx); - while(!mGroupChange.empty()) + if(mGenMtx.trylock()) { - RsGxsGroupChange* gc = mGroupChange.back(); - std::list& gList = gc->mGrpIdList; - std::list::iterator lit = gList.begin(); - for(; lit != gList.end(); lit++) - grpIds.push_back(*lit); + while(!mGroupChange.empty()) + { + RsGxsGroupChange* gc = mGroupChange.back(); + std::list& gList = gc->mGrpIdList; + std::list::iterator lit = gList.begin(); + for(; lit != gList.end(); lit++) + grpIds.push_back(*lit); - mGroupChange.pop_back(); - delete gc; + mGroupChange.pop_back(); + delete gc; + } } } @@ -911,23 +912,34 @@ bool RsGenExchange::subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool RsGenExchange::updated(bool willCallGrpChanged, bool willCallMsgChanged) { bool changed = false; - { - RsStackMutex stack(mGenMtx); + if(mGenMtx.trylock()) + { changed = (!mGroupChange.empty() || !mMsgChange.empty()); + + if(!willCallGrpChanged) + { + while(!mGroupChange.empty()) + { + RsGxsGroupChange* gc = mGroupChange.back(); + mGroupChange.pop_back(); + delete gc; + } + } + + if(!willCallMsgChanged) + { + while(!mMsgChange.empty()) + { + RsGxsMsgChange* mc = mMsgChange.back(); + mMsgChange.pop_back(); + delete mc; + } + } + + mGenMtx.unlock(); } - if(!willCallGrpChanged) - { - std::list grpIds; - groupsChanged(grpIds); - } - - if(!willCallMsgChanged) - { - std::map > msgs; - msgsChanged(msgs); - } return changed; } @@ -1232,7 +1244,7 @@ void RsGenExchange::notifyNewGroups(std::vector &groups) // TODO: move this to nxs layer to save bandwidth if(received == mReceivedGrps.end()) { - GxsPendingSignItem gpsi(grp, grp->grpId); + GxsPendingItem gpsi(grp, grp->grpId); mReceivedGrps.push_back(gpsi); } else @@ -1272,7 +1284,8 @@ void RsGenExchange::publishGroup(uint32_t& token, RsGxsGrpItem *grpItem) RsStackMutex stack(mGenMtx); token = mDataAccess->generatePublicToken(); - mGrpsToPublish.insert(std::make_pair(token, grpItem)); + GxsGrpPendingSign ggps(grpItem, token); + mGrpsToPublish.push_back(ggps); #ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::publishGroup() token: " << token; @@ -1507,13 +1520,13 @@ void RsGenExchange::publishMsgs() RsStackMutex stack(mGenMtx); // stick back msgs pending signature - typedef std::map > PendSignMap; + typedef std::map > PendSignMap; PendSignMap::iterator sign_it = mMsgPendingSign.begin(); for(; sign_it != mMsgPendingSign.end(); sign_it++) { - GxsPendingSignItem& item = sign_it->second; + GxsPendingItem& item = sign_it->second; mMsgsToPublish.insert(std::make_pair(sign_it->first, item.mItem)); } @@ -1570,7 +1583,7 @@ void RsGenExchange::publishMsgs() // sign attempt if(pit == mMsgPendingSign.end()) { - GxsPendingSignItem gsi(msgItem, token); + GxsPendingItem gsi(msgItem, token); mMsgPendingSign.insert(std::make_pair(token, gsi)); } else @@ -1672,7 +1685,8 @@ void RsGenExchange::publishMsgs() mMsgsToPublish.clear(); } -RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) +RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpItem* /* grpItem */, + RsTlvSecurityKeySet& /* keySet */) { #ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::service_CreateGroup(): Does nothing" @@ -1682,49 +1696,56 @@ RsGenExchange::ServiceCreate_Return RsGenExchange::service_CreateGroup(RsGxsGrpI } -#define GEN_EXCH_GRP_CHUNK 30 +#define PENDING_SIGN_TIMEOUT 10 // 5 seconds void RsGenExchange::publishGrps() { RsStackMutex stack(mGenMtx); + NxsGrpSignPendVect::iterator vit = mGrpsToPublish.begin(); - NxsGrpSignPendVect::iterator pend_it = mGrpPendingSign.begin(); + typedef std::pair GrpNote; + std::map toNotify; - for(; pend_it != mGrpPendingSign.end();) + while( vit != mGrpsToPublish.end() ) { - GxsPendingSignItem& gpsi = *pend_it; + GxsGrpPendingSign& ggps = *vit; - if(gpsi.mAttempts == SIGN_MAX_ATTEMPTS) + /* do intial checks to see if this entry has expired */ + time_t now = time(NULL) ; + uint32_t token = ggps.mToken; + + + if(now > (ggps.mStartTS + PENDING_SIGN_TIMEOUT) ) { - pend_it = mGrpPendingSign.erase(pend_it); + // timed out + toNotify.insert(std::make_pair( + token, GrpNote(false, ""))); + delete ggps.mItem; + vit = mGrpsToPublish.erase(vit); + + continue; } - else - { - gpsi.mAttempts++; - mGrpsToPublish.insert(std::make_pair(gpsi.mId, gpsi.mItem)); - pend_it++; - } - } - std::map::iterator mit = mGrpsToPublish.begin(); - std::vector toRemove; - int i = 0; - for(; mit != mGrpsToPublish.end(); mit++) - { - - if(i > GEN_EXCH_GRP_CHUNK-1) break; - - uint32_t token = mit->first; - toRemove.push_back(token); - i++; + RsGxsGroupId grpId; RsNxsGrp* grp = new RsNxsGrp(mServType); - RsGxsGrpItem* grpItem = mit->second; + RsGxsGrpItem* grpItem = ggps.mItem; - RsTlvSecurityKeySet privatekeySet, publicKeySet, tempKeySet; - generateGroupKeys(privatekeySet, publicKeySet, - !(grpItem->meta.mGroupFlags & GXS_SERV::FLAG_PRIVACY_PUBLIC)); + RsTlvSecurityKeySet privatekeySet, publicKeySet; - // find private admin key + if(!(ggps.mHaveKeys)) + { + generateGroupKeys(privatekeySet, publicKeySet, true); + ggps.mHaveKeys = true; + ggps.mPrivateKeys = privatekeySet; + ggps.mPublicKeys = publicKeySet; + } + else + { + privatekeySet = ggps.mPrivateKeys; + publicKeySet = ggps.mPublicKeys; + } + + // find private admin key RsTlvSecurityKey privAdminKey; std::map::iterator mit_keys = privatekeySet.keys.begin(); @@ -1747,20 +1768,30 @@ void RsGenExchange::publishGrps() // get group id from private admin key id grpItem->meta.mGroupId = grp->grpId = privAdminKey.keyId; + // what!? this will remove the private keys! privatekeySet.keys.insert(publicKeySet.keys.begin(), publicKeySet.keys.end()); ServiceCreate_Return ret = service_CreateGroup(grpItem, privatekeySet); - uint32_t size = mSerialiser->size(grpItem); - char *gData = new char[size]; - bool serialOk = mSerialiser->serialise(grpItem, gData, &size); - grp->grp.setBinData(gData, size); + bool serialOk = false, servCreateOk; - delete[] gData; + if(ret == SERVICE_CREATE_SUCCESS) + { + uint32_t size = mSerialiser->size(grpItem); + char *gData = new char[size]; + serialOk = mSerialiser->serialise(grpItem, gData, &size); + grp->grp.setBinData(gData, size); + delete[] gData; + servCreateOk = true; - if(serialOk) + }else + { + servCreateOk = false; + } + + if(serialOk && servCreateOk) { grp->metaData = new RsGxsGrpMetaData(); grpItem->meta.mPublishTs = time(NULL); @@ -1783,17 +1814,8 @@ void RsGenExchange::publishGrps() if(mDataStore->validSize(grp) && serialOk) { - RsGxsGroupId grpId = grp->grpId; + grpId = grp->grpId; mDataAccess->addGroupData(grp); - - - - std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" << std::endl; - - // add to published to allow acknowledgement - mGrpNotify.insert(std::make_pair(mit->first, grpId)); - mDataAccess->updatePublicRequestStatus(mit->first, RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE); - } else { @@ -1801,6 +1823,10 @@ void RsGenExchange::publishGrps() } } } + else if(ret == SERVICE_CREATE_FAIL_TRY_LATER) + { + create = CREATE_FAIL_TRY_LATER; + } } else { @@ -1815,56 +1841,49 @@ void RsGenExchange::publishGrps() #ifdef GEN_EXCH_DEBUG std::cerr << "RsGenExchange::publishGrps() failed to publish grp " << std::endl; #endif - delete grp; delete grpItem; - - // add to published to allow acknowledgement, grpid is empty as grp creation failed - mGrpNotify.insert(std::make_pair(token, RsGxsGroupId(""))); - mDataAccess->updatePublicRequestStatus(token, RsTokenService::GXS_REQUEST_V2_STATUS_FAILED); + vit = mGrpsToPublish.erase(vit); + toNotify.insert(std::make_pair( + token, GrpNote(false, grpId))); } else if(create == CREATE_FAIL_TRY_LATER) { - delete grp; - - NxsGrpSignPendVect::iterator vit = std::find(mGrpPendingSign.begin(), - mGrpPendingSign.end(), token); - - if(vit == mGrpPendingSign.end()) - { - GxsPendingSignItem gpsi(grpItem, token); - mGrpPendingSign.push_back(gpsi); - }else - { - if(vit->mAttempts == SIGN_MAX_ATTEMPTS) - { - delete vit->mItem; - } - } +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishGrps() failed grp, trying again " << std::endl; +#endif + ggps.mLastAttemptTS = time(NULL); + vit++; } else if(create == CREATE_SUCCESS) { delete grpItem; - } + vit = mGrpsToPublish.erase(vit); - if((create == CREATE_SUCCESS) || (create == CREATE_FAIL)) - { - NxsGrpSignPendVect::iterator vit = std::find(mGrpPendingSign.begin(), - mGrpPendingSign.end(), token); +#ifdef GEN_EXCH_DEBUG + std::cerr << "RsGenExchange::publishGrps() ok -> pushing to notifies" + << std::endl; +#endif - // set to max attempts so entry removed in next publish pass - if(vit != mGrpPendingSign.end()) - { - vit->mAttempts = SIGN_MAX_ATTEMPTS; - } + // add to published to allow acknowledgement + toNotify.insert(std::make_pair(token, + GrpNote(true,grpId))); } } - // clear grp list as we're done publishing them and entries - // are invalid - for(std::vector::size_type i = 0; i < toRemove.size(); i++) - mGrpsToPublish.erase(toRemove[i]); + std::map::iterator mit = toNotify.begin(); + + for(; mit != toNotify.end(); mit++) + { + GrpNote& note = mit->second; + uint8_t status = note.first ? RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE + : RsTokenService::GXS_REQUEST_V2_STATUS_FAILED; + + mGrpNotify.insert(std::make_pair(mit->first, note.second)); + mDataAccess->updatePublicRequestStatus(mit->first, status); + } + } @@ -1997,7 +2016,7 @@ void RsGenExchange::processRecvdMessages() for(; pend_it != mMsgPendingValidate.end();) { - GxsPendingSignItem& gpsi = *pend_it; + GxsPendingItem& gpsi = *pend_it; if(gpsi.mAttempts == VALIDATE_MAX_ATTEMPTS) { @@ -2093,7 +2112,7 @@ void RsGenExchange::processRecvdMessages() if(vit == mMsgPendingValidate.end()) { - GxsPendingSignItem item(msg, id); + GxsPendingItem item(msg, id); mMsgPendingValidate.push_back(item); }else { @@ -2128,7 +2147,7 @@ void RsGenExchange::processRecvdGroups() while( vit != mReceivedGrps.end()) { - GxsPendingSignItem& gpsi = *vit; + GxsPendingItem& gpsi = *vit; RsNxsGrp* grp = gpsi.mItem; RsGxsGrpMetaData* meta = new RsGxsGrpMetaData(); bool deserialOk = meta->deserialise(grp->meta.bin_data, grp->meta.bin_len); diff --git a/libretroshare/src/gxs/rsgenexchange.h b/libretroshare/src/gxs/rsgenexchange.h index be7c0820a..24477367d 100644 --- a/libretroshare/src/gxs/rsgenexchange.h +++ b/libretroshare/src/gxs/rsgenexchange.h @@ -39,14 +39,14 @@ #include "serialiser/rsnxsitems.h" template -class GxsPendingSignItem +class GxsPendingItem { public: - GxsPendingSignItem(GxsItem item, Identity id) : + GxsPendingItem(GxsItem item, Identity id) : mItem(item), mId(id), mAttempts(0) {} - GxsPendingSignItem(const GxsPendingSignItem& gpsi) + GxsPendingItem(const GxsPendingItem& gpsi) { this->mItem = gpsi.mItem; this->mId = gpsi.mId; @@ -63,6 +63,22 @@ public: uint8_t mAttempts; }; +class GxsGrpPendingSign +{ +public: + + GxsGrpPendingSign(RsGxsGrpItem* item, uint32_t token): mLastAttemptTS(0), mStartTS(time(NULL)), mToken(token), + mItem(item), mHaveKeys(false) + {} + + time_t mLastAttemptTS, mStartTS; + uint32_t mToken; + RsGxsGrpItem* mItem; + bool mHaveKeys; // mKeys->first == true if key present + RsTlvSecurityKeySet mPrivateKeys; + RsTlvSecurityKeySet mPublicKeys; +}; + typedef std::map > GxsMsgDataMap; typedef std::map GxsGroupDataMap; typedef std::map > GxsMsgRelatedDataMap; @@ -94,7 +110,7 @@ class RsGenExchange : public RsNxsObserver, public RsThread, public RsGxsIface public: /// used by class derived for RsGenExchange to indicate if service create passed or not - enum ServiceCreate_Return { SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_FAIL_TRY_LATER } ; + enum ServiceCreate_Return { SERVICE_CREATE_SUCCESS, SERVICE_CREATE_FAIL, SERVICE_CREATE_FAIL_TRY_LATER } ; /*! * Constructs a RsGenExchange object, the owner ship of gds, ns, and serviceserialiser passes \n @@ -646,10 +662,12 @@ private: std::vector mReceivedMsgs; - typedef std::vector > NxsGrpPendValidVect; + typedef std::vector > NxsGrpPendValidVect; NxsGrpPendValidVect mReceivedGrps; - std::map mGrpsToPublish; + std::vector mGrpsToPublish; + typedef std::vector NxsGrpSignPendVect; + std::map mMsgsToPublish; std::map mMsgNotify; @@ -666,14 +684,13 @@ private: /// authentication policy uint32_t mAuthenPolicy; - std::map > + std::map > mMsgPendingSign; - std::vector > mMsgPendingValidate; - typedef std::vector > NxsMsgPendingVect; + std::vector > mMsgPendingValidate; + typedef std::vector > NxsMsgPendingVect; + - std::vector > mGrpPendingSign; - typedef std::vector > NxsGrpSignPendVect; private: diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 6e574ee5c..ce79d112d 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -1231,6 +1231,7 @@ static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, GxsIdP // Must Use meta. RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) { + #ifdef DEBUG_IDS std::cerr << "p3IdService::service_CreateGroup()"; std::cerr << std::endl; @@ -1304,6 +1305,8 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte std::cerr << std::endl; #endif // DEBUG_IDS + ServiceCreate_Return createStatus; + if (item->group.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID) { /* create the hash */ @@ -1320,6 +1323,8 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte } #endif + + if (!AuthGPG::getAuthGPG()->getKeyFingerprint(ownId,ownFinger)) { std::cerr << "p3IdService::service_CreateGroup() ERROR Own Finger is stuck"; @@ -1337,6 +1342,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte /* do signature */ + #if ENABLE_PGP_SIGNATURES #define MAX_SIGN_SIZE 2048 uint8_t signarray[MAX_SIGN_SIZE]; @@ -1348,6 +1354,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte /* error */ std::cerr << "p3IdService::service_CreateGroup() ERROR Signing stuff"; std::cerr << std::endl; + createStatus = SERVICE_CREATE_FAIL_TRY_LATER; } else { @@ -1357,6 +1364,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte { item->group.mPgpIdSign += signarray[i]; } + createStatus = SERVICE_CREATE_SUCCESS; } /* done! */ #else @@ -1364,6 +1372,10 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte #endif } + else + { + createStatus = SERVICE_CREATE_SUCCESS; + } // Enforce no AuthorId. item->meta.mAuthorId = ""; @@ -1374,7 +1386,8 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte // Reload in a little bit. // HACK to get it to work. RsTickEvent::schedule_in(GXSID_EVENT_CACHEOWNIDS, OWNID_RELOAD_DELAY); - return SERVICE_CREATE_SUCCESS; + + return createStatus; } diff --git a/retroshare-gui/src/gui/notifyqt.cpp b/retroshare-gui/src/gui/notifyqt.cpp index 9c9b65545..476496c26 100644 --- a/retroshare-gui/src/gui/notifyqt.cpp +++ b/retroshare-gui/src/gui/notifyqt.cpp @@ -194,6 +194,7 @@ bool NotifyQt::askForDeferredSelfSignature(const void *data, const uint32_t len, std::map::iterator it = _deferred_signature_queue.find(chksum.toStdString()) ; if(it != _deferred_signature_queue.end()) + { if(it->second->signature_result != 0) // found it. Copy the result, and remove from the queue. { // We should check for the exact data match, for the sake of being totally secure. @@ -211,6 +212,7 @@ bool NotifyQt::askForDeferredSelfSignature(const void *data, const uint32_t len, } else return false ; // already registered, but not done yet. + } // Not found. Store in the queue and emit a signal. // @@ -228,10 +230,21 @@ void NotifyQt::handleSignatureEvent() { std::cerr << "NotifyQt:: performing a deferred signature in the main GUI thread." << std::endl; + static bool working = false ; + + if(!working) + { + working = true ; + for(std::map::const_iterator it(_deferred_signature_queue.begin());it!=_deferred_signature_queue.end();++it) it->second->performSignature() ; + + working = false ; + } } + + bool NotifyQt::askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password) { RsAutoUpdatePage::lockAllEvents() ;