diff --git a/libretroshare/src/ft/ftcontroller.cc b/libretroshare/src/ft/ftcontroller.cc index 99a63e5ea..dc3d29068 100644 --- a/libretroshare/src/ft/ftcontroller.cc +++ b/libretroshare/src/ft/ftcontroller.cc @@ -47,6 +47,7 @@ #include "ft/ftsearch.h" #include "ft/ftdatamultiplex.h" #include "ft/ftextralist.h" +#include "ft/ftserver.h" #include "turtle/p3turtle.h" @@ -101,6 +102,7 @@ ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string / last_clean_time(0), mDataplex(dm), mTurtle(NULL), + mFtServer(NULL), ctrlMutex("ftController"), doneMutex("ftController"), mFtActive(false), @@ -111,10 +113,9 @@ ftController::ftController(CacheStrapper *cs, ftDataMultiplex *dm, std::string / /* TODO */ } -void ftController::setTurtleRouter(p3turtle *pt) -{ - mTurtle = pt ; -} +void ftController::setTurtleRouter(p3turtle *pt) { mTurtle = pt ; } +void ftController::setFtServer(ftServer *ft) { mFtServer = ft ; } + void ftController::setFtSearchNExtra(ftSearch *search, ftExtraList *list) { mSearch = search; @@ -644,7 +645,7 @@ void ftController::locked_checkQueueElement(uint32_t pos) _queue[pos]->mState = ftFileControl::DOWNLOADING ; if(_queue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->monitorTunnels(_queue[pos]->mHash) ; + mTurtle->monitorTunnels(_queue[pos]->mHash,mFtServer) ; } if(pos >= _max_active_downloads && _queue[pos]->mState != ftFileControl::QUEUED && _queue[pos]->mState != ftFileControl::PAUSED) @@ -1262,7 +1263,7 @@ bool ftController::FileRequest(const std::string& fname, const std::string& has // We check that flags are consistent. if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->monitorTunnels(hash) ; + mTurtle->monitorTunnels(hash,mFtServer) ; bool assume_availability = flags & RS_FILE_REQ_CACHE ; // assume availability for cache files diff --git a/libretroshare/src/ft/ftcontroller.h b/libretroshare/src/ft/ftcontroller.h index 8494b2b82..bef432187 100644 --- a/libretroshare/src/ft/ftcontroller.h +++ b/libretroshare/src/ft/ftcontroller.h @@ -42,6 +42,7 @@ class ftFileCreator; class ftTransferModule; class ftFileProvider; class ftSearch; +class ftServer; class ftExtraList; class ftDataMultiplex; class p3turtle ; @@ -119,6 +120,7 @@ class ftController: public CacheTransfer, public RsThread, public pqiMonitor, pu void setFtSearchNExtra(ftSearch *, ftExtraList *); void setTurtleRouter(p3turtle *) ; + void setFtServer(ftServer *) ; bool activate(); bool isActiveAndNoPending(); @@ -234,6 +236,7 @@ class ftController: public CacheTransfer, public RsThread, public pqiMonitor, pu ftDataMultiplex *mDataplex; ftExtraList *mExtraList; p3turtle *mTurtle ; + ftServer *mFtServer ; RsMutex ctrlMutex; diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index f12aba0e9..2a13705f2 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -31,6 +31,7 @@ #include "retroshare/rspeers.h" const int ftserverzone = 29539; +#include "ft/ftturtlefiletransferitem.h" #include "ft/ftserver.h" #include "ft/ftextralist.h" #include "ft/ftfilesearch.h" @@ -154,7 +155,9 @@ void ftServer::connectToTurtleRouter(p3turtle *fts) mTurtleRouter = fts ; mFtController->setTurtleRouter(fts) ; - fts->registerTunnelService(this) ; + mFtController->setFtServer(this) ; + + mTurtleRouter->registerTunnelService(this) ; } void ftServer::StartupThreads() @@ -452,6 +455,39 @@ bool ftServer::FileDetails(const std::string &hash, FileSearchFlags hintflags, F return false; } +RsTurtleGenericTunnelItem *ftServer::deserialiseItem(void *data,uint32_t size) const +{ + uint32_t rstype = getRsItemId(data); + +#ifdef SERVER_DEBUG + std::cerr << "p3turtle: deserialising packet: " << std::endl ; +#endif +#ifdef SERVER_DEBUG + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) + { +#ifdef SERVER_DEBUG + std::cerr << " Wrong type !!" << std::endl ; +#endif + return NULL; /* wrong type */ + } +#endif + + switch(getRsItemSubType(rstype)) + { + case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,size) ; + case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,size) ; + case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,size) ; + case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,size) ; + case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,size) ; + case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,size) ; + case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,size) ; + case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,size) ; + + default: + return NULL ; + } +} + bool ftServer::handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) { FileInfo info ; @@ -842,7 +878,14 @@ bool ftServer::loadConfigMap(std::map &/*configMap*/) bool ftServer::sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendDataRequest(peerId,hash,size,offset,chunksize) ; + { + RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ; + + item->chunk_offset = offset ; + item->chunk_size = chunksize ; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -869,7 +912,10 @@ bool ftServer::sendDataRequest(const std::string& peerId, const std::string& has bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& hash,bool is_client) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendChunkMapRequest(peerId,hash,is_client) ; + { + RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -892,7 +938,11 @@ bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& map,bool is_client) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendChunkMap(peerId,hash,map,is_client) ; + { + RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; + item->compressed_map = map ; + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -915,7 +965,11 @@ bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,co bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string& hash) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendCRC32MapRequest(peerId,hash) ; + { + RsTurtleFileCrcRequestItem *item = new RsTurtleFileCrcRequestItem; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -936,7 +990,12 @@ bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string& bool ftServer::sendSingleChunkCRCRequest(const std::string& peerId,const std::string& hash,uint32_t chunk_number) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendSingleChunkCRCRequest(peerId,hash,chunk_number) ; + { + RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem; + item->chunk_number = chunk_number ; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -959,7 +1018,12 @@ bool ftServer::sendSingleChunkCRCRequest(const std::string& peerId,const std::st bool ftServer::sendCRC32Map(const std::string& peerId,const std::string& hash,const CRC32Map& crcmap) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendCRC32Map(peerId,hash,crcmap) ; + { + RsTurtleFileCrcItem *item = new RsTurtleFileCrcItem ; + item->crc_map = crcmap ; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -981,7 +1045,13 @@ bool ftServer::sendCRC32Map(const std::string& peerId,const std::string& hash,co bool ftServer::sendSingleChunkCRC(const std::string& peerId,const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& crc) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendSingleChunkCRC(peerId,hash,chunk_number,crc) ; + { + RsTurtleChunkCrcItem *item = new RsTurtleChunkCrcItem; + item->chunk_number = chunk_number ; + item->check_sum = crc ; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { /* create a packet */ @@ -1036,7 +1106,23 @@ bool ftServer::sendData(const std::string& peerId, const std::string& hash, uint /******** New Serialiser Type *******/ if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendFileData(peerId,hash,size,baseoffset+offset,chunk,&(((uint8_t *) data)[offset])) ; + { + RsTurtleFileDataItem *item = new RsTurtleFileDataItem ; + + item->chunk_offset = offset ; + item->chunk_size = chunksize ; + item->chunk_data = malloc(chunksize) ; + + if(item->chunk_data == NULL) + { + std::cerr << "p3turtle: Warning: failed malloc of " << chunksize << " bytes for sending data packet." << std::endl ; + delete item; + return false; + } + memcpy(item->chunk_data,(void*)((uint8_t*)data),chunksize) ; + + mTurtleRouter->sendTurtleData(peerId,item) ; + } else { RsFileData *rfd = new RsFileData(); @@ -1080,6 +1166,76 @@ bool ftServer::sendData(const std::string& peerId, const std::string& hash, uint return true; } +void ftServer::receiveTurtleData(RsTurtleGenericTunnelItem *i, + const std::string& hash, + const std::string& virtual_peer_id, + RsTurtleGenericTunnelItem::Direction direction) +{ + switch(i->PacketSubType()) + { + case RS_TURTLE_SUBTYPE_FILE_REQUEST: + { + RsTurtleFileRequestItem *item = dynamic_cast(i) ; + getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ; + } + break ; + + case RS_TURTLE_SUBTYPE_FILE_DATA : + { + RsTurtleFileDataItem *item = dynamic_cast(i) ; + getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ; + + item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted + // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData + + } + break ; + + case RS_TURTLE_SUBTYPE_FILE_MAP : + { + RsTurtleFileMapItem *item = dynamic_cast(i) ; + getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; + } + break ; + + case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: + { + RsTurtleFileMapRequestItem *item = dynamic_cast(i) ; + getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; + } + break ; + + case RS_TURTLE_SUBTYPE_FILE_CRC : + { + RsTurtleFileCrcItem *item = dynamic_cast(i) ; + getMultiplexer()->recvCRC32Map(virtual_peer_id,hash,item->crc_map) ; + } + break ; + + case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST: + { + getMultiplexer()->recvCRC32MapRequest(virtual_peer_id,hash) ; + } + break ; + + case RS_TURTLE_SUBTYPE_CHUNK_CRC : + { + RsTurtleChunkCrcItem *item = dynamic_cast(i) ; + getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ; + } + break ; + + case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: + { + RsTurtleChunkCrcRequestItem *item = dynamic_cast(i) ; + getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ; + } + break ; + default: + std::cerr << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; + } +} + /* NB: The rsCore lock must be activated before calling this. * This Lock should be moved lower into the system... diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index e25585709..715aa0a3f 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -115,6 +115,8 @@ class ftServer: public RsFiles, public ftDataSend, public RsTurtleClientService, // Implements RsTurtleClientService // virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) ; + virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) ; + virtual RsTurtleGenericTunnelItem *deserialiseItem(void *data,uint32_t size) const ; /***************************************************************/ /*************** Control Interface *****************************/ diff --git a/libretroshare/src/ft/ftturtlefiletransferitem.cc b/libretroshare/src/ft/ftturtlefiletransferitem.cc new file mode 100644 index 000000000..1b0be2b2d --- /dev/null +++ b/libretroshare/src/ft/ftturtlefiletransferitem.cc @@ -0,0 +1,739 @@ +/* + * libretroshare/src/services: ftturtlefiletransferitem.cc + * + * Services for RetroShare. + * + * Copyright 2013 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". + * + */ + +#include +#include + +#include +#include + +uint32_t RsTurtleFileRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 8 ; // file offset + s += 4 ; // chunk size + + return s ; +} + +uint32_t RsTurtleFileDataItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 8 ; // file offset + s += 4 ; // chunk size + s += chunk_size ; // actual data size. + + return s ; +} + +uint32_t RsTurtleFileMapRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // direction + + return s ; +} + +uint32_t RsTurtleFileMapItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // direction + s += 4 ; // compressed_map.size() + + s += 4 * compressed_map._map.size() ; + + return s ; +} + +uint32_t RsTurtleFileCrcRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + + return s ; +} +uint32_t RsTurtleChunkCrcItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // chunk number + s += 20 ; // check_sum + + return s ; +} +uint32_t RsTurtleChunkCrcRequestItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + s += 4 ; // chunk number + + return s ; +} +uint32_t RsTurtleFileCrcItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // tunnel id + + s += 4 ; // size of _map + s += 4 ; // size of _crcs + + s += 4 * crc_map._crcs.size() ; + s += 4 * crc_map._ccmap._map.size() ; + + return s ; +} +bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + + ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); + ok &= setRawUInt32(data, tlvsize, &offset, direction); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl; +#endif + } + + return ok; +} + +bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) +{ + uint32_t tlvsize = serial_size(); + uint32_t offset = 0; + + if (pktsize < tlvsize) + return false; /* not enough space */ + + pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + + ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); + ok &= setRawUInt32(data, tlvsize, &offset, direction); + ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map.size()); + + for(uint32_t i=0;i +#include + +/***********************************************************************************/ +/* Turtle File Transfer item classes */ +/***********************************************************************************/ + +class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_REQUEST);} + RsTurtleFileRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } + + uint64_t chunk_offset ; + uint32_t chunk_size ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + protected: + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileDataItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_DATA) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_DATA) ;} + ~RsTurtleFileDataItem() ; + RsTurtleFileDataItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return true ; } + virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } + + uint64_t chunk_offset ; // offset in the file + uint32_t chunk_size ; // size of the file chunk + void *chunk_data ; // actual data. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileMapRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP_REQUEST) ;} + RsTurtleFileMapRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileMapItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_MAP) { setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FILE_MAP) ;} + RsTurtleFileMapItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + + CompressedChunkMap compressed_map ; // Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" + // by default, we suppose the peer has all the chunks. This info will thus be and-ed + // with the default file map for this source. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileCrcRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC_REQUEST);} + RsTurtleFileCrcRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleChunkCrcRequestItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC_REQUEST);} + RsTurtleChunkCrcRequestItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return false ; } + virtual Direction travelingDirection() const { return DIRECTION_SERVER ; } + + uint32_t chunk_number ; // id of the chunk to CRC. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleFileCrcItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleFileCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_FILE_CRC) { setPriorityLevel(QOS_PRIORITY_RS_FILE_CRC);} + RsTurtleFileCrcItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return true ; } + virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } + + CRC32Map crc_map ;// Map info for the file in compressed format. Each *bit* in the array uint's says "I have" or "I don't have" + // by default, we suppose the peer has all the chunks. This info will thus be and-ed + // with the default file map for this source. + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; + +class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem +{ + public: + RsTurtleChunkCrcItem() : RsTurtleGenericTunnelItem(RS_TURTLE_SUBTYPE_CHUNK_CRC) { setPriorityLevel(QOS_PRIORITY_RS_CHUNK_CRC);} + RsTurtleChunkCrcItem(void *data,uint32_t size) ; // deserialization + + virtual bool shouldStampTunnel() const { return true ; } + virtual Direction travelingDirection() const { return DIRECTION_CLIENT ; } + + uint32_t chunk_number ; + Sha1CheckSum check_sum ; + + virtual std::ostream& print(std::ostream& o, uint16_t) ; + virtual bool serialize(void *data,uint32_t& size) ; + virtual uint32_t serial_size() ; +}; diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index a21b1f202..105e3846a 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -308,7 +308,8 @@ HEADERS += ft/ftchunkmap.h \ ft/ftfilesearch.h \ ft/ftsearch.h \ ft/ftserver.h \ - ft/fttransfermodule.h + ft/fttransfermodule.h \ + ft/ftturtlefiletransferitem.h HEADERS += pqi/authssl.h \ pqi/authgpg.h \ @@ -448,6 +449,7 @@ SOURCES += ft/ftchunkmap.cc \ ft/ftfilesearch.cc \ ft/ftserver.cc \ ft/fttransfermodule.cc \ + ft/ftturtlefiletransferitem.cc SOURCES += pqi/authgpg.cc \ pqi/authssl.cc \ diff --git a/libretroshare/src/retroshare/rsturtle.h b/libretroshare/src/retroshare/rsturtle.h index 59fbffac8..e66ab7367 100644 --- a/libretroshare/src/retroshare/rsturtle.h +++ b/libretroshare/src/retroshare/rsturtle.h @@ -108,7 +108,7 @@ class RsTurtle // tunnels for the given hash. The download should be driven by the file // transfer module by calling ftServer::FileRequest(). // - virtual void monitorTunnels(const std::string& file_hash) = 0 ; + virtual void monitorTunnels(const std::string& file_hash,RsTurtleClientService *client_service) = 0 ; // Tells the turtle router to stop handling tunnels for the given file hash. Traditionally this should // be called after calling ftServer::fileCancel(). diff --git a/libretroshare/src/serialiser/itempriorities.h b/libretroshare/src/serialiser/itempriorities.h index 0dea7db1f..afd06510f 100644 --- a/libretroshare/src/serialiser/itempriorities.h +++ b/libretroshare/src/serialiser/itempriorities.h @@ -23,6 +23,10 @@ * */ +#pragma once + +#include + // This file centralises QoS priorities for all transfer RsItems. // const uint8_t QOS_PRIORITY_UNKNOWN = 0 ; diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index 7ce9a6fb2..8f0239161 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -111,8 +111,9 @@ p3turtle::p3turtle(p3LinkMgr *lm,ftServer *fs) _ft_controller = fs->getController() ; _random_bias = RSRandom::random_u32() ; + _serialiser = new RsTurtleSerialiser() ; - addSerialType(new RsTurtleSerialiser()); + addSerialType(_serialiser); _last_clean_time = 0 ; _last_tunnel_management_time = 0 ; @@ -995,7 +996,6 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) std::cerr << "p3Turtle: treating generic tunnel item:" << std::endl ; item->print(std::cerr,1) ; #endif - RsTurtleGenericTunnelItem::Direction direction = item->travelingDirection() ; { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ @@ -1021,9 +1021,16 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) tunnel.transfered_bytes += static_cast(item)->serial_size() ; + if(item->PeerId() == tunnel.local_dst) + item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; + else if(item->PeerId() == tunnel.local_src) + item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; + else + std::cerr << "(EE) critical error in p3turtle::routeGenericTunnelItem(): item mismatches tunnel src/dst ids." << std::endl; + // Let's figure out whether this packet is for us or not. - if(direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT && tunnel.local_src != mLinkMgr->getOwnId()) + if(item->PeerId() == tunnel.local_dst && tunnel.local_src != mLinkMgr->getOwnId()) //direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT && { #ifdef P3TURTLE_DEBUG std::cerr << " Forwarding generic item to peer " << tunnel.local_src << std::endl ; @@ -1032,14 +1039,16 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) _traffic_info_buffer.unknown_updn_Bps += static_cast(item)->serial_size() ; - if(dynamic_cast(item) != NULL) - item->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA) ; + // This has been disabled for compilation reasons. Not sure we actually need it. + // + //if(dynamic_cast(item) != NULL) + // item->setPriorityLevel(QOS_PRIORITY_RS_TURTLE_FORWARD_FILE_DATA) ; sendItem(item) ; return ; } - if(direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER && tunnel.local_dst != mLinkMgr->getOwnId()) + if(item->PeerId() == tunnel.local_src && tunnel.local_dst != mLinkMgr->getOwnId()) //direction == RsTurtleGenericTunnelItem::DIRECTION_SERVER && { #ifdef P3TURTLE_DEBUG std::cerr << " Forwarding generic item to peer " << tunnel.local_dst << std::endl ; @@ -1057,198 +1066,31 @@ void p3turtle::routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) // This is done off-mutex, to avoid various deadlocks // - switch(item->PacketSubType()) - { - case RS_TURTLE_SUBTYPE_FILE_REQUEST: handleRecvFileRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_FILE_DATA : handleRecvFileData(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP : handleRecvFileMap(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: handleRecvFileMapRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_FILE_CRC : handleRecvFileCRC32Map(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST: handleRecvFileCRC32MapRequest(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC : handleRecvChunkCRC(dynamic_cast(item)) ; - break ; - - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: handleRecvChunkCRCRequest(dynamic_cast(item)) ; - break ; - default: - std::cerr << "WARNING: Unknown packet type received: id=" << reinterpret_cast(item->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; -#ifdef P3TURTLE_DEBUG - exit(-1) ; -#endif - } + handleRecvGenericTunnelItem(item) ; delete item ; } -void p3turtle::handleRecvFileRequest(RsTurtleFileRequestItem *item) +void p3turtle::handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item) { #ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file request item:" << std::endl ; + std::cerr << "p3Turtle: received Generic tunnel item:" << std::endl ; item->print(std::cerr,1) ; #endif - // This is a new request. Let's add it to the request map, and forward it to - // open peers. - - TurtleVirtualPeerId vpid ; - uint64_t size ; - TurtleFileHash hash ; + std::string hash ; + std::string vpid ; + RsTurtleClientService *service ; + // Now lock the router { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; + std::map::iterator it2(_local_tunnels.find(item->tunnelId())) ; if(it2 == _local_tunnels.end()) { #ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file request with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; - std::map::const_iterator it(_outgoing_file_hashes.find(tunnel.hash)) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - assert(it != _outgoing_file_hashes.end()) ; - - std::cerr << " This is an endpoint for this file request." << std::endl ; - std::cerr << " Forwarding data request to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - size = 0 ; //it->second.size ; Not used by ftDataMultiplex actually - vpid = tunnel.vpid ; - hash = tunnel.hash ; - } - - // This call is voluntarily off-mutex gards because it can cause cross mutex locks with the multiplexer. - // (Yeah, this bug was a shity hard one to catch). - // - _ft_server->getMultiplexer()->recvDataRequest(vpid,hash,size,item->chunk_offset,item->chunk_size) ; -} - -void p3turtle::handleRecvFileData(RsTurtleFileDataItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file data item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - TurtleVirtualPeerId vpid ; - uint64_t size ; - TurtleFileHash hash ; - - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - _traffic_info_buffer.data_dn_Bps += static_cast(item)->serial_size() ; - - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; - std::map::iterator it( _incoming_file_hashes.find(tunnel.hash) ) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; -#endif - if(it==_incoming_file_hashes.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "No tunnel for incoming data. Maybe the tunnel is being closed." << std::endl ; -#endif - return ; - } - -#ifdef P3TURTLE_DEBUG - std::cerr << " This is an endpoint for this data chunk." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - //_ft_server->getMultiplexer()->recvData(tunnel.vpid,tunnel.hash,hash_info.size,item->chunk_offset,item->chunk_size,item->chunk_data) ; - vpid = tunnel.vpid ; - hash = tunnel.hash ; - size = 0 ; // Not used by ftDataMultiplex, see ftDataMultiplex:handleRecvData() - - // also update the hash time stamp to show that it's actually being downloaded. - //it->second.time_stamp = time(NULL) ; - } - - _ft_server->getMultiplexer()->recvData(vpid,hash,size,item->chunk_offset,item->chunk_size,item->chunk_data) ; - item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted - // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData -} - -void p3turtle::handleRecvFileMapRequest(RsTurtleFileMapRequestItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file Map item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - - std::cerr << " This is an endpoint for this file map request." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // we should check that there is no backward call to the turtle router! - // - hash = tunnel.hash ; - vpid = tunnel.vpid ; - } - - _ft_server->getMultiplexer()->recvChunkMapRequest(vpid,hash,item->direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; -} - -void p3turtle::handleRecvFileMap(RsTurtleFileMapItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file Map item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; + std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnelId() << std::endl ; #endif return ; } @@ -1266,161 +1108,29 @@ void p3turtle::handleRecvFileMap(RsTurtleFileMapItem *item) // vpid = tunnel.vpid ; hash = tunnel.hash ; - } - _ft_server->getMultiplexer()->recvChunkMap(vpid,hash,item->compressed_map,item->direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; -} -void p3turtle::handleRecvFileCRC32MapRequest(RsTurtleFileCrcRequestItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file CRC32 Map Request item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + std::map::const_iterator it = _incoming_file_hashes.find(hash) ; - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) + if(it == _incoming_file_hashes.end()) { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file data with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif + std::cerr << "p3turtle::handleRecvGenericTunnelItem(): hash " << hash << " for tunnel " << (void*)(it2->first) << " has no attached service! Dropping the item. This is a serious consistency error." << std::endl; return ; } - TurtleTunnel& tunnel(it2->second) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - - std::cerr << " This is an endpoint for this file crc request." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // we should check that there is no backward call to the turtle router! - // - hash = tunnel.hash ; - vpid = tunnel.vpid ; + service = it->second.service ; } - _ft_server->getMultiplexer()->recvCRC32MapRequest(vpid,hash) ; + service->receiveTurtleData(item,hash,vpid,item->travelingDirection()) ; } -void p3turtle::handleRecvChunkCRC(RsTurtleChunkCrcItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file CRC32 Map Request item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: chunk crc request with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - - std::cerr << " This is an endpoint for this file crc request." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // we should check that there is no backward call to the turtle router! - // - hash = tunnel.hash ; - vpid = tunnel.vpid ; - } - - _ft_server->getMultiplexer()->recvSingleChunkCRC(vpid,hash,item->chunk_number,item->check_sum) ; -} -void p3turtle::handleRecvChunkCRCRequest(RsTurtleChunkCrcRequestItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file CRC32 Map Request item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: chunk crc request with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - - std::cerr << " This is an endpoint for this file crc request." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // we should check that there is no backward call to the turtle router! - // - hash = tunnel.hash ; - vpid = tunnel.vpid ; - } - - _ft_server->getMultiplexer()->recvSingleChunkCRCRequest(vpid,hash,item->chunk_number) ; -} -void p3turtle::handleRecvFileCRC32Map(RsTurtleFileCrcItem *item) -{ -#ifdef P3TURTLE_DEBUG - std::cerr << "p3Turtle: received file CRC32 Map item:" << std::endl ; - item->print(std::cerr,1) ; -#endif - std::string hash,vpid ; - { - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - std::map::iterator it2(_local_tunnels.find(item->tunnel_id)) ; - - if(it2 == _local_tunnels.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: got file CRC32 map with unknown tunnel id " << (void*)item->tunnel_id << std::endl ; -#endif - return ; - } - - TurtleTunnel& tunnel(it2->second) ; - -#ifdef P3TURTLE_DEBUG - assert(!tunnel.hash.empty()) ; - - std::cerr << " This is an endpoint for this file map." << std::endl ; - std::cerr << " Forwarding data to the multiplexer." << std::endl ; - std::cerr << " using peer_id=" << tunnel.vpid << ", hash=" << tunnel.hash << std::endl ; -#endif - // We should check that there is no backward call to the turtle router! - // - vpid = tunnel.vpid ; - hash = tunnel.hash ; - } - _ft_server->getMultiplexer()->recvCRC32Map(vpid,hash,item->crc_map) ; -} // Send a data request into the correct tunnel for the given file hash -void p3turtle::sendDataRequest(const std::string& peerId, const std::string& , uint64_t, uint64_t offset, uint32_t chunksize) +// +void p3turtle::sendTurtleData(const std::string& virtual_peer_id,RsTurtleGenericTunnelItem *item) { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; + std::map::const_iterator it(_virtual_peers.find(virtual_peer_id)) ; if(it == _virtual_peers.end()) { @@ -1432,255 +1142,31 @@ void p3turtle::sendDataRequest(const std::string& peerId, const std::string& , u TurtleTunnelId tunnel_id = it->second ; TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - RsTurtleFileRequestItem *item = new RsTurtleFileRequestItem ; item->tunnel_id = tunnel_id ; // we should randomly select a tunnel, or something more clever. - item->chunk_offset = offset ; - item->chunk_size = chunksize ; - item->PeerId(tunnel.local_dst) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending file req (chunksize=" << item->chunk_size << ", offset=" << item->chunk_offset << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << tunnel.local_dst << std::endl ; -#endif - sendItem(item) ; -} - -// Send file data into the correct tunnel for the given file hash -void p3turtle::sendFileData(const std::string& peerId, const std::string& , uint64_t, uint64_t offset, uint32_t chunksize, void *data) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::sendData: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - tunnel.time_stamp = time(NULL) ; - - RsTurtleFileDataItem *item = new RsTurtleFileDataItem ; - item->tunnel_id = tunnel_id ; - item->chunk_offset = offset ; - item->chunk_size = chunksize ; - item->chunk_data = malloc(chunksize) ; - - tunnel.transfered_bytes += static_cast(item)->serial_size(); - - if(item->chunk_data == NULL) - { - std::cerr << "p3turtle: Warning: failed malloc of " << chunksize << " bytes for sending data packet." << std::endl ; - delete item; - return ; - } - memcpy(item->chunk_data,(void*)((uint8_t*)data),chunksize) ; - item->PeerId(tunnel.local_src) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending file data (chunksize=" << item->chunk_size << ", offset=" << item->chunk_offset << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << tunnel.local_src << std::endl ; -#endif - _traffic_info_buffer.data_up_Bps += static_cast(item)->serial_size() ; - - sendItem(item) ; -} - -void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& ,bool is_client) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; - item->tunnel_id = tunnel_id ; std::string ownid = mLinkMgr->getOwnId() ; if(tunnel.local_src == ownid) { - assert(!is_client) ; - item->direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; + item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_SERVER) ; item->PeerId(tunnel.local_dst) ; + _traffic_info_buffer.data_dn_Bps += item->serial_size() ; } else if(tunnel.local_dst == ownid) { - assert(is_client) ; - item->direction = RsTurtleGenericTunnelItem::DIRECTION_CLIENT ; + item->setTravelingDirection(RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; item->PeerId(tunnel.local_src) ; + _traffic_info_buffer.data_up_Bps += item->serial_size() ; } else - std::cerr << "p3turtle::sendChunkMapRequest: consistency error!" << std::endl ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending chunk map req to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; -#endif - sendItem(item) ; -} - -void p3turtle::sendChunkMap(const std::string& peerId,const std::string& ,const CompressedChunkMap& cmap,bool is_client) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif + std::cerr << "p3Turtle::sendTurtleData(): asked to send a packet into a tunnel that is not registered. Dropping packet." << std::endl ; + delete item ; return ; } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; - item->tunnel_id = tunnel_id ; - item->compressed_map = cmap ; - - std::string ownid = mLinkMgr->getOwnId() ; - - if(tunnel.local_src == ownid) - { - assert(!is_client) ; - item->direction = RsTurtleGenericTunnelItem::DIRECTION_SERVER ; - item->PeerId(tunnel.local_dst) ; - } - else if(tunnel.local_dst == ownid) - { - assert(is_client) ; - item->direction = RsTurtleGenericTunnelItem::DIRECTION_CLIENT ; - item->PeerId(tunnel.local_src) ; - } - else - std::cerr << "p3turtle::sendChunkMap: consistency error!" << std::endl ; #ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending chunk map to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; -#endif - sendItem(item) ; -} -void p3turtle::sendSingleChunkCRC(const std::string& peerId,const std::string&,uint32_t chunk_number,const Sha1CheckSum& crc) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::sendCRC32MapRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleChunkCrcItem *item = new RsTurtleChunkCrcItem; - item->tunnel_id = tunnel_id ; - item->chunk_number = chunk_number ; - item->check_sum = crc ; - item->PeerId(tunnel.local_dst) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending CRC32 map request to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; -#endif - sendItem(item) ; -} -void p3turtle::sendSingleChunkCRCRequest(const std::string& peerId,const std::string&,uint32_t chunk_number) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::sendCRC32MapRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem; - item->tunnel_id = tunnel_id ; - item->chunk_number = chunk_number ; - item->PeerId(tunnel.local_dst) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending CRC32 map request to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; -#endif - sendItem(item) ; -} -void p3turtle::sendCRC32MapRequest(const std::string& peerId,const std::string& ) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::sendCRC32MapRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleFileCrcRequestItem *item = new RsTurtleFileCrcRequestItem; - item->tunnel_id = tunnel_id ; -// item->crc_map = cmap ; - item->PeerId(tunnel.local_dst) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending CRC32 map request to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; -#endif - sendItem(item) ; -} -void p3turtle::sendCRC32Map(const std::string& peerId,const std::string& ,const CRC32Map& cmap) -{ - RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ - - // get the proper tunnel for this file hash and peer id. - std::map::const_iterator it(_virtual_peers.find(peerId)) ; - - if(it == _virtual_peers.end()) - { -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::senddataRequest: cannot find virtual peer " << peerId << " in VP list." << std::endl ; -#endif - return ; - } - TurtleTunnelId tunnel_id = it->second ; - TurtleTunnel& tunnel(_local_tunnels[tunnel_id]) ; - - RsTurtleFileCrcItem *item = new RsTurtleFileCrcItem ; - item->tunnel_id = tunnel_id ; - item->crc_map = cmap ; - item->PeerId(tunnel.local_src) ; - -#ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle: sending CRC32 map to peer " << peerId << ", hash=0x" << tunnel.hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; + std::cerr << "p3turtle: sending service packet to virtual peer id " << virtual_peer_id << ", hash=0x" << tunnel.hash << ", tunnel = " << (void*)item->tunnel_id << ", next peer=" << tunnel.local_dst << std::endl ; #endif sendItem(item) ; } @@ -2302,7 +1788,7 @@ TurtleRequestId p3turtle::turtleSearch(const LinearizedExpression& expr) return id ; } -void p3turtle::monitorTunnels(const std::string& hash) +void p3turtle::monitorTunnels(const std::string& hash,RsTurtleClientService *client_service) { { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ @@ -2338,6 +1824,7 @@ void p3turtle::monitorTunnels(const std::string& hash) // also should send associated request to the file transfer module. _incoming_file_hashes[hash].last_digg_time = RSRandom::random_u32()%10 ; + _incoming_file_hashes[hash].service = client_service ; } IndicateConfigChanged() ; // initiates saving of handled hashes. @@ -2380,6 +1867,7 @@ void p3turtle::registerTunnelService(RsTurtleClientService *service) std::cerr << "p3turtle: registered new tunnel service " << (void*)service << std::endl; _registered_services.push_back(service) ; + _serialiser->registerClientService(service) ; } static std::string printFloatNumber(float num,bool friendly=false) diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h index afbb54530..b8ae97452 100644 --- a/libretroshare/src/turtle/p3turtle.h +++ b/libretroshare/src/turtle/p3turtle.h @@ -198,7 +198,8 @@ class TurtleHashInfo public: std::vector tunnels ; // list of active tunnel ids for this file hash TurtleRequestId last_request ; // last request for the tunnels of this hash - time_t last_digg_time ; + time_t last_digg_time ; // last time the tunnel digging happenned. + RsTurtleClientService *service ; // client service to which items should be sent. Never NULL. }; // Subclassing: @@ -249,7 +250,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config // This function should be called in addition to ftServer::FileRequest() so that the turtle router // automatically provide tunnels for the file to download. // - virtual void monitorTunnels(const std::string& file_hash) ; + virtual void monitorTunnels(const std::string& file_hash,RsTurtleClientService *client_service) ; /// This should be called when canceling a file download, so that the turtle router stops /// handling tunnels for this file. @@ -288,7 +289,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config virtual bool saveList(bool& cleanup, std::list&) ; virtual bool loadList(std::list& /*load*/) ; - /************* Communication with ftserver *******************/ + /************* Communication with clients *******************/ /// Does the turtle router manages tunnels to this peer ? (this is not a /// real id, but a fake one, that the turtle router is capable of connecting with a tunnel id). virtual bool isTurtlePeer(const std::string& peer_id) const ; @@ -307,28 +308,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config void getVirtualPeersList(std::list& list) ; /// Send a data request into the correct tunnel for the given file hash - void sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize) ; - - /// Send file data into the correct tunnel for the given file hash - void sendFileData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) ; - - /// Send a request for the chunk map of this file to the given peer - void sendChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) ; - - /// Send a chunk map of this file to the given peer - void sendChunkMap(const std::string& peerId, const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ; - - /// Send a request for the crc32 map of this file to the given peer - void sendCRC32MapRequest(const std::string& peerId, const std::string& hash) ; - - /// Send a crc32 map of this file to the given peer - void sendCRC32Map(const std::string& peerId, const std::string& hash,const CRC32Map& cmap) ; - - /// Send a request for the CRC of a single chunk of this file to the given peer - void sendSingleChunkCRCRequest(const std::string& peerId, const std::string& hash,uint32_t chunk_number) ; - - /// Send a crc32 map of this file to the given peer - void sendSingleChunkCRC(const std::string& peerId, const std::string& hash,uint32_t chunk_number,const Sha1CheckSum& sum) ; + void sendTurtleData(const std::string& virtual_peer_id, RsTurtleGenericTunnelItem *item) ; private: //--------------------------- Admin/Helper functions -------------------------// @@ -371,18 +351,13 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config void routeGenericTunnelItem(RsTurtleGenericTunnelItem *item) ; /// specific routing functions for handling particular packets. + void handleRecvGenericTunnelItem(RsTurtleGenericTunnelItem *item); + + // following functions should go to ftServer void handleSearchRequest(RsTurtleSearchRequestItem *item); void handleSearchResult(RsTurtleSearchResultItem *item); void handleTunnelRequest(RsTurtleOpenTunnelItem *item); void handleTunnelResult(RsTurtleTunnelOkItem *item); - void handleRecvFileRequest(RsTurtleFileRequestItem *item); - void handleRecvFileData(RsTurtleFileDataItem *item); - void handleRecvFileMapRequest(RsTurtleFileMapRequestItem*); - void handleRecvFileMap(RsTurtleFileMapItem*); - void handleRecvFileCRC32MapRequest(RsTurtleFileCrcRequestItem*); - void handleRecvFileCRC32Map(RsTurtleFileCrcItem*); - void handleRecvChunkCRCRequest(RsTurtleChunkCrcRequestItem*); - void handleRecvChunkCRC(RsTurtleChunkCrcItem*); //------ Functions connecting the turtle router to other components.----------// @@ -401,6 +376,7 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config p3LinkMgr *mLinkMgr; ftServer *_ft_server ; ftController *_ft_controller ; + RsTurtleSerialiser *_serialiser ; mutable RsMutex mTurtleMtx; diff --git a/libretroshare/src/turtle/rsturtleitem.cc b/libretroshare/src/turtle/rsturtleitem.cc index 739793e3e..ad5a66fd5 100644 --- a/libretroshare/src/turtle/rsturtleitem.cc +++ b/libretroshare/src/turtle/rsturtleitem.cc @@ -4,6 +4,7 @@ #include #include "turtletypes.h" #include "rsturtleitem.h" +#include "turtleclientservice.h" //#define P3TURTLE_DEBUG // -----------------------------------------------------------------------------------// @@ -90,101 +91,6 @@ uint32_t RsTurtleTunnelOkItem::serial_size() return s ; } -uint32_t RsTurtleFileRequestItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 8 ; // file offset - s += 4 ; // chunk size - - return s ; -} - -uint32_t RsTurtleFileDataItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 8 ; // file offset - s += 4 ; // chunk size - s += chunk_size ; // actual data size. - - return s ; -} - -uint32_t RsTurtleFileMapRequestItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 4 ; // direction - - return s ; -} - -uint32_t RsTurtleFileMapItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 4 ; // direction - s += 4 ; // compressed_map.size() - - s += 4 * compressed_map._map.size() ; - - return s ; -} - -uint32_t RsTurtleFileCrcRequestItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - - return s ; -} -uint32_t RsTurtleChunkCrcItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 4 ; // chunk number - s += 20 ; // check_sum - - return s ; -} -uint32_t RsTurtleChunkCrcRequestItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - s += 4 ; // chunk number - - return s ; -} -uint32_t RsTurtleFileCrcItem::serial_size() -{ - uint32_t s = 0 ; - - s += 8 ; // header - s += 4 ; // tunnel id - - s += 4 ; // size of _map - s += 4 ; // size of _crcs - - s += 4 * crc_map._crcs.size() ; - s += 4 * crc_map._ccmap._map.size() ; - - return s ; -} // // ---------------------------------- Serialization ----------------------------------// // @@ -216,19 +122,31 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) case RS_TURTLE_SUBTYPE_SEARCH_RESULT : return new RsTurtleSearchResultItem(data,*size) ; case RS_TURTLE_SUBTYPE_OPEN_TUNNEL : return new RsTurtleOpenTunnelItem(data,*size) ; case RS_TURTLE_SUBTYPE_TUNNEL_OK : return new RsTurtleTunnelOkItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ; - case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ; - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,*size) ; - case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,*size) ; + + // We need to call some client serialiser from there. + // + // case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_FILE_MAP : return new RsTurtleFileMapItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_FILE_CRC_REQUEST : return new RsTurtleFileCrcRequestItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_FILE_CRC : return new RsTurtleFileCrcItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST : return new RsTurtleChunkCrcRequestItem(data,*size) ; + // case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,*size) ; default: - std::cerr << "Unknown packet type in RsTurtle!" << std::endl ; - return NULL ; + break ; } + // now try all client services + // + RsItem *item = NULL ; + + for(uint32_t i=0;i<_client_services.size();++i) + if((item = _client_services[i]->deserialiseItem(data,*size)) != NULL) + return item ; + + std::cerr << "Unknown packet type in RsTurtle (not even handled by client services)!" << std::endl ; + return NULL ; #ifndef WINDOWS_SYS } catch(std::exception& e) @@ -240,224 +158,6 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) } -bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) -{ - uint32_t tlvsize = serial_size(); - uint32_t offset = 0; - - if (pktsize < tlvsize) - return false; /* not enough space */ - - pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - - ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); - ok &= setRawUInt32(data, tlvsize, &offset, direction); - - if (offset != tlvsize) - { - ok = false; -#ifdef RSSERIAL_DEBUG - std::cerr << "RsFileConfigSerialiser::serialiseTransfer() Size Error! " << std::endl; -#endif - } - - return ok; -} - -bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) -{ - uint32_t tlvsize = serial_size(); - uint32_t offset = 0; - - if (pktsize < tlvsize) - return false; /* not enough space */ - - pktsize = tlvsize; - - bool ok = true; - - ok &= setRsItemHeader(data,tlvsize,PacketId(), tlvsize); - - /* skip the header */ - offset += 8; - - /* add mandatory parts first */ - - ok &= setRawUInt32(data, tlvsize, &offset, tunnel_id); - ok &= setRawUInt32(data, tlvsize, &offset, direction); - ok &= setRawUInt32(data, tlvsize, &offset, compressed_map._map.size()); - - for(uint32_t i=0;i(item)->serialize(data,*size) ; } virtual RsItem *deserialise (void *data, uint32_t *size) ; + + // 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 ; }; diff --git a/libretroshare/src/turtle/turtleclientservice.h b/libretroshare/src/turtle/turtleclientservice.h new file mode 100644 index 000000000..34a69a51e --- /dev/null +++ b/libretroshare/src/turtle/turtleclientservice.h @@ -0,0 +1,88 @@ +/* + * libretroshare/src/services: turtleclientservice.h + * + * Services for RetroShare. + * + * Copyright 2013 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". + * + */ + +// This class is the parent class for any service that will use the turtle router to distribute its packets. +// Typical representative clients include: +// +// p3ChatService: opens tunnels to distant peers for chatting +// ftServer: searches and open tunnels to distant sources for file transfer +// +#pragma once + +#include +#include +#include +#include + +class RsItem ; + +class RsTurtleClientService +{ + public: + // Handling of tunnel request for the given hash. Most of the time, it's a search in a predefined list. + // The output info_string is used by the turtle router to display info about tunnels it manages. It is + // not passed to the tunnel. + + virtual bool handleTunnelRequest(const std::string& hash,const std::string& peer_id,std::string& description_info_string) { return false ; } + + // This method is called by the turtle router to send data that comes out of a turtle tunnel. + // The turtle router stays responsible for the memory management of data. Most of the time the + // data chunk is a serialized item to be de-serialized by the client service. + // + // Parameters: + // virtual_peer_id : name of the tunnel that sent the data + // data : memory chunk for the data + // size : size of data + // item->direction : direction of travel: + // RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a client + // RsTurtleGenericTunnelItem::DIRECTION_CLIENT: the service is acting as a server + // + // Most of the time this parameter is not used by services, except when some info (such as chunk maps, chat items, etc) go + // both ways, and their nature cannot suffice to determine where they should be handled. + // + // By default (if not overloaded), the method will just free the data, as any subclass should do as well. + // + virtual void receiveTurtleData(void *data,uint32_t size,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) + { + std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ; + } + + // This method does the exact same job, but the item is already de-serialized. It is kept for + // compatibility reasons only. New services should not use it, only the file transfer should. + + virtual void receiveTurtleData(RsTurtleGenericTunnelItem *item,const std::string& hash,const std::string& virtual_peer_id,RsTurtleGenericTunnelItem::Direction direction) + { + std::cerr << "!!!!!! Received Data from turtle router, but the client service is not handling it !!!!!!!!!!" << std::endl ; + } + + // Method for deserialising specific items of the client service. The + // method has a default behavior of not doing anything, since most client + // services might only use the generic item already provided by the turtle + // router: RsTurtleGenericDataItem + + virtual RsTurtleGenericTunnelItem *deserialiseItem(void *data, uint32_t size) const { return NULL ; } +}; + +