diff --git a/src/gxs/rsgenexchange.h b/src/gxs/rsgenexchange.h index 1bb8bbde6..7390b140b 100644 --- a/src/gxs/rsgenexchange.h +++ b/src/gxs/rsgenexchange.h @@ -96,8 +96,7 @@ typedef std::map > GxsMsgRelatedDa class RsGixs; -class RsGenExchange : public RsNxsObserver, public RsTickingThread, - public RsGxsIface +class RsGenExchange : public RsNxsObserver, public RsTickingThread, public RsGxsIface { public: diff --git a/src/gxs/rsgxsnetservice.cc b/src/gxs/rsgxsnetservice.cc index 10c2f0682..eea7f954c 100644 --- a/src/gxs/rsgxsnetservice.cc +++ b/src/gxs/rsgxsnetservice.cc @@ -367,7 +367,7 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, RsNxsNetMgr *netMgr, RsNxsObserver *nxsObs, const RsServiceInfo serviceInfo, RsGixsReputation* reputations, RsGcxs* circles, RsGixs *gixs, - PgpAuxUtils *pgpUtils, RsGxsNetTunnelService *mGxsNT, + PgpAuxUtils *pgpUtils, RsGxsNetTunnelService *mGxsNT, bool syncOldMsgVersions, bool grpAutoSync, bool msgAutoSync, bool distSync, uint32_t default_store_period, uint32_t default_sync_period) : p3ThreadedService(), p3Config(), mTransactionN(0), mObserver(nxsObs), mDataStore(gds), @@ -377,6 +377,7 @@ RsGxsNetService::RsGxsNetService(uint16_t servType, RsGeneralDataService *gds, mLastCleanRejectedMessages(0), mSYNC_PERIOD(SYNC_PERIOD), mCircles(circles), mGixs(gixs), mReputations(reputations), mPgpUtils(pgpUtils), mGxsNetTunnel(mGxsNT), + mSyncOldMsgVersions(syncOldMsgVersions), mGrpAutoSync(grpAutoSync), mAllowMsgSync(msgAutoSync),mAllowDistSync(distSync), mServiceInfo(serviceInfo), mDefaultMsgStorePeriod(default_store_period), mDefaultMsgSyncPeriod(default_sync_period) @@ -961,12 +962,28 @@ void RsGxsNetService::handleRecvSyncGrpStatistics(RsNxsSyncGrpStatsItem *grs) #endif mDataStore->retrieveGxsMsgMetaData(reqIds, result); - const auto& vec(result[grs->grpId]) ; + auto& vec(result[grs->grpId]) ; if(vec.empty()) // that means we don't have any, or there isn't any, but since the default is always 0, no need to send. return ; - RsNxsSyncGrpStatsItem *grs_resp = new RsNxsSyncGrpStatsItem(mServType) ; + if(!mSyncOldMsgVersions) // if the service doesn't sync old msg versions, get rid of them asap + { + std::set old_versions; + for(auto msgMeta:vec) + if(!msgMeta->mOrigMsgId.isNull() && msgMeta->mMsgId != msgMeta->mOrigMsgId) + old_versions.insert(msgMeta->mOrigMsgId); + + for(uint32_t i=0;imMsgId)!= old_versions.end()) + { + vec[i] = vec[vec.size()-1]; + vec.pop_back(); + } + else + ++i; + } + RsNxsSyncGrpStatsItem *grs_resp = new RsNxsSyncGrpStatsItem(mServType) ; grs_resp->request_type = RsNxsSyncGrpStatsItem::GROUP_INFO_TYPE_RESPONSE ; grs_resp->number_of_posts = vec.size(); grs_resp->grpId = grs->grpId; @@ -4450,6 +4467,8 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_ uint32_t max_send_delay = locked_getGrpConfig(item->grpId).msg_req_delay; // we should use "sync" but there's only one variable used in the GUI: the req one. #endif + // First, filter out some messages we may not want to send. + if(canSendMsgIds(msgMetas, *grpMeta, peer, should_encrypt_to_this_circle_id)) { for(auto vit = msgMetas.begin();vit != msgMetas.end(); ++vit) @@ -4615,87 +4634,108 @@ bool RsGxsNetService::canSendMsgIds(std::vector messages_old_versions; - if(circleType == GXS_CIRCLE_TYPE_LOCAL) + if(!mSyncOldMsgVersions) { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: LOCAL => returning false" << std::endl; -#endif - return false; - } - else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. - { -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: PUBLIC => returning true" << std::endl; -#endif - return true; - } - else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) - { - const RsGxsCircleId& circleId = grpMeta.mCircleId; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs ids list will be encrypted." << std::endl; -#endif - should_encrypt_id = circleId ; - - // For each message ID, check that the author is in the circle. If not, do not send the message, which means, remove it from the list. - // Unsigned messages are still transmitted. This is because in some groups (channels) the posts are not signed. Whether an unsigned post - // is allowed at this point is anyway already vetted by the RsGxsGenExchange service. - - // Messages that stay in the list will be sent. As a consequence true is always returned. - // Messages put in vetting list will be dealt with later - - std::vector toVet; + for(const auto& pmsg:msgMetas) + if(!pmsg->mOrigMsgId.isNull() && pmsg->mOrigMsgId != pmsg->mMsgId) + messages_old_versions.insert(pmsg->mOrigMsgId); for(uint32_t i=0;imAuthorId.isNull() ) // keep the message in this case - ++i ; - else + if(messages_old_versions.find(msgMetas[i]->mMsgId) != messages_old_versions.end()) { - if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, grpMeta.mGroupId, msgMetas[i]->mAuthorId)) - { + std::cerr << " Not sending msg id " << msgMetas[i]->mMsgId << " because it is an old version." << std::endl; + msgMetas[i] = msgMetas[msgMetas.size()-1]; + msgMetas.pop_back(); + } + else + ++i; + } + + + // first do the simple checks + uint8_t circleType = grpMeta.mCircleType; + + if(circleType == GXS_CIRCLE_TYPE_LOCAL) + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: LOCAL => returning false" << std::endl; +#endif + return false; + } + else if(circleType == GXS_CIRCLE_TYPE_PUBLIC || circleType == GXS_CIRCLE_TYPE_UNKNOWN) // this complies with the fact that p3IdService does not initialise the circle type. + { +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: PUBLIC => returning true" << std::endl; +#endif + return true; + } + else if(circleType == GXS_CIRCLE_TYPE_EXTERNAL) + { + const RsGxsCircleId& circleId = grpMeta.mCircleId; +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs ids list will be encrypted." << std::endl; +#endif + should_encrypt_id = circleId ; + + // For each message ID, check that the author is in the circle. If not, do not send the message, which means, remove it from the list. + // Unsigned messages are still transmitted. This is because in some groups (channels) the posts are not signed. Whether an unsigned post + // is allowed at this point is anyway already vetted by the RsGxsGenExchange service. + + // Messages that stay in the list will be sent. As a consequence true is always returned. + // Messages put in vetting list will be dealt with later + + std::vector toVet; + + for(uint32_t i=0;imAuthorId.isNull() ) // keep the message in this case ++i ; - continue ; + else + { + if(mCircles->isLoaded(circleId) && mCircles->isRecipient(circleId, grpMeta.mGroupId, msgMetas[i]->mAuthorId)) + { + ++i ; + continue ; + } + + MsgIdCircleVet mic(msgMetas[i]->mMsgId, msgMetas[i]->mAuthorId); + toVet.push_back(mic); +#ifdef NXS_NET_DEBUG_4 + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " deleting MsgMeta entry for msg ID " << msgMetas[i]->mMsgId << " signed by " << msgMetas[i]->mAuthorId << " who is not in group circle " << circleId << std::endl; +#endif + + //delete msgMetas[i] ; + msgMetas[i] = msgMetas[msgMetas.size()-1] ; + msgMetas.pop_back() ; } - MsgIdCircleVet mic(msgMetas[i]->mMsgId, msgMetas[i]->mAuthorId); - toVet.push_back(mic); #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " deleting MsgMeta entry for msg ID " << msgMetas[i]->mMsgId << " signed by " << msgMetas[i]->mAuthorId << " who is not in group circle " << circleId << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle info not loaded. Putting in vetting list and returning false." << std::endl; #endif + if(!toVet.empty()) + mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, sslId, grpMeta.mCircleId)); - //delete msgMetas[i] ; - msgMetas[i] = msgMetas[msgMetas.size()-1] ; - msgMetas.pop_back() ; - } - + return true ; + } + else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) + { #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle info not loaded. Putting in vetting list and returning false." << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; #endif - if(!toVet.empty()) - mPendingCircleVets.push_back(new MsgCircleIdsRequestVetting(mCircles, mPgpUtils, toVet, grpMeta.mGroupId, sslId, grpMeta.mCircleId)); - - return true ; - } - else if(circleType == GXS_CIRCLE_TYPE_YOUR_FRIENDS_ONLY) - { + bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; #ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " YOUREYESONLY, checking further" << std::endl; + GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; #endif - bool res = checkPermissionsForFriendGroup(sslId,grpMeta) ; -#ifdef NXS_NET_DEBUG_4 - GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Final answer: " << res << std::endl; -#endif - return res ; + return res ; + } + else + { + std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; + return false; + } } - else - { - std::cerr << "(EE) unknown value found in circle type for group " << grpMeta.mGroupId << ": " << (int)circleType << ": this is probably a bug in the design of the group creation." << std::endl; - return false; - } -} /** inherited methods **/ diff --git a/src/gxs/rsgxsnetservice.h b/src/gxs/rsgxsnetservice.h index 2896a100d..561eb2f92 100644 --- a/src/gxs/rsgxsnetservice.h +++ b/src/gxs/rsgxsnetservice.h @@ -97,6 +97,7 @@ public: const RsServiceInfo serviceInfo, RsGixsReputation* reputations = NULL, RsGcxs* circles = NULL, RsGixs *gixs=NULL, PgpAuxUtils *pgpUtils = NULL, RsGxsNetTunnelService *mGxsNT = NULL, + bool sendOldMsgVersions = true, bool grpAutoSync = true, bool msgAutoSync = true,bool distSync=false, uint32_t default_store_period = RS_GXS_DEFAULT_MSG_STORE_PERIOD, uint32_t default_sync_period = RS_GXS_DEFAULT_MSG_REQ_PERIOD); @@ -626,6 +627,7 @@ private: PgpAuxUtils *mPgpUtils; RsGxsNetTunnelService *mGxsNetTunnel; + bool mSyncOldMsgVersions; bool mGrpAutoSync; bool mAllowMsgSync; bool mAllowDistSync; diff --git a/src/gxs/rsgxsutil.cc b/src/gxs/rsgxsutil.cc index 16e30c3b3..b7cdf4f6d 100644 --- a/src/gxs/rsgxsutil.cc +++ b/src/gxs/rsgxsutil.cc @@ -99,7 +99,7 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vectorgetStoragePeriod(grpId) ; @@ -112,24 +112,29 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vector messages_with_kids ; + std::set messages_old_versions ; for( uint32_t i=0;imParentId.isNull()) messages_with_kids.insert(metaV[i]->mParentId) ; + for( uint32_t i=0;imOrigMsgId.isNull() && metaV[i]->mOrigMsgId != metaV[i]->mMsgId) // in some situations, mOrigMsgId is initialized, but equal to the sgId itself + messages_old_versions.insert(metaV[i]->mOrigMsgId) ; + for( uint32_t i=0;imMsgId)!=messages_with_kids.end()); - // check if expired + // Check if expired bool remove = store_period > 0 && ((meta->mPublishTs + store_period) < now) && !have_kids; - // check client does not want the message kept regardless of age - remove &= !(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER); + // Check client does not want the message kept regardless of age + remove = remove && !(meta->mMsgStatus & GXS_SERV::GXS_MSG_STATUS_KEEP_FOREVER); - // if not subscribed remove messages (can optimise this really) + // If not subscribed remove messages (can optimise this really) remove = remove || (grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_NOT_SUBSCRIBED); remove = remove || !(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED); @@ -138,6 +143,10 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vectormPublishTs: " << now - meta->mPublishTs ; #endif + // Only keep old messages if the client service asks for it. + + if(!mGenExchangeClient->keepOldMsgVersions() && messages_old_versions.find(meta->mMsgId)!=messages_old_versions.end()) + remove = true; if( remove ) { @@ -150,7 +159,6 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vectorgetServiceInfo(), mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel, + pgpAuxUtils,mGxsNetTunnel, + true, // sync old versions of msgs. Not really useful here because msgs are not sync-ed anyway, but this is the default. false,false,true); // don't synchronise group automatic (need explicit group request) // don't sync messages at all. // allow distsync, so that we can grab GXS id requests for other services @@ -1386,7 +1387,11 @@ int RsServer::StartupRetroShare() RS_SERVICE_GXS_TYPE_CHANNELS, gxschannels_ds, nxsMgr, mGxsChannels, mGxsChannels->getServiceInfo(), mReputations, mGxsCircles,mGxsIdService, - pgpAuxUtils,mGxsNetTunnel,true,true,true); + pgpAuxUtils,mGxsNetTunnel, + false, // don't sync old versions of messages + true, // auto-sync groups + true, // auto-sync messages + true); // distant sync (default=false) mGxsChannels->setNetworkExchangeService(gxschannels_ns) ; @@ -1449,7 +1454,7 @@ int RsServer::StartupRetroShare() RsGxsNetService* gxstrans_ns = new RsGxsNetService( RS_SERVICE_TYPE_GXS_TRANS, gxstrans_ds, nxsMgr, mGxsTrans, mGxsTrans->getServiceInfo(), mReputations, mGxsCircles, - mGxsIdService, pgpAuxUtils,NULL,true,true,false,p3GxsTrans::GXS_STORAGE_PERIOD,p3GxsTrans::GXS_SYNC_PERIOD); + mGxsIdService, pgpAuxUtils,NULL,true,true,true,false,p3GxsTrans::GXS_STORAGE_PERIOD,p3GxsTrans::GXS_SYNC_PERIOD); mGxsTrans->setNetworkExchangeService(gxstrans_ns); pqih->addService(gxstrans_ns, true); diff --git a/src/services/p3gxschannels.h b/src/services/p3gxschannels.h index ebdabc94b..5bd3ad156 100644 --- a/src/services/p3gxschannels.h +++ b/src/services/p3gxschannels.h @@ -79,6 +79,7 @@ protected: virtual RsGenExchange::ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override; virtual void notifyChanges(std::vector& changes) override; + virtual bool keepOldMsgVersions() const override { return false ; } // Overloaded from RsTickEvent. virtual void handle_event(uint32_t event_type, const std::string &elabel) override;