mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
added asymmetry in GXS tunnel management to reduce the number of tunnels
This commit is contained in:
parent
393ff75c90
commit
66df281f25
@ -799,6 +799,9 @@ void RsGxsNetService::checkDistantSyncState()
|
||||
if(online_peers.find(*it2) != online_peers.end()) // check that the peer is online
|
||||
at_least_one_friend_is_supplier = true ;
|
||||
|
||||
// That strategy is likely to create islands of friends connected to each other. There's no real way
|
||||
// to decide what to do here, except maybe checking the last message TS remotely vs. locally.
|
||||
|
||||
if(at_least_one_friend_is_supplier)
|
||||
{
|
||||
mGxsNetTunnel->releasePeers(mServType,grpId);
|
||||
|
@ -36,7 +36,11 @@
|
||||
#define GXS_NET_TUNNEL_ERROR() std::cerr << "(EE) GXS_NET_TUNNEL ERROR : "
|
||||
|
||||
|
||||
RsGxsNetTunnelService::RsGxsNetTunnelService(): mGxsNetTunnelMtx("GxsNetTunnel") {}
|
||||
RsGxsNetTunnelService::RsGxsNetTunnelService(): mGxsNetTunnelMtx("GxsNetTunnel")
|
||||
{
|
||||
#warning this is for testing only. In the final version this needs to be initialized with some random content.
|
||||
memset(mRandomBias,0,RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE) ;
|
||||
}
|
||||
|
||||
//===========================================================================================================================================//
|
||||
// Transport Items //
|
||||
@ -287,7 +291,7 @@ RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::locked_makeVirtualPeerId() co
|
||||
//memcpy(mem+RsPeerId::SIZE_IN_BYTES ,group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ;
|
||||
memcpy(mem+RsPeerId::SIZE_IN_BYTES /*+RsGxsGroupId::SIZE_IN_BYTES*/,mRandomBias ,RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE) ;
|
||||
|
||||
return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES+RsGxsGroupId::SIZE_IN_BYTES+RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE).toByteArray());
|
||||
return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES+/*RsGxsGroupId::SIZE_IN_BYTES+*/ RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE).toByteArray());
|
||||
}
|
||||
|
||||
void RsGxsNetTunnelService::dump() const
|
||||
@ -318,6 +322,8 @@ void RsGxsNetTunnelService::dump() const
|
||||
for(auto it(mGroups.begin());it!=mGroups.end();++it)
|
||||
{
|
||||
std::cerr << " " << it->first << " hash: " << it->second.hash << " policy: " << group_policy_str[it->second.group_policy] << " status: " << group_status_str[it->second.group_status] << " Last contact: " << time(NULL) - it->second.last_contact << " secs ago" << std::endl;
|
||||
|
||||
if(!it->second.virtual_peers.empty())
|
||||
std::cerr << " virtual peers:" << std::endl;
|
||||
for(auto it2(it->second.virtual_peers.begin());it2!=it->second.virtual_peers.end();++it2)
|
||||
std::cerr << " " << *it2 << std::endl;
|
||||
@ -334,6 +340,9 @@ void RsGxsNetTunnelService::dump() const
|
||||
for(auto it2(it->second.providing_set.begin());it2!=it->second.providing_set.end();++it2)
|
||||
std::cerr << " service " << std::hex << it2->first << std::dec << " " << it2->second.provided_groups.size() << " groups" << std::endl;
|
||||
}
|
||||
std::cerr << "Virtual peer turtle => GXS conversion table: " << std::endl;
|
||||
for(auto it(mTurtle2GxsPeer.begin());it!=mTurtle2GxsPeer.end();++it)
|
||||
std::cerr << " " << it->first << " => " << it->second << std::endl;
|
||||
|
||||
std::cerr << "Hashes: " << std::endl;
|
||||
for(auto it(mHandledHashes.begin());it!=mHandledHashes.end();++it)
|
||||
@ -413,7 +422,7 @@ void RsGxsNetTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *item,co
|
||||
RsItem *decrypted_item = RsGxsNetTunnelSerializer().deserialise(data,&data_size);
|
||||
RsGxsNetTunnelVirtualPeerItem *pid_item = dynamic_cast<RsGxsNetTunnelVirtualPeerItem*>(decrypted_item) ;
|
||||
|
||||
if(!pid_item)
|
||||
if(!pid_item) // this handles the case of a KeepAlive packet.
|
||||
{
|
||||
delete decrypted_item ;
|
||||
return ;
|
||||
@ -555,7 +564,7 @@ void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const
|
||||
|
||||
if(ginfo.virtual_peers.empty())
|
||||
{
|
||||
ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_TUNNELS_REQUESTED ;
|
||||
ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE ;
|
||||
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
GXS_NET_TUNNEL_DEBUG() << " no more virtual peers for group " << group_id << ": setting status to TUNNELS_REQUESTED" << std::endl;
|
||||
@ -617,30 +626,115 @@ void RsGxsNetTunnelService::data_tick()
|
||||
{
|
||||
last_dump = now;
|
||||
dump();
|
||||
|
||||
sendKeepAlivePackets() ;
|
||||
}
|
||||
}
|
||||
|
||||
void RsGxsNetTunnelService::sendKeepAlivePackets()
|
||||
{
|
||||
RS_STACK_MUTEX(mGxsNetTunnelMtx);
|
||||
RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId() ;
|
||||
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
GXS_NET_TUNNEL_DEBUG() << " sending keep-alive packets. Own GXS peer ID is " << own_gxs_vpid << std::endl;
|
||||
#endif
|
||||
|
||||
// We send KA packets for each GXS virtual peer. The advantage is that unused tunnels will automatically die which eliminates duplicate tunnels
|
||||
// automatically. We only send from the client side.
|
||||
|
||||
for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it)
|
||||
if(own_gxs_vpid < it->first)
|
||||
{
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
GXS_NET_TUNNEL_DEBUG() << " sending to virtual peer " << it->first << " through tunnel " << it->second.turtle_virtual_peer_id << std::endl;
|
||||
#endif
|
||||
RsGxsNetTunnelKeepAliveItem pitem ;
|
||||
RsTemporaryMemory tmpmem( RsGxsNetTunnelSerializer().size(&pitem) ) ;
|
||||
uint32_t len = tmpmem.size();
|
||||
|
||||
RsGxsNetTunnelSerializer().serialise(&pitem,tmpmem,&len);
|
||||
|
||||
RsTurtleGenericDataItem *encrypted_turtle_item = NULL ;
|
||||
|
||||
if(p3turtle::encryptData(tmpmem,len,it->second.encryption_master_key,encrypted_turtle_item))
|
||||
mPendingTurtleItems.push_back(std::make_pair(it->second.turtle_virtual_peer_id,encrypted_turtle_item)) ;
|
||||
}
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
else
|
||||
GXS_NET_TUNNEL_DEBUG() << " ignoring virtual peer " << it->first << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void RsGxsNetTunnelService::autowash()
|
||||
{
|
||||
RS_STACK_MUTEX(mGxsNetTunnelMtx);
|
||||
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
GXS_NET_TUNNEL_DEBUG() << " performing per-group consistency test." << std::endl;
|
||||
#endif
|
||||
RsGxsNetTunnelVirtualPeerId own_gxs_vpid = locked_makeVirtualPeerId() ;
|
||||
|
||||
for(auto it(mGroups.begin());it!=mGroups.end();++it)
|
||||
{
|
||||
RsGxsNetTunnelGroupInfo& ginfo(it->second) ;
|
||||
bool should_monitor_tunnels = false ;
|
||||
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
GXS_NET_TUNNEL_DEBUG() << " group " << it->first << ": " ;
|
||||
#endif
|
||||
// check whether the group already has GXS virtual peers with suppliers. If so, we can set the GRP policy as passive.
|
||||
|
||||
if(ginfo.group_policy == RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE)
|
||||
{
|
||||
bool found = false ;
|
||||
|
||||
// check wether one virtual peer provided by GXS has ID > own ID. In this case we leave the priority to it.
|
||||
|
||||
for(auto it2(ginfo.virtual_peers.begin());!found && it2!=ginfo.virtual_peers.end();++it2)
|
||||
{
|
||||
auto it3 = mTurtle2GxsPeer.find(*it2) ;
|
||||
|
||||
if( it3 != mTurtle2GxsPeer.end() && it3->second < own_gxs_vpid)
|
||||
found = true ;
|
||||
}
|
||||
|
||||
if(found)
|
||||
{
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
std::cerr << " active, with client-side peers : ";
|
||||
#endif
|
||||
should_monitor_tunnels = true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
should_monitor_tunnels = false ;
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
std::cerr << " active, and no client-side peers available : " ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
else
|
||||
std::cerr << " passive : ";
|
||||
#endif
|
||||
|
||||
// check if the group is in active or passive mode, in which case make sure that turtle manages tunnels or not.
|
||||
// if active, then we check wether they are tunnels are not. If not, we ask turtle to monitor.
|
||||
|
||||
RsGxsNetTunnelGroupInfo& ginfo(it->second) ;
|
||||
|
||||
if(ginfo.group_policy == RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE && ginfo.virtual_peers.empty())
|
||||
if(should_monitor_tunnels)
|
||||
{
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
std::cerr << " requesting tunnels" << std::endl;
|
||||
#endif
|
||||
mTurtle->monitorTunnels(ginfo.hash,this,false) ;
|
||||
ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_TUNNELS_REQUESTED;
|
||||
}
|
||||
|
||||
if(ginfo.group_policy == RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE)
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_RSGXSNETTUNNEL
|
||||
std::cerr << " dropping tunnels" << std::endl;
|
||||
#endif
|
||||
mTurtle->stopMonitoringTunnels(ginfo.hash);
|
||||
ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,14 +129,14 @@ struct RsGxsNetTunnelGroupInfo
|
||||
enum GroupStatus {
|
||||
RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN = 0x00, // unknown status
|
||||
RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE = 0x01, // no virtual peers requested, just waiting
|
||||
RS_GXS_NET_TUNNEL_GRP_STATUS_TUNNELS_REQUESTED = 0x02, // virtual peers requested, and waiting for turtle to answer
|
||||
// RS_GXS_NET_TUNNEL_GRP_STATUS_TUNNELS_REQUESTED = 0x02, // virtual peers requested, and waiting for turtle to answer
|
||||
RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE = 0x03 // some virtual peers are available. Data can be read/written
|
||||
};
|
||||
|
||||
enum GroupPolicy {
|
||||
RS_GXS_NET_TUNNEL_GRP_POLICY_UNKNOWN = 0x00, // nothing has been set
|
||||
RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE = 0x01, // group is available for server side tunnels, but does not explicitely request tunnels
|
||||
RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group explicitely request tunnels, if none available
|
||||
RS_GXS_NET_TUNNEL_GRP_POLICY_ACTIVE = 0x02, // group will explicitely request tunnels, if none available
|
||||
};
|
||||
|
||||
RsGxsNetTunnelGroupInfo() : group_policy(RS_GXS_NET_TUNNEL_GRP_POLICY_PASSIVE),group_status(RS_GXS_NET_TUNNEL_GRP_STATUS_IDLE),last_contact(0),service_id(0) {}
|
||||
@ -147,7 +147,7 @@ struct RsGxsNetTunnelGroupInfo
|
||||
TurtleFileHash hash ;
|
||||
uint16_t service_id ;
|
||||
|
||||
std::set<RsGxsNetTunnelVirtualPeerId> virtual_peers ; // list of which virtual peers provide this group. Can me more than 1.
|
||||
std::set<TurtleVirtualPeerId> virtual_peers ; // list of which virtual peers provide this group. Can me more than 1.
|
||||
};
|
||||
|
||||
class RsGxsNetTunnelService: public RsTurtleClientService, public RsTickingThread
|
||||
@ -231,6 +231,7 @@ protected:
|
||||
p3turtle *mTurtle ;
|
||||
private:
|
||||
void autowash() ;
|
||||
void sendKeepAlivePackets() ;
|
||||
void handleIncoming(RsGxsNetTunnelItem *item) ;
|
||||
void flush_pending_items();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user