Merge pull request #74 from csoler/v0.6-BugFixing_22

added auto-delete and not syncing of previous versions of group messa…
This commit is contained in:
csoler 2023-02-18 20:51:45 +01:00 committed by GitHub
commit 74cd958cf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 143 additions and 79 deletions

View File

@ -96,8 +96,7 @@ typedef std::map<RsGxsGrpMsgIdPair, std::vector<RsGxsMsgItem*> > GxsMsgRelatedDa
class RsGixs;
class RsGenExchange : public RsNxsObserver, public RsTickingThread,
public RsGxsIface
class RsGenExchange : public RsNxsObserver, public RsTickingThread, public RsGxsIface
{
public:

View File

@ -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<RsGxsMessageId> old_versions;
for(auto msgMeta:vec)
if(!msgMeta->mOrigMsgId.isNull() && msgMeta->mMsgId != msgMeta->mOrigMsgId)
old_versions.insert(msgMeta->mOrigMsgId);
for(uint32_t i=0;i<vec.size();)
if(old_versions.find(vec[i]->mMsgId)!= 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<std::shared_ptr<RsGxsMsgMetaData
return false ;
}
// first do the simple checks
uint8_t circleType = grpMeta.mCircleType;
// If the service prevents sending old versions of messages, remove them from the list
std::set<RsGxsMessageId> 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<MsgIdCircleVet> 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;i<msgMetas.size();)
if( msgMetas[i]->mAuthorId.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<MsgIdCircleVet> toVet;
for(uint32_t i=0;i<msgMetas.size();)
if( msgMetas[i]->mAuthorId.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 **/

View File

@ -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;

View File

@ -99,7 +99,7 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vector<RsGxsGrou
GxsMsgMetaResult::iterator mit = result.begin();
#ifdef DEBUG_GXSUTIL
GXSUTIL_DEBUG() << " Cleaning up group message for group ID " << grpId << std::endl;
GXSUTIL_DEBUG() << " Cleaning up messages for group ID " << grpId << std::endl;
#endif
uint32_t store_period = mGenExchangeClient->getStoragePeriod(grpId) ;
@ -112,24 +112,29 @@ bool RsGxsCleanUp::clean(RsGxsGroupId& next_group_to_check,std::vector<RsGxsGrou
// end the message tree will be deleted slice after slice, which should still be reasonnably fast.
//
std::set<RsGxsMessageId> messages_with_kids ;
std::set<RsGxsMessageId> messages_old_versions ;
for( uint32_t i=0;i<metaV.size();++i)
if(!metaV[i]->mParentId.isNull())
messages_with_kids.insert(metaV[i]->mParentId) ;
for( uint32_t i=0;i<metaV.size();++i)
if(!metaV[i]->mOrigMsgId.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;i<metaV.size();++i)
{
const auto& meta = metaV[i];
bool have_kids = (messages_with_kids.find(meta->mMsgId)!=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::vector<RsGxsGrou
<< " subscribed: " << bool(grpMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) << " store_period: " << store_period
<< " kids: " << have_kids << " now - meta->mPublishTs: " << 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::vector<RsGxsGrou
else
std::cerr << std::endl;
#endif
//delete meta;
}
}
}

View File

@ -344,6 +344,15 @@ struct RsGxsIface
virtual uint32_t getStoragePeriod(const RsGxsGroupId& grpId) = 0;
virtual void setStoragePeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0;
/*!
* \brief keepOldMsgVersions
* Overload this in order to force the deletion of old versions of messages.
* \return
* true = keep old message versions (e.g. forums)
* false = delete old message versions (e.g. channels)
*/
virtual bool keepOldMsgVersions() const { return true ; }
virtual uint32_t getDefaultSyncPeriod() = 0;
virtual uint32_t getSyncPeriod(const RsGxsGroupId& grpId) = 0;
virtual void setSyncPeriod(const RsGxsGroupId& grpId,uint32_t age_in_secs) = 0;

View File

@ -1295,7 +1295,8 @@ int RsServer::StartupRetroShare()
RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr,
mGxsIdService, mGxsIdService->getServiceInfo(),
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);

View File

@ -79,6 +79,7 @@ protected:
virtual RsGenExchange::ServiceCreate_Return service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet) override;
virtual void notifyChanges(std::vector<RsGxsNotify*>& 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;