mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-29 01:16:20 -05:00
saving ongoing work. Implementation almoast finished.
This commit is contained in:
parent
8df9d4be04
commit
5c0f1dac08
@ -82,11 +82,12 @@ void p3GxsTunnelService::flush()
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
for(std::map<RsGxsId,GxsTunnelPeerInfo>::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();++it)
|
||||
for(std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it(_gxs_tunnel_contacts.begin());it!=_gxs_tunnel_contacts.end();++it)
|
||||
{
|
||||
if(it->second.last_contact+20+GXS_TUNNEL_KEEP_ALIVE_TIMEOUT < now && it->second.status == RS_GXS_TUNNEL_STATUS_CAN_TALK)
|
||||
{
|
||||
std::cerr << "(II) GxsTunnelService:: connexion interrupted with peer." << std::endl;
|
||||
|
||||
it->second.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ;
|
||||
it->second.virtual_peer_id.clear() ;
|
||||
|
||||
@ -232,7 +233,7 @@ void p3GxsTunnelService::addVirtualPeer(const TurtleFileHash& hash,const TurtleV
|
||||
else // client side
|
||||
{
|
||||
RsGxsId to_gxs_id = gxsIdFromHash(hash) ;
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(to_gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(to_gxs_id) ;
|
||||
|
||||
if(it == _gxs_tunnel_contacts.end())
|
||||
{
|
||||
@ -273,6 +274,7 @@ void p3GxsTunnelService::locked_restartDHSession(const RsPeerId& virtual_peer_id
|
||||
GxsTunnelDHInfo& dhinfo = _gxs_tunnel_virtual_peer_ids[virtual_peer_id] ;
|
||||
|
||||
dhinfo.status = RS_GXS_TUNNEL_DH_STATUS_UNINITIALIZED ;
|
||||
dhinfo.own_gxs_id = own_gxs_id ;
|
||||
|
||||
if(!locked_initDHSessionKey(dhinfo.dh))
|
||||
{
|
||||
@ -313,7 +315,7 @@ void p3GxsTunnelService::removeVirtualPeer(const TurtleFileHash& hash,const Turt
|
||||
DH_free(it->second.dh) ;
|
||||
_gxs_tunnel_virtual_peer_ids.erase(it) ;
|
||||
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
|
||||
if(it2 == _gxs_tunnel_contacts.end())
|
||||
{
|
||||
@ -436,7 +438,7 @@ bool p3GxsTunnelService::handleEncryptedData(const uint8_t *data_bytes,uint32_t
|
||||
}
|
||||
|
||||
RsGxsId gxs_id = it->second.gxs_id ;
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it2 = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
|
||||
if(it2 == _gxs_tunnel_contacts.end())
|
||||
{
|
||||
@ -636,22 +638,25 @@ void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item)
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << " DH key computation successed. New key in place." << std::endl;
|
||||
#endif
|
||||
GxsTunnelPeerInfo& pinfo(_gxs_tunnel_contacts[senders_id]) ;
|
||||
// make a hash of destination and source GXS ids in order to create the tunnel name
|
||||
|
||||
RsGxsId own_id = it->second.own_gxs_id ;
|
||||
RsGxsTunnelId tunnel_id = makeGxsTunnelId(own_id,senders_id) ;
|
||||
|
||||
GxsTunnelPeerInfo& pinfo(_gxs_tunnel_contacts[tunnel_id]) ;
|
||||
|
||||
// Now hash the key buffer into a 16 bytes key.
|
||||
|
||||
assert(GXS_TUNNEL_AES_KEY_SIZE <= Sha1CheckSum::SIZE_IN_BYTES) ;
|
||||
memcpy(pinfo.aes_key, RsDirUtil::sha1sum(key_buff,size).toByteArray(),GXS_TUNNEL_AES_KEY_SIZE) ;
|
||||
delete[] key_buff ;
|
||||
|
||||
|
||||
pinfo.last_contact = time(NULL) ;
|
||||
pinfo.last_keep_alive_sent = time(NULL) ;
|
||||
pinfo.status = RS_GXS_TUNNEL_STATUS_CAN_TALK ;
|
||||
pinfo.virtual_peer_id = vpid ;
|
||||
pinfo.direction = it->second.direction ;
|
||||
|
||||
if(pinfo.direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT)
|
||||
pinfo.own_gxs_id = gxsIdFromHash(it->second.hash) ;
|
||||
pinfo.own_gxs_id = own_id ;
|
||||
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << " DH key computed. Tunnel is now secured!" << std::endl;
|
||||
@ -676,6 +681,29 @@ void p3GxsTunnelService::handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item)
|
||||
//RsServer::notify()->notifyListChange(NOTIFY_LIST_PRIVATE_INCOMING_CHAT, NOTIFY_TYPE_ADD);
|
||||
}
|
||||
|
||||
RsGxsTunnelId p3GxsTunnelService::makeGxsTunnelId(const RsGxsId& own_id,const RsGxsId& distant_id) const
|
||||
{
|
||||
unsigned char mem[RsGxsId::SIZE_IN_BYTES * 2] ;
|
||||
|
||||
// Always sort the ids, as a matter to avoid confusion between the two. Also that generates the same tunnel ID on both sides
|
||||
// which helps debugging. If the code is right this is not needed anyway.
|
||||
|
||||
if(own_id < distant_id)
|
||||
{
|
||||
memcpy(mem, own_id.toBytesArray(), RsGxsId::SIZE_IN_BYTES) ;
|
||||
memcpy(mem+RsGxsId::SIZE_IN_BYTES, distant_id.toBytesArray(), RsGxsId::SIZE_IN_BYTES) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(mem, distant_id.toBytesArray(), RsGxsId::SIZE_IN_BYTES) ;
|
||||
memcpy(mem+RsGxsId::SIZE_IN_BYTES, own_id.toBytesArray(), RsGxsId::SIZE_IN_BYTES) ;
|
||||
}
|
||||
|
||||
assert( RsGxsTunnelId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES ) ;
|
||||
|
||||
return RsGxsTunnelId( RsUtil::sha1sum(mem, 2*RsGxsId::SIZE_IN_BYTES).toByteArray() ) ;
|
||||
}
|
||||
|
||||
bool p3GxsTunnelService::locked_sendDHPublicKey(const DH *dh,const RsGxsId& own_gxs_id,const RsPeerId& virtual_peer_id)
|
||||
{
|
||||
if(dh == NULL)
|
||||
@ -847,7 +875,7 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
|
||||
#endif
|
||||
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
|
||||
if(it == _gxs_tunnel_contacts.end())
|
||||
{
|
||||
@ -912,7 +940,7 @@ void p3GxsTunnelService::sendEncryptedTurtleData(const uint8_t *buff,uint32_t rs
|
||||
mTurtle->sendTurtleData(virtual_peer_id,gitem) ;
|
||||
}
|
||||
|
||||
bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,RsGxsTunnelClientService *client,uint32_t& error_code)
|
||||
bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id, uint32_t& error_code)
|
||||
{
|
||||
// should be a parameter.
|
||||
|
||||
@ -942,14 +970,17 @@ bool p3GxsTunnelService::requestSecuredTunnel(const RsGxsId& to_gxs_id,const RsG
|
||||
return true ;
|
||||
}
|
||||
|
||||
void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id)
|
||||
void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id,const RsGxsId& from_gxs_id,RsGxsTunnelId& tunnel_id)
|
||||
{
|
||||
RsGxsTunnelId tnl_id = makeGxsTunnelId(from_gxs_id,to_gxs_id) ;
|
||||
tunnel_id = tnl_id ;
|
||||
|
||||
{
|
||||
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
if(_gxs_tunnel_contacts.find(to_gxs_id) != _gxs_tunnel_contacts.end())
|
||||
if(_gxs_tunnel_contacts.find(tunnel_id) != _gxs_tunnel_contacts.end())
|
||||
{
|
||||
std::cerr << "GxsTunnelService:: asking distant chat connexion to a peer who's already in a chat. Ignoring." << std::endl;
|
||||
std::cerr << "GxsTunnelService:: asking GXS tunnel for a configuration that already exits.Ignoring." << std::endl;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
@ -961,6 +992,7 @@ void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id
|
||||
info.last_keep_alive_sent = now ;
|
||||
info.status = RS_GXS_TUNNEL_STATUS_TUNNEL_DN ;
|
||||
info.own_gxs_id = from_gxs_id ;
|
||||
info.to_gxs_id = to_gxs_id ;
|
||||
info.direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ;
|
||||
info.virtual_peer_id.clear();
|
||||
|
||||
@ -968,11 +1000,13 @@ void p3GxsTunnelService::startClientGxsTunnelConnection(const RsGxsId& to_gxs_id
|
||||
|
||||
{
|
||||
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
|
||||
_gxs_tunnel_contacts[to_gxs_id] = info ;
|
||||
|
||||
_gxs_tunnel_contacts[tnt_id] = info ;
|
||||
}
|
||||
|
||||
// Now ask the turtle router to manage a tunnel for that hash.
|
||||
|
||||
#warning need to make sure that we can ask the same hash if the from ID is different. What's going to happen??
|
||||
RsFileHash hash = hashFromGxsId(to_gxs_id) ;
|
||||
#ifdef DEBUG_GXS_TUNNEL
|
||||
std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl;
|
||||
@ -1032,7 +1066,7 @@ bool p3GxsTunnelService::getTunnelStatus(const RsGxsId& gxs_id,uint32_t& status,
|
||||
{
|
||||
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
|
||||
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
|
||||
if(it != _gxs_tunnel_contacts.end())
|
||||
{
|
||||
@ -1049,7 +1083,7 @@ bool p3GxsTunnelService::getTunnelStatus(const RsGxsId& gxs_id,uint32_t& status,
|
||||
return false ;
|
||||
}
|
||||
|
||||
bool p3GxsTunnelService::closeExistingTunnel(const RsGxsId& gxs_id)
|
||||
bool p3GxsTunnelService::closeExistingTunnel(const RsGxsTunnelId& tunnel_id)
|
||||
{
|
||||
// two cases:
|
||||
// - client needs to stop asking for tunnels => remove the hash from the list of tunnelled files
|
||||
@ -1058,7 +1092,7 @@ bool p3GxsTunnelService::closeExistingTunnel(const RsGxsId& gxs_id)
|
||||
|
||||
{
|
||||
RsStackMutex stack(mGxsTunnelMtx); /********** STACK LOCKED MTX ******/
|
||||
std::map<RsGxsId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo>::const_iterator it = _gxs_tunnel_contacts.find(gxs_id) ;
|
||||
|
||||
if(it == _gxs_tunnel_contacts.end())
|
||||
{
|
||||
|
@ -51,6 +51,42 @@
|
||||
//
|
||||
// Data is send to a service ID (could be any existing service ID). The endpoint of the tunnel must register each service, in order to
|
||||
// allow the data to be transmitted/sent from/to that service. Otherwise an error is issued.
|
||||
//
|
||||
// Algorithms
|
||||
//
|
||||
// Tunnel establishment
|
||||
// * we need to layers: the turtle layer, and the GXS id layer.
|
||||
// * at the turtle layer:
|
||||
// - accept virtual peers from turtle tunnel service. The hash for that VP only depends on the server GXS id at server side, which is our
|
||||
// own ID at server side, and destination ID at client side. What happens if two different clients request to talk to the same GXS id? (same hash)
|
||||
// They should use different virtual peers, so it should be ok.
|
||||
// - multiple tunnels may end up to the same hash, but will correspond to different GXS tunnels since the GXS id in the other side is different.
|
||||
//
|
||||
// * at the GXS layer
|
||||
// - we should be able to have as many tunnels as they are different couples of GXS ids to interact. That means the tunnel should be determined
|
||||
// by a mix between our own GXS id and the GXS id we're talking to. That is what the TunnelVirtualPeer is.
|
||||
//
|
||||
|
||||
//
|
||||
// RequestTunnel(source_own_id,destination_id)
|
||||
// |
|
||||
// +---------------------------> p3Turtle::monitorTunnels( hash(destination_id) )
|
||||
// |
|
||||
// [Turtle async work] -------------------+
|
||||
// | |
|
||||
// handleTunnelRequest() <-----------------------------------------------+ |
|
||||
// | |
|
||||
// +---------------- keep record in _gxs_tunnel_virtual_peer_id, initiate DH exchange |
|
||||
// |
|
||||
// handleDHPublicKey() <-----------------------------------------------------------------------------+
|
||||
// |
|
||||
// +---------------- update _gxs_tunnel_contacts[ tunnel_hash = hash(own_id, destination_id) ]
|
||||
// |
|
||||
// +---------------- notify client service that Peer(destination_id, tunnel_hash) is ready to talk to
|
||||
//
|
||||
// Notes
|
||||
// * one other option would be to make the turtle hash depend on both GXS ids in a way that it is possible to find which are the two ids on the server side.
|
||||
// but that would prevent the use of unknown IDs, which we would like to offer as well.
|
||||
|
||||
#include <turtle/turtleclientservice.h>
|
||||
#include <retroshare/rsgxstunnel.h>
|
||||
@ -74,9 +110,9 @@ public:
|
||||
// Creates the invite if the public key of the distant peer is available.
|
||||
// Om success, stores the invite in the map above, so that we can respond to tunnel requests.
|
||||
//
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelClientService *client,uint32_t& error_code) ;
|
||||
virtual bool closeExistingTunnel(const RsGxsId& pid) ;
|
||||
virtual bool getTunnelStatus(const RsGxsId &gxs_id,uint32_t &status, RsGxsId *from_gxs_id=NULL) ;
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t& error_code) ;
|
||||
virtual bool closeExistingTunnel(const RsGxsTunnelId &tunnel_id) ;
|
||||
virtual bool getTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t &status);
|
||||
|
||||
private:
|
||||
void flush() ;
|
||||
@ -108,6 +144,7 @@ private:
|
||||
|
||||
DH *dh ;
|
||||
RsGxsId gxs_id ;
|
||||
RsGxsId own_gxs_id ;
|
||||
RsTurtleGenericTunnelItem::Direction direction ;
|
||||
uint32_t status ;
|
||||
TurtleFileHash hash ;
|
||||
@ -115,7 +152,7 @@ private:
|
||||
|
||||
// This maps contains the current peers to talk to with distant chat.
|
||||
//
|
||||
std::map<RsGxsId, GxsTunnelPeerInfo> _gxs_tunnel_contacts ; // current peers we can talk to
|
||||
std::map<RsGxsTunnelId,GxsTunnelPeerInfo> _gxs_tunnel_contacts ; // current peers we can talk to
|
||||
std::map<RsPeerId,GxsTunnelDHInfo> _gxs_tunnel_virtual_peer_ids ; // current virtual peers. Used to figure out tunnels, etc.
|
||||
|
||||
// List of items to be sent asap. Used to store items that we cannot pass directly to
|
||||
@ -133,7 +170,7 @@ private:
|
||||
// session handling handles
|
||||
|
||||
void markGxsTunnelAsClosed(const RsGxsId &gxs_id) ;
|
||||
void startClientGxsTunnelConnection(const RsGxsId &to_gxs_id, const RsGxsId& from_gxs_id) ;
|
||||
void startClientGxsTunnelConnection(const RsGxsId &to_gxs_id, const RsGxsId& from_gxs_id, RsGxsTunnelId &tunnel_id) ;
|
||||
void locked_restartDHSession(const RsPeerId &virtual_peer_id, const RsGxsId &own_gxs_id) ;
|
||||
|
||||
// utility functions
|
||||
@ -148,6 +185,7 @@ private:
|
||||
bool locked_initDHSessionKey(DH *&dh);
|
||||
|
||||
TurtleVirtualPeerId virtualPeerIdFromHash(const TurtleFileHash& hash) ; // ... and to a hash for p3turtle
|
||||
RsGxsTunnelId makeGxsTunnelId(const RsGxsId &own_id, const RsGxsId &distant_id) const; // creates a unique ID from two GXS ids.
|
||||
|
||||
// item handling
|
||||
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
static const uint32_t RS_GXS_TUNNEL_ERROR_NO_ERROR = 0x0000 ;
|
||||
static const uint32_t RS_GXS_TUNNEL_ERROR_UNKNOWN_GXS_ID = 0x0001 ;
|
||||
|
||||
typedef TurtleVirtualPeerId RsGxsTunnelId ;
|
||||
typedef GXSTunnelId RsGxsTunnelId ;
|
||||
|
||||
class RsGxsTunnelClientService
|
||||
{
|
||||
@ -44,12 +44,12 @@ public:
|
||||
// The client should derive this in order to handle notifications from the tunnel service.
|
||||
// This cannot be ignored because the client needs to know when the tunnel is active.
|
||||
|
||||
virtual void notifyTunnelStatus(const RsGxsId& id,uint32_t tunnel_status) =0;
|
||||
virtual void notifyTunnelStatus(const RsGxsTunnelId& tunnel_id,uint32_t tunnel_status) =0;
|
||||
|
||||
// Data obtained from the corresponding GXS id. The memory ownership is transferred to the client, which
|
||||
// is responsible to free it using free() once used.
|
||||
|
||||
virtual void receiveData(const RsGxsId& id,unsigned char *data,uint32_t data_size) =0;
|
||||
virtual void receiveData(const RsGxsTunnelId& id,const RsGxsId& from_id,unsigned char *data,uint32_t data_size) =0;
|
||||
};
|
||||
|
||||
class GxsTunnelInfo
|
||||
@ -88,7 +88,7 @@ public:
|
||||
// When the tunnel is secured, the client---here supplied as argument---will be notified. He can
|
||||
// then send data into the tunnel. The same tunnel may be used by different clients.
|
||||
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,uint32_t& error_code) =0 ;
|
||||
virtual bool requestSecuredTunnel(const RsGxsId& to_id,const RsGxsId& from_id,RsGxsTunnelId& tunnel_id,uint32_t& error_code) =0 ;
|
||||
|
||||
// Data is sent through the established tunnel, possibly multiple times, until reception is acknowledged. If the tunnel does not exist, the item is rejected and
|
||||
// an error is issued. In any case, the memory ownership of the data is transferred to the tunnel service, so the client should not use it afterwards.
|
||||
|
@ -218,6 +218,7 @@ static const uint32_t RS_GENERIC_ID_GXS_ID_TYPE = 0x0006 ;
|
||||
static const uint32_t RS_GENERIC_ID_GXS_MSG_ID_TYPE = 0x0007 ;
|
||||
static const uint32_t RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE = 0x0008 ;
|
||||
static const uint32_t RS_GENERIC_ID_GROUTER_ID_TYPE = 0x0009 ;
|
||||
static const uint32_t RS_GENERIC_ID_GXS_TUNNEL_ID_TYPE = 0x0010 ;
|
||||
|
||||
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_SSL_ID_TYPE> SSLIdType ;
|
||||
typedef t_RsGenericIdType< PGP_KEY_ID_SIZE , true, RS_GENERIC_ID_PGP_ID_TYPE> PGPIdType ;
|
||||
@ -227,4 +228,5 @@ typedef t_RsGenericIdType< PGP_KEY_FINGERPRINT_SIZE, true, RS_GENERIC_ID_PGP_F
|
||||
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_GROUP_ID_TYPE > GXSGroupId ;
|
||||
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_ID_TYPE > GXSId ;
|
||||
typedef t_RsGenericIdType< CERT_SIGN_LEN , false, RS_GENERIC_ID_GXS_CIRCLE_ID_TYPE > GXSCircleId ;
|
||||
typedef t_RsGenericIdType< SSL_ID_SIZE , false, RS_GENERIC_ID_GXS_TUNNEL_ID_TYPE > GXSTunnelId ;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user