added proper synchronization of GxsIds through tunnels of another service

This commit is contained in:
csoler 2018-05-03 23:21:59 +02:00
parent 4d6fed643a
commit 8d5c013a17
No known key found for this signature in database
GPG Key ID: 7BCA522266C0804C
7 changed files with 127 additions and 85 deletions

View File

@ -766,7 +766,7 @@ void RsGxsNetService::generic_sendItem(RsNxsItem *si)
void RsGxsNetService::checkDistantSyncState()
{
if(!mAllowDistSync || mGxsNetTunnel==NULL)
if(!mAllowDistSync || mGxsNetTunnel==NULL || !mGrpAutoSync)
return ;
RsGxsGrpMetaTemporaryMap grpMeta;
@ -835,6 +835,17 @@ void RsGxsNetService::syncGrpStatistics()
std::set<RsPeerId> online_peers;
mNetMgr->getOnlineList(mServiceInfo.mServiceType, online_peers);
if(mAllowDistSync && mGxsNetTunnel != NULL)
{
// Grab all online virtual peers of distant tunnels for the current service.
std::list<RsGxsNetTunnelVirtualPeerId> vpids ;
mGxsNetTunnel->getVirtualPeers(vpids);
for(auto it(vpids.begin());it!=vpids.end();++it)
online_peers.insert(RsPeerId(*it)) ;
}
// Go through group statistics and groups without information are re-requested to random peers selected
// among the ones who provided the group info.
@ -4168,7 +4179,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
// check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for
RsGxsGroupId peer_grp ;
if(mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId)
if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId)
{
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl;
@ -4522,7 +4533,7 @@ bool RsGxsNetService::canSendMsgIds(std::vector<RsGxsMsgMetaData*>& msgMetas, co
// check if that peer is a virtual peer id, in which case we only send/recv data to/from it items for the group it's requested for
RsGxsGroupId peer_grp ;
if(mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId)
if(mAllowDistSync && mGxsNetTunnel != NULL && mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(sslId),peer_grp) && peer_grp != grpMeta.mGroupId)
{
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Distant peer designed for group " << peer_grp << ": cannot request sync for different group." << std::endl;
@ -5064,6 +5075,18 @@ bool RsGxsNetService::removeGroups(const std::list<RsGxsGroupId>& groups)
return true ;
}
bool RsGxsNetService::isDistantPeer(const RsPeerId& pid)
{
RS_STACK_MUTEX(mNxsMutex) ;
if(!mAllowDistSync || mGxsNetTunnel == NULL)
return false ;
RsGxsGroupId group_id ;
return mGxsNetTunnel->isDistantPeer(RsGxsNetTunnelVirtualPeerId(pid),group_id);
}
bool RsGxsNetService::stampMsgServerUpdateTS(const RsGxsGroupId& gid)
{
RS_STACK_MUTEX(mNxsMutex) ;

View File

@ -170,6 +170,7 @@ public:
virtual bool getGroupServerUpdateTS(const RsGxsGroupId& gid,time_t& grp_server_update_TS,time_t& msg_server_update_TS) ;
virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) ;
virtual bool removeGroups(const std::list<RsGxsGroupId>& groups);
virtual bool isDistantPeer(const RsPeerId& pid);
/* p3Config methods */
public:

View File

@ -275,6 +275,7 @@ bool RsGxsNetTunnelService::requestDistantPeers(uint16_t service_id, const RsGxs
ginfo.group_policy = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE;
ginfo.hash = calculateGroupHash(group_id) ;
ginfo.service_id = service_id;
mHandledHashes[ginfo.hash] = group_id ;
@ -307,39 +308,6 @@ bool RsGxsNetTunnelService::releaseDistantPeers(uint16_t service_id,const RsGxsG
return true;
}
const Bias20Bytes& RsGxsNetTunnelService::locked_randomBias()
{
if(mRandomBias.isNull())
{
#ifdef DEBUG_RSGXSNETTUNNEL
#warning /!\ this is for testing only! Remove this when done! Can not be done at initialization when rsPeer is not started.
RsPeerId ssl_id = rsPeers->getOwnId() ;
mRandomBias = Bias20Bytes(RsDirUtil::sha1sum(ssl_id.toByteArray(),ssl_id.SIZE_IN_BYTES)) ;
#else
mRandomBias = Bias20Bytes::random();
#endif
IndicateConfigChanged();
}
return mRandomBias ;
}
RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::locked_makeVirtualPeerId(const RsGxsGroupId& group_id)
{
assert(RsPeerId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ;// so that we can build the virtual PeerId from a SHA1 sum.
// We compute sha1( SSL_id | mRandomBias ) and trunk it to 16 bytes in order to compute a RsPeerId
Bias20Bytes rb(locked_randomBias());
unsigned char mem[group_id.SIZE_IN_BYTES + rb.SIZE_IN_BYTES];
memcpy(mem ,group_id.toByteArray(),group_id.SIZE_IN_BYTES) ;
memcpy(mem+group_id.SIZE_IN_BYTES,rb.toByteArray(),rb.SIZE_IN_BYTES) ;
return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,group_id.SIZE_IN_BYTES+rb.SIZE_IN_BYTES).toByteArray());
}
void RsGxsNetTunnelService::dump() const
{
RS_STACK_MUTEX(mGxsNetTunnelMtx);
@ -379,7 +347,7 @@ void RsGxsNetTunnelService::dump() const
std::cerr << " Virtual peers: " << std::endl;
for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it)
std::cerr << " GXS Peer:" << it->first << " Turtle:" << it->second.turtle_virtual_peer_id
<< " status: " << vpid_status_str[it->second.vpid_status] << " direction: "
<< " status: " << vpid_status_str[it->second.vpid_status]
<< " group_id: " << it->second.group_id
<< " direction: " << (int)it->second.side
<< " last seen " << time(NULL)-it->second.last_contact << " secs ago"
@ -466,7 +434,9 @@ void RsGxsNetTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *item,co
return ;
}
if(getRsItemService(getRsItemId(data)) == RS_SERVICE_TYPE_GXS_NET_TUNNEL)
uint16_t service_id = getRsItemService(getRsItemId(data));
if(service_id == RS_SERVICE_TYPE_GXS_NET_TUNNEL)
{
RsItem *decrypted_item = RsGxsNetTunnelSerializer().deserialise(data,&data_size);
RsGxsNetTunnelVirtualPeerItem *pid_item = dynamic_cast<RsGxsNetTunnelVirtualPeerItem*>(decrypted_item) ;
@ -491,52 +461,61 @@ void RsGxsNetTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *item,co
vp_info.side = direction; // client/server
vp_info.last_contact = time(NULL); // last time some data was sent/recvd
vp_info.group_id = group_id;
vp_info.service_id = mGroups[group_id].service_id ;
memcpy(vp_info.encryption_master_key,encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE);
vp_info.turtle_virtual_peer_id = turtle_virtual_peer_id; // turtle peer to use when sending data to this vpid.
free(data);
return ;
}
else
// item is a generic data item for the client. Let's store the data in the appropriate incoming data queue.
auto it = mTurtle2GxsPeer.find(turtle_virtual_peer_id) ;
if(it == mTurtle2GxsPeer.end())
{
// item is a generic data item for the client. Let's store the data in the appropriate incoming data queue.
GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for vpid " << turtle_virtual_peer_id << " but this vpid is unknown!" << std::endl;
free(data);
return;
}
auto it = mTurtle2GxsPeer.find(turtle_virtual_peer_id) ;
RsGxsNetTunnelVirtualPeerId gxs_vpid = it->second ;
if(it == mTurtle2GxsPeer.end())
{
GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for vpid " << turtle_virtual_peer_id << " but this vpid is unknown!" << std::endl;
free(data);
return;
}
auto it2 = mVirtualPeers.find(gxs_vpid) ;
RsGxsNetTunnelVirtualPeerId gxs_vpid = it->second ;
if(it2 == mVirtualPeers.end())
{
GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for GXS vpid " << gxs_vpid << " but the virtual peer id is missing!" << std::endl;
free(data);
return;
}
it2->second.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer
it2->second.last_contact = time(NULL); // last time some data was sent/recvd
auto it2 = mVirtualPeers.find(gxs_vpid) ;
if(it2 == mVirtualPeers.end())
{
GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for GXS vpid " << gxs_vpid << " but the virtual peer id is missing!" << std::endl;
free(data);
return;
}
it2->second.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ; // status of the peer
it2->second.last_contact = time(NULL); // last time some data was sent/recvd
if(service_id != it2->second.service_id && service_id != RS_SERVICE_GXS_TYPE_GXSID)
{
GXS_NET_TUNNEL_ERROR() << " received an item for VPID " << gxs_vpid << " openned for service " << it2->second.service_id << " that is not for that service nor for GXS Id service (service=" << std::hex << service_id << std::dec << ". Rejecting!" << std::endl;
free(data);
return ;
}
#ifdef DEBUG_RSGXSNETTUNNEL
GXS_NET_TUNNEL_DEBUG() << "item contains generic data for VPID " << gxs_vpid << ". Storing in incoming list" << std::endl;
GXS_NET_TUNNEL_DEBUG() << "item contains generic data for VPID " << gxs_vpid << ". service_id = " << std::hex << service_id << std::dec << ". Storing in incoming list" << std::endl;
#endif
// push the data into the incoming data list
// push the data into the incoming data list
RsTlvBinaryData *bind = new RsTlvBinaryData;
bind->tlvtype = 0;
bind->bin_len = data_size;
bind->bin_data = data;
RsTlvBinaryData *bind = new RsTlvBinaryData;
bind->tlvtype = 0;
bind->bin_len = data_size;
bind->bin_data = data;
mIncomingData.push_back(std::make_pair(gxs_vpid,bind)) ;
}
mIncomingData[service_id].push_back(std::make_pair(gxs_vpid,bind)) ;
}
void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid,RsTurtleGenericTunnelItem::Direction dir)
@ -679,6 +658,40 @@ void RsGxsNetTunnelService::data_tick()
rstime::rs_usleep(1*1000*1000) ; // 1 sec
}
const Bias20Bytes& RsGxsNetTunnelService::locked_randomBias()
{
if(mRandomBias.isNull())
{
#ifdef DEBUG_RSGXSNETTUNNEL
#warning /!\ this is for testing only! Remove this when done! Can not be done at initialization when rsPeer is not started.
RsPeerId ssl_id = rsPeers->getOwnId() ;
mRandomBias = Bias20Bytes(RsDirUtil::sha1sum(ssl_id.toByteArray(),ssl_id.SIZE_IN_BYTES)) ;
#else
mRandomBias = Bias20Bytes::random();
#endif
IndicateConfigChanged();
}
return mRandomBias ;
}
RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::locked_makeVirtualPeerId(const RsGxsGroupId& group_id)
{
assert(RsPeerId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ;// so that we can build the virtual PeerId from a SHA1 sum.
// We compute sha1( SSL_id | mRandomBias ) and trunk it to 16 bytes in order to compute a RsPeerId
Bias20Bytes rb(locked_randomBias());
unsigned char mem[group_id.SIZE_IN_BYTES + rb.SIZE_IN_BYTES];
memcpy(mem ,group_id.toByteArray(),group_id.SIZE_IN_BYTES) ;
memcpy(mem+group_id.SIZE_IN_BYTES,rb.toByteArray(),rb.SIZE_IN_BYTES) ;
return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,group_id.SIZE_IN_BYTES+rb.SIZE_IN_BYTES).toByteArray());
}
void RsGxsNetTunnelService::sendKeepAlivePackets()
{
RS_STACK_MUTEX(mGxsNetTunnelMtx);
@ -834,14 +847,8 @@ bool RsGxsNetTunnelService::loadList(std::list<RsItem *> &load)
RsSerialiser *RsGxsNetTunnelService::setupSerialiser()
{
RS_STACK_MUTEX(mGxsNetTunnelMtx);
static RsSerialiser *ser = NULL ; // this is not so nice, but this method is only called from p3Config, so there's no really need of a data race
if(!ser)
{
ser = new RsSerialiser ;
ser->addSerialType(new RsGxsNetTunnelSerializer) ;
}
RsSerialiser *ser = new RsSerialiser ;
ser->addSerialType(new RsGxsNetTunnelSerializer) ;
return ser ;
}

View File

@ -120,6 +120,7 @@ struct RsGxsNetTunnelVirtualPeerInfo
TurtleVirtualPeerId turtle_virtual_peer_id ; // turtle peer to use when sending data to this vpid.
RsGxsGroupId group_id ; // group that virtual peer is providing
uint16_t service_id ; // this is used for checkng consistency of the incoming data
};
struct RsGxsNetTunnelGroupInfo
@ -144,6 +145,7 @@ struct RsGxsNetTunnelGroupInfo
GroupStatus group_status ;
time_t last_contact ;
TurtleFileHash hash ;
uint16_t service_id ;
std::set<TurtleVirtualPeerId> virtual_peers ; // list of which virtual peers provide this group. Can me more than 1.
};

