/******************************************************************************* * libretroshare/src/grouter: p3grouter.h * * * * libretroshare: retroshare core library * * * * Copyright 2013 by Cyril Soler * * * * 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 . * * * *******************************************************************************/ #pragma once #include #include #include #include "retroshare/rsgrouter.h" #include "retroshare/rstypes.h" #include "retroshare/rstypes.h" #include "retroshare/rsidentity.h" #include "turtle/turtleclientservice.h" #include "services/p3service.h" #include "pqi/p3cfgmgr.h" #include "util/rsdebug.h" #include "groutertypes.h" #include "groutermatrix.h" #include "grouteritems.h" // To be put in pqi/p3cfgmgr.h static const uint32_t CONFIG_TYPE_GROUTER = 0x0016 ; class p3LinkMgr ; class p3turtle ; class RsGixs ; class RsGRouterItem ; class RsGRouterGenericDataItem ; class RsGRouterSignedReceiptItem ; class RsGRouterAbstractMsgItem ; class RsGRouterTransactionItem ; class RsGRouterTransactionAcknItem ; // This class is responsible for accepting data chunks and merging them into a final object. When the object is // complete, it is de-serialised and returned as a RsGRouterGenericDataItem*. class GRouterTunnelInfo { public: GRouterTunnelInfo() :first_tunnel_ok_TS(0), last_tunnel_ok_TS(0) {} // These two methods handle the memory management of buffers for each virtual peers. void addVirtualPeer(const TurtleVirtualPeerId& vpid) ; void removeVirtualPeer(const TurtleVirtualPeerId& vpid) ; std::set virtual_peers ; rstime_t first_tunnel_ok_TS ; // timestamp when 1st tunnel was received. rstime_t last_tunnel_ok_TS ; // timestamp when last tunnel was received. }; class GRouterDataInfo { // ! This class does not have a copy constructor that duplicates the incoming data buffer. This is on purpose! public: GRouterDataInfo() : last_activity_TS(0) { incoming_data_buffer = NULL ; } void clear() { if(incoming_data_buffer!=NULL) delete incoming_data_buffer ; incoming_data_buffer = NULL ;} // These two methods handle the memory management of buffers for each virtual peers. RsGRouterAbstractMsgItem *addDataChunk(RsGRouterTransactionChunkItem *chunk_item) ; RsGRouterTransactionChunkItem *incoming_data_buffer ; rstime_t last_activity_TS ; }; class p3GRouter: public RsGRouter, public RsTurtleClientService, public p3Service, public p3Config { public: p3GRouter(p3ServiceControl *sc,RsGixs *is) ; //===================================================// // Router clients business // //===================================================// // This method allows to associate client ids (that are saved to disk) to client objects deriving // from GRouterClientService. The various services are responsible for regstering themselves to the // global router, with consistent ids. The services are stored in a map, and arriving objects are // passed on the correct service depending on the client id of the key they are reaching. // virtual bool registerClientService(const GRouterServiceId& id,GRouterClientService *service) ; // Use this method to register/unregister a key that the global router will // forward in the network, so that is can be a possible destination for // global messages. // // auth_id : The GXS key that will be used to sign the data Receipts. // contact_key : The key that is used to open tunnels // desc_str : Any fixed length string (< 20 characters) to descript the address in words. // client_id : Id of the client service to send the traffic to. // The client ID should match the ID that has been registered using the previous method. // // Unregistering a key might not have an instantaneous effect, so the client is responsible for // discarding traffic that might later come for this key. // virtual bool registerKey(const RsGxsId& authentication_id, const GRouterServiceId& client_id,const std::string& description_string) ; virtual bool unregisterKey(const RsGxsId &key_id, const GRouterServiceId &sid) ; //===================================================// // Routing clue collection methods // //===================================================// virtual void addRoutingClue( const RsGxsId& id, const RsPeerId& peer_id) override; //===================================================// // Client/server request services // //===================================================// // Sends an item to the given destination. The router takes ownership of // the memory. That means item_data will be erase on return. The returned id should be // remembered by the client, so that he knows when the data has been received. // The client id is supplied so that the client can be notified when the data has been received. // Data is not modified by the global router. // virtual bool sendData(const RsGxsId& destination, const GRouterServiceId& client_id, const uint8_t *data, uint32_t data_size, const RsGxsId& signing_id, GRouterMsgPropagationId& id) ; // Cancels a given sending order. If called too late, the message might already have left. But this will remove the item from the // re-try list. virtual bool cancel(GRouterMsgPropagationId mid) ; //===================================================// // Interface with RsGRouter // //===================================================// // debug info from routing matrix // - list of known key ids // - list of clues/time_stamp for each key. // - real time routing probabilities // virtual bool getRoutingMatrixInfo(GRouterRoutingMatrixInfo& info) ; // debug info from routing cache // - Cache Items // * which message ids // * directions // * timestamp // * message type // - Cache state (memory size, etc) // virtual bool getRoutingCacheInfo(std::vector& info) ; //===================================================// // Derived from p3Service // //===================================================// virtual RsServiceInfo getServiceInfo() { return RsServiceInfo(RS_SERVICE_TYPE_GROUTER, SERVICE_INFO_APP_NAME, SERVICE_INFO_APP_MAJOR_VERSION, SERVICE_INFO_APP_MINOR_VERSION, SERVICE_INFO_MIN_MAJOR_VERSION, SERVICE_INFO_MIN_MINOR_VERSION) ; } virtual void setDebugEnabled(bool b) { _debug_enabled = b ; } virtual void connectToTurtleRouter(p3turtle *pt) ; protected: //===================================================// // Routing method handling // //===================================================// // Calls // - packet handling methods // - matrix updates // virtual int tick() ; static const std::string SERVICE_INFO_APP_NAME ; static const uint16_t SERVICE_INFO_APP_MAJOR_VERSION = 1; static const uint16_t SERVICE_INFO_APP_MINOR_VERSION = 0; static const uint16_t SERVICE_INFO_MIN_MAJOR_VERSION = 1; static const uint16_t SERVICE_INFO_MIN_MINOR_VERSION = 0; //===================================================// // Interaction with turtle router // //===================================================// uint16_t serviceId() const { return RS_SERVICE_TYPE_GROUTER; } virtual bool handleTunnelRequest(const RsFileHash& /*hash*/,const RsPeerId& /*peer_id*/) ; virtual void receiveTurtleData(const RsTurtleGenericTunnelItem */*item*/,const RsFileHash& /*hash*/,const RsPeerId& /*virtual_peer_id*/,RsTurtleGenericTunnelItem::Direction /*direction*/); virtual void addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) ; virtual void removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) ; private: //===================================================// // Low level item sorting // //===================================================// void handleLowLevelServiceItems() ; void handleLowLevelServiceItem(RsGRouterTransactionItem*) ; void handleLowLevelTransactionChunkItem(RsGRouterTransactionChunkItem *chunk_item); void handleLowLevelTransactionAckItem(RsGRouterTransactionAcknItem*) ; static Sha1CheckSum computeDataItemHash(const RsGRouterGenericDataItem *data_item); std::ostream& grouter_debug() const { static std::ostream null(0); return _debug_enabled?(std::cerr):null; } void routePendingObjects() ; void handleTunnels() ; void autoWash() ; //===================================================// // High level item sorting // //===================================================// void handleIncoming() ; void handleIncomingItem(const RsGRouterAbstractMsgItem *item); void handleIncomingReceiptItem(const RsGRouterSignedReceiptItem *receipt_item) ; void handleIncomingDataItem(const RsGRouterGenericDataItem *data_item) ; bool locked_getLocallyRegisteredClientFromServiceId(const GRouterServiceId& service_id,GRouterClientService *& client); // utility functions // static float computeMatrixContribution(float base,uint32_t time_shift,float probability) ; static bool sliceDataItem(RsGRouterAbstractMsgItem *,std::list& chunks) ; uint32_t computeRandomDistanceIncrement(const RsPeerId& pid,const GRouterKeyId& destination_id) ; // signs an item with the given key. bool signDataItem(RsGRouterAbstractMsgItem *item,const RsGxsId& id) ; bool verifySignedDataItem(const RsGRouterAbstractMsgItem *item, const RsIdentityUsage::UsageCode &info, uint32_t &error_status) ; bool encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& destination_key) ; bool decryptDataItem(RsGRouterGenericDataItem *item) ; static Sha1CheckSum makeTunnelHash(const RsGxsId& destination,const GRouterServiceId& client); //bool locked_getGxsIdAndClientId(const TurtleFileHash &sum,RsGxsId& gxs_id,GRouterServiceId& client_id); bool locked_sendTransactionData(const RsPeerId& pid,const RsGRouterTransactionItem& item); void locked_collectAvailableFriends(const GRouterKeyId &gxs_id, const std::set& incoming_routes,uint32_t duplication_factor, std::map &friend_peers_and_duplication_factors); void locked_collectAvailableTunnels(const TurtleFileHash& hash, uint32_t total_duplication, std::map &tunnel_peers_and_duplication_factors); void locked_sendToPeers(RsGRouterGenericDataItem *data_item, const std::map &peers_and_duplication_factors); //===================================================// // p3Config methods // //===================================================// // Load/save the routing info, the pending items in transit, and the config variables. // virtual bool loadList(std::list& items) ; virtual bool saveList(bool& cleanup,std::list& items) ; virtual RsSerialiser *setupSerialiser() ; //===================================================// // Debug methods // //===================================================// // Prints the internal state of the router, for debug purpose. // void debugDump() ; //===================================================// // Internal queues/variables // //===================================================// // Stores the routing info // - list of known key ids // - list of clues/time_stamp for each key. // - real time routing probabilities // GRouterMatrix _routing_matrix ; // Stores the keys which identify the router's node. For each key, a structure holds: // - the client service // - flags // - usage time stamps // std::map _owned_key_ids ; // Registered services. These are known to the different peers with a common id, // so it's important to keep consistency here. This map is volatile, and re-created at each startup of // the software, when newly created services register themselves. std::map _registered_services ; // Stores the routing events. // - ongoing requests, waiting for return ACK // - pending items // Both a stored in 2 different lists, to allow a more efficient handling. // std::map _pending_messages;// pending messages // Stores virtual peers that appear/disappear as the result of the turtle router client // std::map _tunnels ; // Stores incoming data from any peers (virtual and real) into chunks that get aggregated until finished. // std::map _incoming_data_pipes ; // Queue of incoming items. Might be receipts or data. Should always be empty (not a storage place) std::list _incoming_items ; // Data handling methods // //void handleRecvDataItem(RsGRouterGenericDataItem *item); //void handleRecvReceiptItem(RsGRouterReceiptItem *item); // Pointers to other RS objects // p3ServiceControl *mServiceControl ; p3turtle *mTurtle ; RsGixs *mGixs ; //p3LinkMgr *mLinkMgr ; // Multi-thread protection mutex. // RsMutex grMtx ; // config update/save variables bool _changed ; bool _debug_enabled ; rstime_t _last_autowash_time ; rstime_t _last_matrix_update_time ; rstime_t _last_debug_output_time ; rstime_t _last_config_changed ; uint64_t _random_salt ; /** Temporarly store items that could not have been verified yet due to * missing author key, attempt to handle them once in a while. * The items are discarded if after mMissingKeyQueueEntryTimeout the key * hasn't been received yet, and are not saved on RetroShare stopping. */ std::list< std::pair< std::unique_ptr, rstime_t > > mMissingKeyQueue; RsMutex mMissingKeyQueueMtx; /// protect mMissingKeyQueue /// @see mMissingKeyQueue static constexpr rstime_t mMissingKeyQueueEntryTimeout = 600; /// @see mMissingKeyQueue static constexpr rstime_t mMissingKeyQueueCheckEvery = 30; /// @see mMissingKeyQueue rstime_t mMissingKeyQueueCheckLastCheck = 0; RS_SET_CONTEXT_DEBUG_LEVEL(2) };