From 5566d90f328d383a9136d38d86b80e5b33974352 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 24 Mar 2018 16:42:16 +0100 Subject: [PATCH] finished tunnel handling and data send/recv in GxsNetTunnel --- libretroshare/src/gxs/rsgxsnettunnel.cc | 187 +++++++++++++++++++++--- libretroshare/src/gxs/rsgxsnettunnel.h | 14 +- 2 files changed, 181 insertions(+), 20 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc index e9c389454..5e7fe557d 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ b/libretroshare/src/gxs/rsgxsnettunnel.cc @@ -25,14 +25,77 @@ #include "util/rsdir.h" #include "retroshare/rspeers.h" +#include "serialiser/rstypeserializer.h" #include "rsgxsnettunnel.h" #define DEBUG_RSGXSNETTUNNEL 1 -#define NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } +#define GXS_NET_TUNNEL_NOT_IMPLEMENTED() { std::cerr << __PRETTY_FUNCTION__ << ": not yet implemented." << std::endl; } +#define GXS_NET_TUNNEL_DEBUG() std::cerr << time(NULL) << " : GXS_NET_TUNNEL : " << __FUNCTION__ << " : " +#define GXS_NET_TUNNEL_ERROR() std::cerr << "(EE) GXS_NET_TUNNEL ERROR : " + RsGxsNetTunnelService::RsGxsNetTunnelService(): mGxsNetTunnelMtx("GxsNetTunnel") {} +//===========================================================================================================================================// +// Transport Items // +//===========================================================================================================================================// + +const uint16_t RS_SERVICE_TYPE_GXS_NET_TUNNEL = 0x2233 ; + +const uint8_t RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER = 0x01 ; + +class RsGxsNetTunnelItem: public RsItem +{ +public: + explicit RsGxsNetTunnelItem(uint8_t item_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_GXS_NET_TUNNEL,item_subtype) + { + // no priority. All items are encapsulated into generic Turtle items anyway. + } + + virtual ~RsGxsNetTunnelItem() {} + virtual void clear() {} +}; + +class RsGxsNetTunnelVirtualPeerItem: public RsGxsNetTunnelItem +{ +public: + RsGxsNetTunnelVirtualPeerItem() :RsGxsNetTunnelItem(RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER) {} + explicit RsGxsNetTunnelVirtualPeerItem(uint8_t subtype) :RsGxsNetTunnelItem(subtype) {} + + virtual ~RsGxsNetTunnelVirtualPeerItem() {} + + virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx) + { + RsTypeSerializer::serial_process(j,ctx,virtual_peer_id,"virtual_peer_id") ; + } + + RsPeerId virtual_peer_id ; +}; + +class RsGxsNetTunnelSerializer: public RsServiceSerializer +{ +public: + RsGxsNetTunnelSerializer() :RsServiceSerializer(RS_SERVICE_TYPE_GXS_NET_TUNNEL) {} + + virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const + { + if(service != RS_SERVICE_TYPE_GXS_NET_TUNNEL) + { + GXS_NET_TUNNEL_ERROR() << "received item with wrong service ID " << std::hex << service << std::dec << std::endl; + return NULL ; + } + + switch(item_subtype) + { + case RS_PKT_SUBTYPE_GXS_NET_TUNNEL_VIRTUAL_PEER: return new RsGxsNetTunnelVirtualPeerItem ; + default: + GXS_NET_TUNNEL_ERROR() << "type ID " << std::hex << item_subtype << std::dec << " is not handled!" << std::endl; + return NULL ; + } + } +}; + //===========================================================================================================================================// // Interface with rest of the software // //===========================================================================================================================================// @@ -57,8 +120,7 @@ bool RsGxsNetTunnelService::manage(const RsGxsGroupId& group_id) mHandledHashes[hash] = group_id ; #ifdef DEBUG_GXS_TUNNEL - std::cerr << "Starting distant chat to " << to_gxs_id << ", hash = " << hash << ", from " << from_gxs_id << std::endl; - std::cerr << "Asking turtle router to monitor tunnels for hash " << hash << std::endl; + GXS_NET_TUNNEL_DEBUG() << "Asking turtle router to monitor tunnels for hash " << hash << std::endl; #endif // Now ask the turtle router to manage a tunnel for that hash. @@ -78,7 +140,7 @@ bool RsGxsNetTunnelService::release(const RsGxsGroupId& group_id) if(it == mGroups.end()) { - std::cerr << "RsGxsNetTunnelService::release(): Weird. Cannot release client group " << group_id << " that is not known." << std::endl; + GXS_NET_TUNNEL_ERROR() << "RsGxsNetTunnelService::release(): Weird. Cannot release client group " << group_id << " that is not known." << std::endl; return false ; } @@ -110,7 +172,7 @@ bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualP if(it == mVirtualPeers.end()) { - std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; + GXS_NET_TUNNEL_ERROR() << "cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; return false ; } @@ -118,7 +180,7 @@ bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualP if(it2 == mGroups.end()) { - std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; + GXS_NET_TUNNEL_ERROR() << "cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl; return false ; } @@ -126,13 +188,13 @@ bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualP if(it3 == it2->second.virtual_peers.end()) { - std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find turtle virtual peer " << it->second.second << ". Data is dropped." << std::endl; + std::cerr << "cannot find turtle virtual peer " << it->second.second << ". Data is dropped." << std::endl; return false ; } if(it3->second.vpid_status != RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE) { - std::cerr << "(EE) RsGxsNetTunnelService::sendData(): virtual peer " << it->second.second << " is not active. Data is dropped." << std::endl; + GXS_NET_TUNNEL_ERROR() << "virtual peer " << it->second.second << " is not active. Data is dropped." << std::endl; return false ; } @@ -140,12 +202,14 @@ bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualP RsTurtleGenericDataItem *encrypted_turtle_item = NULL ; - NOT_IMPLEMENTED(); - // if(!p3Turtle::encryptItem(item,it3->second.encryption_master_key,encrypted_turtle_item)) - // { - // std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot encrypt. Something's wrong. Data is dropped." << std::endl; - // return false ; - // } + uint32_t serialized_size = 0; // TODO + RsTemporaryMemory data(serialized_size) ; + + if(!p3turtle::encryptData(data,serialized_size,it3->second.encryption_master_key,encrypted_turtle_item)) + { + GXS_NET_TUNNEL_ERROR() << "cannot encrypt. Something's wrong. Data is dropped." << std::endl; + return false ; + } mTurtle->sendTurtleData(it->second.second,encrypted_turtle_item) ; @@ -155,7 +219,7 @@ bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualP bool RsGxsNetTunnelService::getVirtualPeers(const RsGxsGroupId&, std::list& peers) { // returns the virtual peers for this group - NOT_IMPLEMENTED(); + GXS_NET_TUNNEL_NOT_IMPLEMENTED(); return false ; } @@ -227,7 +291,7 @@ void RsGxsNetTunnelService::connectToTurtleRouter(p3turtle *tr) bool RsGxsNetTunnelService::handleTunnelRequest(const RsFileHash &hash,const RsPeerId& peer_id) { - NOT_IMPLEMENTED(); + GXS_NET_TUNNEL_NOT_IMPLEMENTED(); // at this point we need to talk to the client services // There's 2 ways to do that: @@ -236,10 +300,70 @@ bool RsGxsNetTunnelService::handleTunnelRequest(const RsFileHash &hash,const RsP return true ; } + void RsGxsNetTunnelService::receiveTurtleData(RsTurtleGenericTunnelItem *item,const RsFileHash& hash,const RsPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) { - NOT_IMPLEMENTED(); + GXS_NET_TUNNEL_NOT_IMPLEMENTED(); + + if(item->PacketSubType() != RS_TURTLE_SUBTYPE_GENERIC_DATA) + { + GXS_NET_TUNNEL_ERROR() << "item with type " << std::hex << item->PacketSubType() << std::dec << " received by GxsNetTunnel, but is not handled!" << std::endl; + return; + } + + // (cyril) this is a bit complicated. We should store pointers to the encryption keys in another structure and access it directly. + + auto it = mHandledHashes.find(hash) ; + + if(it == mHandledHashes.end()) + { + GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for hash " << hash << " but this hash is unknown!" << std::endl; + return; + } + + RsGxsGroupId group_id = it->second; + + auto it2 = mGroups.find(group_id) ; + + if(it2 == mGroups.end()) + { + GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for hash " << hash << " and group " << group_id << " but this group id is unknown!" << std::endl; + return; + } + + RsGxsNetTunnelGroupInfo& g_info(it2->second) ; + + g_info.last_contact = time(NULL) ; + + auto it3 = g_info.virtual_peers.find(virtual_peer_id) ; + + if(it3 == g_info.virtual_peers.end()) + { + GXS_NET_TUNNEL_ERROR() << "item received by GxsNetTunnel for hash " << hash << ", group " << group_id << " but the virtual peer id is missing!" << std::endl; + return; + } + + RsGxsNetTunnelVirtualPeerInfo& vp_info(it3->second) ; + + unsigned char *data = NULL ; + uint32_t data_size = 0 ; + + if(!p3turtle::decryptItem(static_cast(item),vp_info.encryption_master_key,data,data_size)) + { + GXS_NET_TUNNEL_ERROR() << "Cannot decrypt data!" << std::endl; + + if(data) + free(data) ; + + return ; + } + + RsGxsNetTunnelItem *decrypted_item = dynamic_cast(RsGxsNetTunnelSerializer().deserialise(data,&data_size)) ; + free(data); + + handleIncoming(decrypted_item); } + void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid,RsTurtleGenericTunnelItem::Direction dir) { auto it = mHandledHashes.find(hash) ; @@ -258,11 +382,25 @@ void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const Tur RsGxsNetTunnelVirtualPeerInfo& vpinfo( ginfo.virtual_peers[vpid] ) ; vpinfo.vpid_status = RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK ; - vpinfo.net_service_virtual_peer.clear(); vpinfo.side = dir ; vpinfo.last_contact = time(NULL) ; generateEncryptionKey(group_id,vpid,vpinfo.encryption_master_key ); + + // If we're a server, we need to send our own virtual peer id to the client + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) + { + vpinfo.net_service_virtual_peer = makeServerVirtualPeerIdForGroup(group_id); + + RsGxsNetTunnelVirtualPeerItem *pitem = new RsGxsNetTunnelVirtualPeerItem ; + + pitem->virtual_peer_id = vpinfo.net_service_virtual_peer ; + + vpinfo.outgoing_items.push_back(pitem) ; + } + else + vpinfo.net_service_virtual_peer.clear(); } void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid) @@ -309,6 +447,19 @@ void RsGxsNetTunnelService::generateEncryptionKey(const RsGxsGroupId& group_id,c // Service parts // //===========================================================================================================================================// +void RsGxsNetTunnelService::data_tick() +{ + GXS_NET_TUNNEL_DEBUG() << std::endl; + + // cleanup + + autowash(); +} + +void RsGxsNetTunnelService::autowash() +{ +} + #ifdef TODO void RsGxsNetTunnelService::handleIncomingItem(const RsGxsTunnelId& tunnel_id,RsGxsTunnelItem *item) { diff --git a/libretroshare/src/gxs/rsgxsnettunnel.h b/libretroshare/src/gxs/rsgxsnettunnel.h index 2f6cb0eae..16f00de4b 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.h +++ b/libretroshare/src/gxs/rsgxsnettunnel.h @@ -66,6 +66,8 @@ typedef RsPeerId RsGxsNetTunnelVirtualPeerId ; +class RsGxsNetTunnelItem ; + struct RsGxsNetTunnelVirtualPeerInfo { enum { RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN = 0x00, // unknown status. @@ -77,7 +79,7 @@ struct RsGxsNetTunnelVirtualPeerInfo uint8_t vpid_status ; // status of the peer uint8_t side ; // client/server - uint8_t encryption_master_key[16] ; // key from which the encryption key is derived for each virtual peer (using H(master_key | random IV)) + uint8_t encryption_master_key[32] ; // key from which the encryption key is derived for each virtual peer (using H(master_key | random IV)) time_t last_contact ; // last time some data was sent/recvd RsGxsNetTunnelVirtualPeerId net_service_virtual_peer ; // anonymised peer that is used to communicate with client services @@ -103,7 +105,7 @@ struct RsGxsNetTunnelGroupInfo std::map virtual_peers ; }; -class RsGxsNetTunnelService: public RsTurtleClientService +class RsGxsNetTunnelService: public RsTurtleClientService, public RsTickingThread { public: RsGxsNetTunnelService() ; @@ -156,6 +158,11 @@ public: // - method to encrypt/decrypt data and send/receive to/from turtle. virtual void connectToTurtleRouter(p3turtle *tr) ; + + // Overloaded from RsTickingThread + + void data_tick() ; + protected: // interaction with turtle router @@ -166,6 +173,9 @@ protected: p3turtle *mTurtle ; private: + void autowash() ; + void handleIncoming(RsGxsNetTunnelItem *item) ; + static const uint32_t RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE = 16 ; static const uint32_t RS_GXS_TUNNEL_CONST_EKEY_SIZE = 32 ;