View File

@ -166,6 +166,14 @@ public:
*/
virtual bool stampMsgServerUpdateTS(const RsGxsGroupId& gid) =0;
/*!
* \brief isDistantPeer
* \param pid peer that is a virtual peer provided by GxsNetTunnel
* \return
* true if the peer exists (adn therefore is online)
*/
virtual bool isDistantPeer(const RsPeerId& pid)=0;
/*!
* \brief removeGroups
* Removes time stamp information from the list of groups. This allows to re-sync them if suppliers are present.

View File

@ -1279,6 +1279,14 @@ int RsServer::StartupRetroShare()
RsNxsNetMgr* nxsMgr = new RsNxsNetMgrImpl(serviceCtrl);
/**** GXS Dist sync service ****/
#ifdef RS_USE_GXS_DISTANT_SYNC
RsGxsNetTunnelService *mGxsNetTunnel = new RsGxsNetTunnelService ;
#else
RsGxsNetTunnelService *mGxsNetTunnel = NULL ;
#endif
/**** Identity service ****/
RsGeneralDataService* gxsid_ds = new RsDataService(currGxsDir + "/", "gxsid_db",
@ -1300,9 +1308,10 @@ int RsServer::StartupRetroShare()
RS_SERVICE_GXS_TYPE_GXSID, gxsid_ds, nxsMgr,
mGxsIdService, mGxsIdService->getServiceInfo(),
mReputations, mGxsCircles,mGxsIdService,
pgpAuxUtils,NULL,
false,false); // don't synchronise group automatic (need explicit group request)
pgpAuxUtils,mGxsNetTunnel,
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
// Normally we wouldn't need this (we do in other service):
// mGxsIdService->setNetworkExchangeService(gxsid_ns) ;
@ -1358,14 +1367,6 @@ int RsServer::StartupRetroShare()
mWiki->setNetworkExchangeService(wiki_ns) ;
#endif
/**** GXS Dist sync service ****/
#ifdef RS_USE_GXS_DISTANT_SYNC
RsGxsNetTunnelService *mGxsNetTunnel = new RsGxsNetTunnelService ;
#else
RsGxsNetTunnelService *mGxsNetTunnel = NULL ;
#endif
/**** Forum GXS service ****/
RsGeneralDataService* gxsforums_ds = new RsDataService(currGxsDir + "/", "gxsforums_db",

View File

@ -2700,7 +2700,7 @@ void p3IdService::requestIdsFromNet()
bool request_can_proceed = false ;
for(cit2 = peers.begin(); cit2 != peers.end(); ++cit2)
if(rsPeers->isOnline(*cit2)) // make sure that the peer in online, so that we know that the request has some chance to succeed.
if(rsPeers->isOnline(*cit2) || mNes->isDistantPeer(*cit2)) // make sure that the peer in online, so that we know that the request has some chance to succeed.
{
requests[*cit2].push_back(cit->first);
request_can_proceed = true ;