RetroShare/libretroshare/src/gxstunnel/p3gxstunnel.h

208 lines
9.2 KiB
C
Raw Normal View History

/*
* libretroshare/src/chat: distantchat.h
*
* Services for RetroShare.
*
* Copyright 2015 by Cyril Soler
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "csoler@users.sourceforge.net".
*
*/
#pragma once
// Generic tunnel service
//
// Preconditions:
// * multiple services can use the same tunnel
// * tunnels are automatically encrypted and ensure transport (items stored in a queue until ACKed by the other side)
// * each tunnel is associated to a specific GXS id on both sides. Consequently, services that request tunnels from different IDs to a
// server for the same GXS id need to be handled correctly.
//
// GUI
// * the GUI should show for each tunnel:
// - starting and ending GXS ids
// - tunnel status (DH ok, closed from distant peer, locally closed, etc)
// - amount of data that is transferred in the tunnel
// - number of pending items (and total size)
// - number ACKed items both ways.
//
// we can use an additional tab "Authenticated tunnels" in the statistics->turtle window
//
// Interaction with services:
//
// Services request tunnels from a given GXS id and to a given GXS id. When ready, they get a handle (virtual peer id)
//
// Services send data in the tunnel using the virtual peer id
//
// 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>
2015-11-18 23:56:35 -05:00
#include <gxstunnel/rsgxstunnelitems.h>
class RsGixs ;
static const uint32_t GXS_TUNNEL_AES_KEY_SIZE = 16 ;
class p3GxsTunnelService: public RsGxsTunnelService, public RsTurtleClientService
{
public:
p3GxsTunnelService(RsGixs *pids)
: mGixs(pids), mGxsTunnelMtx("GXS tunnel")
{
mTurtle = NULL ;
}
virtual void connectToTurtleRouter(p3turtle *) ;
// 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,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() ;
virtual bool handleIncomingItem(RsGxsTunnelItem *) ;
class GxsTunnelPeerInfo
{
public:
GxsTunnelPeerInfo() : last_contact(0), last_keep_alive_sent(0), status(0), direction(0)
{
memset(aes_key, 0, GXS_TUNNEL_AES_KEY_SIZE);
}
time_t last_contact ; // used to keep track of working connexion
time_t last_keep_alive_sent ; // last time we sent a keep alive packet.
unsigned char aes_key[GXS_TUNNEL_AES_KEY_SIZE] ;
uint32_t status ; // info: do we have a tunnel ?
RsPeerId virtual_peer_id; // given by the turtle router. Identifies the tunnel.
RsGxsId own_gxs_id ; // gxs id we're using to talk.
RsTurtleGenericTunnelItem::Direction direction ; // specifiec wether we are client(managing the tunnel) or server.
};
class GxsTunnelDHInfo
{
public:
GxsTunnelDHInfo() : dh(0), direction(0), status(0) {}
DH *dh ;
RsGxsId gxs_id ;
RsGxsId own_gxs_id ;
RsTurtleGenericTunnelItem::Direction direction ;
uint32_t status ;
TurtleFileHash hash ;
};
// This maps contains the current peers to talk to with distant chat.
//
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
// sendTurtleData(), because of Mutex protection.
std::list<RsGxsTunnelItem*> pendingGxsTunnelItems ;
// Overloaded from RsTurtleClientService
virtual bool handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) ;
virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ;
void addVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&,RsTurtleGenericTunnelItem::Direction dir) ;
void removeVirtualPeer(const TurtleFileHash&, const TurtleVirtualPeerId&) ;
// session handling handles
void markGxsTunnelAsClosed(const RsGxsId &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
static TurtleFileHash hashFromGxsId(const RsGxsId& destination) ;
static RsGxsId gxsIdFromHash(const TurtleFileHash& sum) ;
// Cryptography management
void handleRecvDHPublicKey(RsGxsTunnelDHPublicKeyItem *item) ;
bool locked_sendDHPublicKey(const DH *dh, const RsGxsId& own_gxs_id, const RsPeerId& virtual_peer_id) ;
bool locked_initDHSessionKey(DH *&dh);
2015-11-18 23:56:35 -05:00
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
void handleRecvStatusItem(RsGxsTunnelStatusItem *item) ;
// Comunication with Turtle service
void sendTurtleData(RsGxsTunnelItem *) ;
void sendEncryptedTurtleData(const uint8_t *buff,uint32_t rssize,const RsGxsId &gxs_id) ;
bool handleEncryptedData(const uint8_t *data_bytes,uint32_t data_size,const TurtleFileHash& hash,const RsPeerId& virtual_peer_id) ;
static TurtleFileHash hashFromVirtualPeerId(const DistantChatPeerId& peerId) ; // converts IDs so that we can talk to RsPeerId from outside
// local data
p3turtle *mTurtle ;
RsGixs *mGixs ;
RsMutex mGxsTunnelMtx ;
};