2018-11-10 14:45:05 +01:00
/*******************************************************************************
* libretroshare / src / gxs : gxsnettunnel . h *
* *
* libretroshare : retroshare core library *
* *
2018-11-11 20:42:48 +01:00
* Copyright 2018 by Cyril Soler < retroshare . project @ gmail . com > *
2018-11-10 14:45:05 +01:00
* *
* This program is free software : you can redistribute it and / or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation , either version 3 of the *
* License , or ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU Lesser General Public License for more details . *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program . If not , see < https : //www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-12-20 00:09:34 +01:00
2018-04-27 00:00:29 +02:00
# pragma once
2017-12-20 00:09:34 +01:00
# include <map>
2018-07-15 11:14:58 +02:00
# include "turtle/p3turtle.h"
# include "retroshare/rsgxsdistsync.h"
2017-12-20 00:09:34 +01:00
/*!
* \ brief The RsGxsNetTunnelService class takes care of requesting tunnels to the turtle router , through which it is possible to sync
2018-03-15 17:46:21 +01:00
* a particular GXS group . For each group , a set of virtual peers , corresponding to active tunnels will be made available
* to RsGxsNetService .
2017-12-20 00:09:34 +01:00
*
2018-03-15 17:46:21 +01:00
* It is the responsibility of RsGxsNetService to activate / desactivate tunnels for each particular group , depending on wether the group
2018-05-05 18:08:27 +02:00
* is already available at regular friends or not .
2018-03-29 10:54:58 +02:00
*
* Tunnel management is done at the level of groups rather than services , because we would like to keep the possibility to not
* request tunnels for some groups which do not need it , and only request tunnels for specific groups that cannot be provided
* by direct connections .
2017-12-20 00:09:34 +01:00
*/
2018-03-15 17:46:21 +01:00
// Protocol:
2017-12-20 00:09:34 +01:00
// * request tunnels based on H(GroupId)
// * encrypt tunnel data using chacha20+HMAC-SHA256 using AEAD( GroupId, 96bits IV, tunnel ID ) (similar to what FT does)
// * when tunnel is established, exchange virtual peer names: vpid = H( GroupID | Random bias )
// * when vpid is known, notify the client (GXS net service) which can use the virtual peer to sync
// * only use a single tunnel per virtual peer ID
2018-03-15 17:46:21 +01:00
// -
// Client ------------------ TR(H(GroupId)) --------------> Server |
// | Turtle
// Client <-------------------- T OK ---------------------- Server |
// -
// Here, a turtle vpid is known | [ addVirtualPeer() called by turtle ]
// -
// [Encrypted traffic using H(GroupId | Tunnel ID, 96bits IV)] |
// |
// Client <--------- VPID = H( Random IV | GroupId ) ------ Server |
// | | |
// +--------------> Mark the virtual peer active <-----------+ | Encrypted traffic decoded locally and sorted
// |
// Here, a consistent virtual peer ID is known |
// |
// Client <------------------- GXS Data ------------------> Server |
// -
// Notes:
2018-05-05 18:08:27 +02:00
// * tunnels are established symmetrically. If a distant peers wants to sync the same group, they'll have to open a single tunnel, with a different ID.
2018-03-29 10:54:58 +02:00
// Groups therefore have two states:
// - managed : the group can be used to answer tunnel requests. If server tunnels are established, the group will be synced with these peers
// - tunneled: the group will actively request tunnels. If tunnels are established both ways, the same virtual peers will be used so the tunnels are "merged".
// * In practice, that means one of the two tunnels will not be used and therefore die.
// * If a tunneled group already has enough virtual peers, it will not request for tunnels itself.
//
// Group policy | Request tunnels | SyncWithPeers | Item receipt
// --------------------+-------------------+-----------------------+----------------
// Passive | no | If peers present | If peers present
// Active | yes, if no peers | If peers present | If peers present
// | | |
//
// * when a service has the DistSync flag set, groups to sync are communicated passively to the GxsNetTunnel service when requesting distant peers.
// However, a call should be made to set a particular group policy to "ACTIVE" for group that do not have peers and need some.
//
// * services also need to retrieve GXS data items that come out of tunnels. These will be available as (data,len) type, since they are not de-serialized.
2018-03-29 16:26:36 +02:00
//
// * GxsNetService stores data information (such as update maps) per peerId, so it makes sense to use the same PeerId for all groups of a given service
// Therefore, virtual peers are stored separately from groups, because each one can sync multiple groups.
//
// * virtual peers are also shared among services. This reduces the required amount of tunnels and tunnel requests to send.
2018-04-01 22:04:16 +02:00
//
2018-05-05 18:08:27 +02:00
// * tunnels for a given service may also be used by the net service of p3IdService in order to explicitely request missing GxsIds.
// So GxsNetTunnel somehow allows different services to use the same tunnel. However we make sure that this traffic is limited to only p3IdService.
//
2018-04-01 22:04:16 +02:00
// How do we know that a group needs distant sync?
// * look into GrpConfigMap for suppliers. Suppliers is cleared at load.
// * last_update_TS in GrpConfigMap is randomised so it cannot be used
// * we need a way to know that there's no suppliers for good reasons (not that we just started)
2018-04-25 17:58:37 +02:00
//
// Security
2018-05-05 18:08:27 +02:00
// * the question of sync-ing with distant anonymous peers is a bit tricky because these peers can try to generate fake requests or change which messages are available
// and there is no way to prevent it. We therefore rely on GXS data integrity system to prevent this to happen.
//
2017-12-20 00:09:34 +01:00
2018-03-24 16:42:16 +01:00
class RsGxsNetTunnelItem ;
2018-06-10 22:34:17 +02:00
class RsNetworkExchangeService ;
2018-03-24 16:42:16 +01:00
2019-10-31 18:23:38 +01:00
class RsGxsNetTunnelService :
public RsTurtleClientService , public RsTickingThread , public p3Config ,
public RsGxsDistSync
2017-12-20 00:09:34 +01:00
{
public :
2018-03-15 17:46:21 +01:00
RsGxsNetTunnelService ( ) ;
2018-03-29 16:26:36 +02:00
virtual ~ RsGxsNetTunnelService ( ) ;
2017-12-20 00:09:34 +01:00
2018-06-10 22:34:17 +02:00
/*!
* \ brief registerSearchableService
* Adds the network exchange service as a possible search source . This is used to allow distant search on the corresponding
* GXS service .
* \ return
* always returns true .
*/
bool registerSearchableService ( RsNetworkExchangeService * ) ;
2017-12-20 00:09:34 +01:00
/*!
2018-03-29 10:54:58 +02:00
* \ brief Manage tunnels for this group
* @ param group_id group for which tunnels should be released
2017-12-20 00:09:34 +01:00
*/
2018-05-01 20:10:56 +02:00
bool requestDistantPeers ( uint16_t service_id , const RsGxsGroupId & group_id ) ;
2017-12-20 00:09:34 +01:00
/*!
* \ brief Stop managing tunnels for this group
* @ param group_id group for which tunnels should be released
*/
2018-05-01 20:10:56 +02:00
bool releaseDistantPeers ( uint16_t service_id , const RsGxsGroupId & group_id ) ;
2017-12-20 00:09:34 +01:00
2018-03-29 10:54:58 +02:00
/*!
* \ brief Get the list of active virtual peers for a given group . This implies that a tunnel is up and
* alive . This function also " registers " the group which allows to handle tunnel requests in the server side .
*/
2018-05-01 15:17:41 +02:00
bool getVirtualPeers ( std : : list < RsGxsNetTunnelVirtualPeerId > & peers ) ; // returns the virtual peers for this service
2018-03-22 14:41:50 +01:00
2018-06-16 22:39:35 +02:00
/*!
* \ brief serviceId
* Overloads the method in RsTurtleClientService .
* \ return
* The service id for RsGxsNetTunnel .
*/
uint16_t serviceId ( ) const ;
2017-12-20 00:09:34 +01:00
/*!
2018-03-29 10:54:58 +02:00
* \ brief sendData
2018-03-22 14:41:50 +01:00
* send data to this virtual peer , and takes memory ownership ( deletes the item )
* \ param item item to send
* \ param virtual_peer destination virtual peer
* \ return
* true if succeeded .
2017-12-20 00:09:34 +01:00
*/
2018-05-01 20:10:56 +02:00
bool sendTunnelData ( uint16_t service_id , unsigned char * & data , uint32_t data_len , const RsGxsNetTunnelVirtualPeerId & virtual_peer ) ;
2018-03-22 14:41:50 +01:00
/*!
2018-04-04 21:41:21 +02:00
* \ brief receiveData
2018-04-25 18:29:49 +02:00
* returns the next piece of data received , and the virtual GXS peer that sended it .
2018-04-04 21:41:21 +02:00
* \ param data memory check containing the data . Memory ownership belongs to the client .
* \ param data_len length of memory chunk
* \ param virtual_peer peer who sent the data
2018-03-22 14:41:50 +01:00
* \ return
2018-04-04 21:41:21 +02:00
* true if something is returned . If not , data is set to NULL , data_len to 0.
2018-03-22 14:41:50 +01:00
*/
2018-05-01 20:10:56 +02:00
bool receiveTunnelData ( uint16_t service_id , unsigned char * & data , uint32_t & data_len , RsGxsNetTunnelVirtualPeerId & virtual_peer ) ;
2018-04-04 21:41:21 +02:00
/*!
* \ brief isDistantPeer
* returns wether the peer is in the list of available distant peers or not
2018-04-25 18:52:07 +02:00
* \ param group_id returned by the service to indicate which group this peer id is designed for .
2018-04-04 21:41:21 +02:00
* \ return true if the peer is a distant GXS peer .
*/
2018-04-25 18:52:07 +02:00
bool isDistantPeer ( const RsGxsNetTunnelVirtualPeerId & virtual_peer , RsGxsGroupId & group_id ) ;
2017-12-20 00:09:34 +01:00
/*!
* \ brief dumps all information about monitored groups .
*/
void dump ( ) const ;
2018-06-06 23:15:29 +02:00
/*!
* \ brief connectToTurtleRouter
* Should be called after allocating a RsGxsNetTunnelService
* \ param tr turtle router object
*/
2018-03-15 17:46:21 +01:00
virtual void connectToTurtleRouter ( p3turtle * tr ) ;
2018-03-24 16:42:16 +01:00
2018-06-10 22:34:17 +02:00
TurtleRequestId turtleGroupRequest ( const RsGxsGroupId & group_id , RsNetworkExchangeService * client_service ) ;
TurtleRequestId turtleSearchRequest ( const std : : string & match_string , RsNetworkExchangeService * client_service ) ;
2018-06-06 23:15:29 +02:00
/*!
* \ brief receiveSearchRequest
* See RsTurtleClientService : : @
*/
2018-07-05 17:40:06 +02:00
virtual bool receiveSearchRequest ( unsigned char * search_request_data , uint32_t search_request_data_len , unsigned char * & search_result_data , uint32_t & search_result_data_len , uint32_t & max_allowed_hits ) ;
2018-06-10 22:34:17 +02:00
virtual void receiveSearchResult ( TurtleSearchRequestId request_id , unsigned char * search_result_data , uint32_t search_result_data_len ) ;
2018-06-06 23:15:29 +02:00
2019-10-31 18:23:38 +01:00
void threadTick ( ) override ; /// @see RsTickingThread
2018-03-24 16:42:16 +01:00
2018-05-01 20:10:56 +02:00
// Overloads p3Config
RsSerialiser * setupSerialiser ( ) ;
bool saveList ( bool & cleanup , std : : list < RsItem * > & save ) ;
bool loadList ( std : : list < RsItem * > & load ) ;
2018-07-15 11:14:58 +02:00
// Overloads RsGxsDistSync
void getStatistics ( std : : map < RsGxsGroupId , RsGxsNetTunnelGroupInfo > & groups , // groups on the client and server side
std : : map < RsGxsNetTunnelVirtualPeerId , RsGxsNetTunnelVirtualPeerInfo > & virtual_peers , // current virtual peers, which group they provide, and how to talk to them through turtle
2018-07-15 19:09:12 +02:00
std : : map < TurtleVirtualPeerId , RsGxsNetTunnelVirtualPeerId > & turtle_vpid_to_net_tunnel_vpid ,
2018-07-15 11:14:58 +02:00
Bias20Bytes & bias ) const ;
2018-03-15 17:46:21 +01:00
protected :
// interaction with turtle router
virtual bool handleTunnelRequest ( const RsFileHash & hash , const RsPeerId & peer_id ) ;
2018-06-06 23:15:29 +02:00
virtual void receiveTurtleData ( const RsTurtleGenericTunnelItem * item , const RsFileHash & hash , const RsPeerId & virtual_peer_id , RsTurtleGenericTunnelItem : : Direction direction ) ;
2018-03-15 17:46:21 +01:00
void addVirtualPeer ( const TurtleFileHash & , const TurtleVirtualPeerId & , RsTurtleGenericTunnelItem : : Direction dir ) ;
void removeVirtualPeer ( const TurtleFileHash & , const TurtleVirtualPeerId & ) ;
2018-05-01 20:10:56 +02:00
const Bias20Bytes & locked_randomBias ( ) ;
2018-03-15 17:46:21 +01:00
p3turtle * mTurtle ;
2018-04-27 00:00:29 +02:00
static const uint32_t RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE = 20 ;
static const uint32_t RS_GXS_TUNNEL_CONST_EKEY_SIZE = 32 ;
2018-04-29 16:19:45 +02:00
mutable Bias20Bytes mRandomBias ; // constant accross reboots. Allows to disguise the real SSL id while providing a consistent value accross time.
2017-12-20 00:09:34 +01:00
private :
2018-03-24 16:42:16 +01:00
void autowash ( ) ;
2018-04-11 23:14:10 +02:00
void sendKeepAlivePackets ( ) ;
2018-03-24 16:42:16 +01:00
void handleIncoming ( RsGxsNetTunnelItem * item ) ;
2018-04-02 17:07:32 +02:00
void flush_pending_items ( ) ;
2018-03-24 16:42:16 +01:00
2018-03-22 14:41:50 +01:00
std : : map < RsGxsGroupId , RsGxsNetTunnelGroupInfo > mGroups ; // groups on the client and server side
2017-12-20 00:09:34 +01:00
2018-03-29 16:26:36 +02:00
std : : map < RsGxsNetTunnelVirtualPeerId , RsGxsNetTunnelVirtualPeerInfo > mVirtualPeers ; // current virtual peers, which group they provide, and how to talk to them through turtle
std : : map < RsFileHash , RsGxsGroupId > mHandledHashes ; // hashes asked to turtle. Used to answer tunnel requests
std : : map < TurtleVirtualPeerId , RsGxsNetTunnelVirtualPeerId > mTurtle2GxsPeer ; // convertion table to find GXS peer id from turtle
2017-12-20 00:09:34 +01:00
2018-04-02 17:07:32 +02:00
std : : list < std : : pair < TurtleVirtualPeerId , RsTurtleGenericDataItem * > > mPendingTurtleItems ; // items that need to be sent off-turtle Mutex.
2018-05-01 20:10:56 +02:00
std : : map < uint16_t , std : : list < std : : pair < RsGxsNetTunnelVirtualPeerId , RsTlvBinaryData * > > > mIncomingData ; // list of incoming data items
2018-04-04 21:41:21 +02:00
2018-06-10 22:34:17 +02:00
std : : map < uint16_t , RsNetworkExchangeService * > mSearchableServices ;
2017-12-20 00:09:34 +01:00
/*!
* \ brief Generates the hash to request tunnels for this group . This hash is only used by turtle , and is used to
* hide the real group id .
*/
2018-03-21 22:09:40 +01:00
RsFileHash calculateGroupHash ( const RsGxsGroupId & group_id ) const ;
2017-12-20 00:09:34 +01:00
/*!
* \ brief makeVirtualPeerIdForGroup creates a virtual peer id that can be used and that will be constant accross time , whatever the
* tunnel ID and turtle virtual peer id . This allows RsGxsNetService to keep sync - ing the data consistently .
*/
2018-05-01 20:10:56 +02:00
RsGxsNetTunnelVirtualPeerId locked_makeVirtualPeerId ( const RsGxsGroupId & group_id ) ;
2018-03-21 22:09:40 +01:00
2018-03-29 16:26:36 +02:00
static void generateEncryptionKey ( const RsGxsGroupId & group_id , const TurtleVirtualPeerId & vpid , unsigned char key [ RS_GXS_TUNNEL_CONST_EKEY_SIZE ] ) ;
2017-12-20 00:09:34 +01:00
2018-03-22 14:41:50 +01:00
mutable RsMutex mGxsNetTunnelMtx ;
2018-04-27 00:00:29 +02:00
friend class RsGxsTunnelRandomBiasItem ;
friend class StoreHere ;
2018-04-29 19:20:14 +02:00
2018-10-07 01:34:05 +02:00
rstime_t mLastKeepAlive ;
rstime_t mLastAutoWash ;
rstime_t mLastDump ;
2017-12-20 00:09:34 +01:00
} ;