/******************************************************************************* * libretroshare/src/turtle: rsturtleitem.h * * * * libretroshare: retroshare core library * * * * Copyright 2009-2018 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 "rsitems/rsserviceids.h" #include "rsitems/rsitem.h" #include "rsitems/itempriorities.h" #include "serialiser/rsserial.h" #include "serialiser/rstlvbase.h" #include "serialiser/rsbaseserial.h" #include "retroshare/rsturtle.h" #include "retroshare/rsexpr.h" #include "retroshare/rstypes.h" #include "turtle/turtletypes.h" #include "serialiser/rsserializer.h" const uint8_t RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST = 0x01 ; const uint8_t RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT = 0x02 ; const uint8_t RS_TURTLE_SUBTYPE_OPEN_TUNNEL = 0x03 ; const uint8_t RS_TURTLE_SUBTYPE_TUNNEL_OK = 0x04 ; const uint8_t RS_TURTLE_SUBTYPE_FILE_REQUEST = 0x07 ; const uint8_t RS_TURTLE_SUBTYPE_FILE_DATA = 0x08 ; const uint8_t RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST = 0x09 ; const uint8_t RS_TURTLE_SUBTYPE_GENERIC_DATA = 0x0a ; const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST = 0x0b ; const uint8_t RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT = 0x0c ; const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP = 0x10 ; const uint8_t RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST = 0x11 ; // const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC = 0x12 ; // unused // const uint8_t RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST = 0x13 ; const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC = 0x14 ; const uint8_t RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST = 0x15 ; const uint8_t RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA = 0x16 ; class TurtleSearchRequestInfo ; /***********************************************************************************/ /* Basic Turtle Item Class */ /***********************************************************************************/ class RsTurtleItem: public RsItem { public: RsTurtleItem(uint8_t turtle_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TURTLE,turtle_subtype) {} }; /***********************************************************************************/ /* Turtle Search Item classes */ /* Specific packets */ /***********************************************************************************/ // Class hierarchy is // // RsTurtleItem // | // +---- RsTurtleSearchRequestItem // | | // | +---- RsTurtleFileSearchRequestItem // | | | // | | +---- RsTurtleStringSearchRequestItem // | | | // | | +---- RsTurtleReqExpSearchRequestItem // | | // | +---- RsTurtleGenericSearchRequestItem // | // +---- RsTurtleSearchResultItem // | // +---- RsTurtleFTSearchResultItem // | // +---- RsTurtleGenericSearchResultItem // class RsTurtleSearchResultItem ; class RsTurtleSearchRequestItem: public RsTurtleItem { public: RsTurtleSearchRequestItem(uint32_t subtype) : RsTurtleItem(subtype), request_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_REQUEST) ;} virtual ~RsTurtleSearchRequestItem() {} virtual RsTurtleSearchRequestItem *clone() const = 0 ; // used for cloning in routing methods virtual std::string GetKeywords() = 0; virtual uint16_t serviceId() const= 0 ; uint32_t request_id ; // randomly generated request id. uint16_t depth ; // Used for limiting search depth. }; class RsTurtleFileSearchRequestItem: public RsTurtleSearchRequestItem { public: RsTurtleFileSearchRequestItem(uint32_t subtype) : RsTurtleSearchRequestItem(subtype) {} virtual ~RsTurtleFileSearchRequestItem() {} virtual uint16_t serviceId() const { return RS_SERVICE_TYPE_FILE_TRANSFER ; } virtual void search(std::list &) const =0; }; class RsTurtleStringSearchRequestItem: public RsTurtleFileSearchRequestItem { public: RsTurtleStringSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_STRING_SEARCH_REQUEST) {} virtual ~RsTurtleStringSearchRequestItem() {} virtual void search(std::list &) const ; std::string match_string ; // string to match std::string GetKeywords() { return match_string; } virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleStringSearchRequestItem(*this) ; } void clear() { match_string.clear() ; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; class RsTurtleRegExpSearchRequestItem: public RsTurtleFileSearchRequestItem { public: RsTurtleRegExpSearchRequestItem() : RsTurtleFileSearchRequestItem(RS_TURTLE_SUBTYPE_REGEXP_SEARCH_REQUEST) {} virtual ~RsTurtleRegExpSearchRequestItem() {} RsRegularExpression::LinearizedExpression expr ; // Reg Exp in linearised mode std::string GetKeywords() { RsRegularExpression::Expression *ex = RsRegularExpression::LinearizedExpression::toExpr(expr); std::string exs = ex->toStdString(); delete ex; return exs; } virtual void search(std::list &) const ; virtual RsTurtleSearchRequestItem *clone() const { return new RsTurtleRegExpSearchRequestItem(*this) ; } void clear() { expr = RsRegularExpression::LinearizedExpression(); } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; class RsTurtleGenericSearchRequestItem: public RsTurtleSearchRequestItem { public: RsTurtleGenericSearchRequestItem() : RsTurtleSearchRequestItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_REQUEST), service_id(0), search_data_len(0), request_type(0), search_data(nullptr) {} virtual ~RsTurtleGenericSearchRequestItem() { clear(); } uint16_t service_id ; // service to search uint32_t search_data_len ; uint8_t request_type ; // type of request. This is used to limit the number of responses. unsigned char *search_data ; std::string GetKeywords() ; virtual uint16_t serviceId() const { return service_id ; } virtual RsTurtleSearchRequestItem *clone() const ; virtual uint32_t requestType() const { return request_type; } void clear() { free(search_data); search_data=NULL; search_data_len=0; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); private: RsTurtleGenericSearchRequestItem(const RsTurtleGenericSearchRequestItem&); // make the object non copi-able. RsTurtleGenericSearchRequestItem& operator=(const RsTurtleGenericSearchRequestItem&) { return *this;} }; class RsTurtleSearchResultItem: public RsTurtleItem { public: RsTurtleSearchResultItem(uint8_t subtype) : RsTurtleItem(subtype), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_SEARCH_RESULT) ;} TurtleSearchRequestId request_id ; // Randomly generated request id. virtual uint32_t count() const =0; virtual void pop() =0; virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)=0; virtual RsTurtleSearchResultItem *duplicate() const =0; }; class RsTurtleFTSearchResultItem: public RsTurtleSearchResultItem { public: RsTurtleFTSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_FT_SEARCH_RESULT){} std::list result ; void clear() { result.clear() ; } uint32_t count() const { return result.size() ; } virtual void pop() { result.pop_back() ;} virtual RsTurtleSearchResultItem *duplicate() const { return new RsTurtleFTSearchResultItem(*this) ; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; class RsTurtleGenericSearchResultItem: public RsTurtleSearchResultItem { public: RsTurtleGenericSearchResultItem() : RsTurtleSearchResultItem(RS_TURTLE_SUBTYPE_GENERIC_SEARCH_RESULT), result_data(nullptr), result_data_len(0) {} virtual ~RsTurtleGenericSearchResultItem() {} uint32_t count() const { return result_data_len/50 ; } // This is a blind size estimate. We should probably use the actual size to limit search results. virtual void pop() {} unsigned char *result_data ; uint32_t result_data_len ; virtual RsTurtleSearchResultItem *duplicate() const ; void clear() { free(result_data); result_data=NULL; result_data_len=0; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; /***********************************************************************************/ /* Turtle Tunnel Item classes */ /***********************************************************************************/ class RsTurtleOpenTunnelItem: public RsTurtleItem { public: RsTurtleOpenTunnelItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_OPEN_TUNNEL), request_id(0), partial_tunnel_id(0), depth(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_OPEN_TUNNEL) ;} TurtleFileHash file_hash ; // hash to match uint32_t request_id ; // randomly generated request id. uint32_t partial_tunnel_id ; // uncomplete tunnel id. Will be completed at destination. uint16_t depth ; // Used for limiting search depth. void clear() { file_hash.clear() ;} protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; class RsTurtleTunnelOkItem: public RsTurtleItem { public: RsTurtleTunnelOkItem() : RsTurtleItem(RS_TURTLE_SUBTYPE_TUNNEL_OK), tunnel_id(0), request_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_TUNNEL_OK) ;} uint32_t tunnel_id ; // id of the tunnel. Should be identical for a tunnel between two same peers for the same hash. uint32_t request_id ; // randomly generated request id corresponding to the intial request. void clear() {} protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; /***********************************************************************************/ /* Generic turtle packets for tunnels */ /***********************************************************************************/ class RsTurtleGenericTunnelItem: public RsTurtleItem { public: RsTurtleGenericTunnelItem(uint8_t sub_packet_id) : RsTurtleItem(sub_packet_id), direction(0), tunnel_id(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_ITEM);} virtual ~RsTurtleGenericTunnelItem() {} typedef uint32_t Direction ; static const Direction DIRECTION_CLIENT = 0x001 ; static const Direction DIRECTION_SERVER = 0x002 ; /// Does this packet stamps tunnels when it passes through ? /// This is used for keeping trace weither tunnels are active or not. virtual bool shouldStampTunnel() const = 0 ; /// All tunnels derived from RsTurtleGenericTunnelItem should have a tunnel id to /// indicate which tunnel they are travelling through. virtual TurtleTunnelId tunnelId() const { return tunnel_id ; } /// Indicate weither the packet is a client packet (goign back to the /// client) or a server packet (going to the server. Typically file /// requests are server packets, whereas file data are client packets. virtual Direction travelingDirection() const { return direction ; } virtual void setTravelingDirection(Direction d) { direction = d; } Direction direction ; // This does not need to be serialised. It's only used by the client services, optionnally, // and is set by the turtle router according to which direction the item travels. uint32_t tunnel_id ; // Id of the tunnel to travel through }; /***********************************************************************************/ /* Specific Turtle Transfer items */ /***********************************************************************************/ // This item can be used by any service to pass-on arbitrary data into a tunnel. // class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem { public: RsTurtleGenericDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_DATA);} virtual ~RsTurtleGenericDataItem() { if(data_bytes != NULL) free(data_bytes) ; } virtual bool shouldStampTunnel() const { return true ; } uint32_t data_size ; void *data_bytes ; void clear() { free(data_bytes) ; data_bytes = NULL ; data_size = 0; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; // Same, but with a fact priority. Can rather be used for e.g. distant chat. // class RsTurtleGenericFastDataItem: public RsTurtleGenericTunnelItem { public: RsTurtleGenericFastDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_GENERIC_FAST_DATA), data_size(0), data_bytes(0) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_GENERIC_FAST_DATA);} virtual ~RsTurtleGenericFastDataItem() { if(data_bytes != NULL) free(data_bytes) ; } virtual bool shouldStampTunnel() const { return true ; } uint32_t data_size ; void *data_bytes ; void clear() { free(data_bytes) ; data_bytes = NULL ; data_size = 0; } protected: void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx); }; /***********************************************************************************/ /* Turtle Serialiser class */ /***********************************************************************************/ class RsTurtleSerialiser: public RsServiceSerializer { public: RsTurtleSerialiser() : RsServiceSerializer(RS_SERVICE_TYPE_TURTLE) {} virtual RsItem *create_item(uint16_t service,uint8_t item_subtype) const; // This is used by the turtle router to add services to its serialiser. // Client services are only used for deserialising, since the serialisation is // performed using the overloaded virtual functions above. // void registerClientService(RsTurtleClientService *service) { _client_services.push_back(service) ; } private: std::vector _client_services ; };