From cee8600a9354bf8e78fe426c75bedd06602fed60 Mon Sep 17 00:00:00 2001 From: csoler Date: Sun, 25 Jul 2010 19:04:31 +0000 Subject: [PATCH] - implemented bidirectional exchange of chunk maps for direct downloads, to allow showing proper completion of transfers from direct friends. - moved the direction flag upward in the pipeline (ftDataSend instead of p3turtle) git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3313 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/ft/ftdata.h | 12 +- libretroshare/src/ft/ftdatamultiplex.cc | 10 +- libretroshare/src/ft/ftdatamultiplex.h | 2 +- libretroshare/src/ft/ftserver.cc | 86 ++++++- libretroshare/src/ft/ftserver.h | 4 +- libretroshare/src/ft/fttransfermodule.cc | 3 +- libretroshare/src/pqi/pqi.h | 6 + libretroshare/src/pqi/pqihandler.cc | 80 +++++-- libretroshare/src/pqi/pqihandler.h | 11 +- libretroshare/src/serialiser/rsbaseitems.cc | 249 +++++++++++++++++++- libretroshare/src/serialiser/rsbaseitems.h | 77 ++++-- libretroshare/src/turtle/p3turtle.cc | 10 +- libretroshare/src/turtle/p3turtle.h | 4 +- 13 files changed, 483 insertions(+), 71 deletions(-) diff --git a/libretroshare/src/ft/ftdata.h b/libretroshare/src/ft/ftdata.h index 65156e8fb..ec699e6b5 100644 --- a/libretroshare/src/ft/ftdata.h +++ b/libretroshare/src/ft/ftdata.h @@ -54,10 +54,14 @@ class ftDataSend /* Server Send */ virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data) = 0; - /// Send a request for a chunk map - virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash) = 0; - /// Send a chunk map - virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap) = 0; + /// Send a chunkmap[request]. Because requests/chunkmaps can go both + //directions, but for different usages, we have this "is_client" flags, + //that gives the ultimate goal of the data. "is_client==true" means that + //the message is for a client (download) instead of a server. + // + virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) = 0; + virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) = 0; + /// Send a request for a chunk crc map virtual bool sendCRC32MapRequest(const std::string& peer_id,const std::string& hash) = 0; /// Send a chunk crc map diff --git a/libretroshare/src/ft/ftdatamultiplex.cc b/libretroshare/src/ft/ftdatamultiplex.cc index 35f1655b6..35c30da2b 100644 --- a/libretroshare/src/ft/ftdatamultiplex.cc +++ b/libretroshare/src/ft/ftdatamultiplex.cc @@ -528,7 +528,7 @@ bool ftDataMultiplex::handleRecvClientChunkMapRequest(const std::string& peerId, (it->second).mCreator->getAvailabilityMap(cmap); } - mDataSend->sendChunkMap(peerId,hash,cmap); + mDataSend->sendChunkMap(peerId,hash,cmap,false); return true ; } @@ -574,7 +574,7 @@ bool ftDataMultiplex::handleRecvServerChunkMapRequest(const std::string& peerId, it->second->getAvailabilityMap(cmap); } - mDataSend->sendChunkMap(peerId,hash,cmap); + mDataSend->sendChunkMap(peerId,hash,cmap,true); return true; } @@ -719,14 +719,14 @@ bool ftDataMultiplex::getClientChunkMap(const std::string& upload_hash,const std // If the map is too old then we should ask an other map to the peer. // if(too_old) - sendChunkMapRequest(peerId,upload_hash); + sendChunkMapRequest(peerId,upload_hash,true); return true ; } -bool ftDataMultiplex::sendChunkMapRequest(const std::string& peer_id,const std::string& hash) +bool ftDataMultiplex::sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) { - return mDataSend->sendChunkMapRequest(peer_id,hash); + return mDataSend->sendChunkMapRequest(peer_id,hash,is_client); } bool ftDataMultiplex::sendCRCMapRequest(const std::string& peer_id,const std::string& hash,const CompressedChunkMap&) { diff --git a/libretroshare/src/ft/ftdatamultiplex.h b/libretroshare/src/ft/ftdatamultiplex.h index b25c05330..1f6354248 100644 --- a/libretroshare/src/ft/ftdatamultiplex.h +++ b/libretroshare/src/ft/ftdatamultiplex.h @@ -108,7 +108,7 @@ class ftDataMultiplex: public ftDataRecv, public RsQueueThread bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); /* Server/client Send */ - bool sendChunkMapRequest(const std::string& peerId, const std::string& hash) ; + bool sendChunkMapRequest(const std::string& peerId, const std::string& hash,bool is_client) ; /* Client Send */ bool sendCRCMapRequest(const std::string& peerId, const std::string& hash,const CompressedChunkMap& chnks) ; diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index 38966856b..b3a82fe37 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -738,27 +738,50 @@ bool ftServer::sendDataRequest(const std::string& peerId, const std::string& has return true; } -bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& hash) +bool ftServer::sendChunkMapRequest(const std::string& peerId,const std::string& hash,bool is_client) { if(mTurtleRouter->isTurtlePeer(peerId)) - mTurtleRouter->sendChunkMapRequest(peerId,hash) ; + mTurtleRouter->sendChunkMapRequest(peerId,hash,is_client) ; else - std::cerr << "ftServer: Warning: not sending chunk map request to peer " << peerId << ", because it's not a turtle tunnel." << std::endl ; + { + /* create a packet */ + /* push to networking part */ + RsFileChunkMapRequest *rfi = new RsFileChunkMapRequest(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + rfi->is_client = is_client ; + + mP3iface->SendFileChunkMapRequest(rfi); + } - // We only send chunkmap requests to turtle peers. This will be a problem at display time for - // direct friends, so I'll see later whether I code it or not. return true ; } -bool ftServer::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& map) +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) ; + mTurtleRouter->sendChunkMap(peerId,hash,map,is_client) ; else - std::cerr << "ftServer: Warning: not sending chunk map to peer " << peerId << ", because it's not a turtle tunnel." << std::endl ; + { + /* create a packet */ + /* push to networking part */ + RsFileChunkMap *rfi = new RsFileChunkMap(); + + /* id */ + rfi->PeerId(peerId); + + /* file info */ + rfi->hash = hash; /* ftr->hash; */ + rfi->is_client = is_client; /* ftr->hash; */ + rfi->compressed_map = map; /* ftr->hash; */ + + mP3iface->SendFileChunkMap(rfi); + } - // We only send chunkmap requests to turtle peers. This will be a problem at display time for - // direct friends, so I'll see later whether I code it or not. return true ; } bool ftServer::sendCRC32MapRequest(const std::string& peerId,const std::string& hash) @@ -1022,6 +1045,8 @@ bool ftServer::handleFileData() // now File Input. RsFileRequest *fr; RsFileData *fd; + RsFileChunkMapRequest *fcmr; + RsFileChunkMap *fcm; int i_init = 0; int i = 0; @@ -1082,7 +1107,48 @@ FileInfo(ffr); fd->fd.binData.TlvShallowClear(); delete fd; } + // now file chunkmap requests + i_init = i; + while((fcmr = mP3iface -> GetFileChunkMapRequest()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fcmr -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + /* incoming data */ + mFtDataplex->recvChunkMapRequest(fcmr->PeerId(), fcmr->hash,fcmr->is_client) ; + + delete fcmr; + } + // now file chunkmaps + i_init = i; + while((fcm = mP3iface -> GetFileChunkMap()) != NULL ) + { +#ifdef SERVER_DEBUG + std::cerr << "ftServer::handleFileData() Recvd ChunkMap request" << std::endl; + std::ostringstream out; + if (i == i_init) + { + out << "Incoming(Net) File Data:" << std::endl; + } + fcm -> print(out); + rslog(RSL_DEBUG_BASIC, ftserverzone, out.str()); +#endif + i++; /* count */ + + /* incoming data */ + mFtDataplex->recvChunkMap(fcm->PeerId(), fcm->hash,fcm->compressed_map,fcm->is_client) ; + + delete fcm; + } if (i > 0) { return 1; diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index 21e3118ad..dad8f6a37 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -210,8 +210,8 @@ virtual bool unshareDownloadDirectory(); public: virtual bool sendData(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); virtual bool sendDataRequest(const std::string& peerId, const std::string& hash, uint64_t size, uint64_t offset, uint32_t chunksize); -virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash) ; -virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap) ; +virtual bool sendChunkMapRequest(const std::string& peer_id,const std::string& hash,bool is_client) ; +virtual bool sendChunkMap(const std::string& peer_id,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) ; virtual bool sendCRC32MapRequest(const std::string&, const std::string&) ; virtual bool sendCRC32Map(const std::string&, const std::string&, const CRC32Map&) ; diff --git a/libretroshare/src/ft/fttransfermodule.cc b/libretroshare/src/ft/fttransfermodule.cc index 864aecb80..078a3180b 100644 --- a/libretroshare/src/ft/fttransfermodule.cc +++ b/libretroshare/src/ft/fttransfermodule.cc @@ -348,7 +348,7 @@ bool ftTransferModule::getChunk(const std::string& peer_id,uint32_t size_hint,ui bool val = mFileCreator->getMissingChunk(peer_id,size_hint,offset, chunk_size,source_peer_map_needed); if(source_peer_map_needed) - mMultiplexor->sendChunkMapRequest(peer_id, mHash) ; + mMultiplexor->sendChunkMapRequest(peer_id, mHash,false) ; #ifdef FT_DEBUG if (val) @@ -683,7 +683,6 @@ bool ftTransferModule::checkCRC() // _crcmap_last_source_id = (_crcmap_last_source_id+1)%mFileSources.size() ; - int n=0 ; bool found = false ; std::map::const_iterator mit ; for(mit = mFileSources.begin();mit != mFileSources.end();++mit) diff --git a/libretroshare/src/pqi/pqi.h b/libretroshare/src/pqi/pqi.h index ed39d2d34..123323ff9 100644 --- a/libretroshare/src/pqi/pqi.h +++ b/libretroshare/src/pqi/pqi.h @@ -66,6 +66,12 @@ virtual int SendFileRequest(RsFileRequest *) = 0; virtual RsFileData *GetFileData() = 0; virtual int SendFileData(RsFileData *) = 0; +virtual RsFileChunkMapRequest *GetFileChunkMapRequest() = 0; +virtual int SendFileChunkMapRequest(RsFileChunkMapRequest *) = 0; + +virtual RsFileChunkMap *GetFileChunkMap() = 0; +virtual int SendFileChunkMap(RsFileChunkMap *) = 0; + }; class P3Interface: public SearchInterface diff --git a/libretroshare/src/pqi/pqihandler.cc b/libretroshare/src/pqi/pqihandler.cc index d917e122b..b7129c6c4 100644 --- a/libretroshare/src/pqi/pqihandler.cc +++ b/libretroshare/src/pqi/pqihandler.cc @@ -311,7 +311,14 @@ int pqihandler::SendFileData(RsFileData *ns) { return HandleRsItem(ns, 0); } - +int pqihandler::SendFileChunkMapRequest(RsFileChunkMapRequest *ns) +{ + return HandleRsItem(ns, 0); +} +int pqihandler::SendFileChunkMap(RsFileChunkMap *ns) +{ + return HandleRsItem(ns, 0); +} int pqihandler::SendRsRawItem(RsRawItem *ns) { pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, @@ -450,24 +457,35 @@ void pqihandler::locked_SortnStoreItem(RsItem *item) case RS_PKT_TYPE_FILE: switch(subtype) - { - case RS_PKT_SUBTYPE_FI_REQUEST: - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "SortnStore -> File Request"); - in_request.push_back(item); - item = NULL; - break; + { + case RS_PKT_SUBTYPE_FI_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, + "SortnStore -> File Request"); + in_request.push_back(item); + item = NULL; + break; - case RS_PKT_SUBTYPE_FI_DATA: - pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, - "SortnStore -> File Data"); - in_data.push_back(item); - item = NULL; - break; + case RS_PKT_SUBTYPE_FI_DATA: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File Data"); + in_data.push_back(item); + item = NULL; + break; - default: - break; /* no match! */ - } + case RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File ChunkMap Request"); + in_chunkmap_request.push_back(item); + item = NULL; + break; + + case RS_PKT_SUBTYPE_FI_CHUNK_MAP: + pqioutput(PQL_DEBUG_BASIC, pqihandlerzone, "SortnStore -> File ChunkMap"); + in_chunkmap.push_back(item); + item = NULL; + break; + + default: + break; /* no match! */ + } break; default: @@ -549,6 +567,34 @@ RsFileData *pqihandler::GetFileData() } return NULL; } +RsFileChunkMapRequest *pqihandler::GetFileChunkMapRequest() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_chunkmap_request.size() != 0) + { + RsFileChunkMapRequest *fi = dynamic_cast(in_chunkmap_request.front()); + if (!fi) { delete in_chunkmap_request.front(); } + in_chunkmap_request.pop_front(); + return fi; + } + return NULL; +} +RsFileChunkMap *pqihandler::GetFileChunkMap() +{ + RsStackMutex stack(coreMtx); /**************** LOCKED MUTEX ****************/ + + if (in_chunkmap.size() != 0) + { + RsFileChunkMap *fi = dynamic_cast(in_chunkmap.front()); + if (!fi) { delete in_chunkmap.front(); } + in_chunkmap.pop_front(); + return fi; + } + return NULL; +} + + RsRawItem *pqihandler::GetRsRawItem() { diff --git a/libretroshare/src/pqi/pqihandler.h b/libretroshare/src/pqi/pqihandler.h index dc3c85310..afa7fec74 100644 --- a/libretroshare/src/pqi/pqihandler.h +++ b/libretroshare/src/pqi/pqihandler.h @@ -63,8 +63,12 @@ virtual RsCacheItem * GetSearchResult(); // file i/o virtual int SendFileRequest(RsFileRequest *ns); virtual int SendFileData(RsFileData *ns); -virtual RsFileRequest * GetFileRequest(); -virtual RsFileData * GetFileData(); +virtual int SendFileChunkMapRequest(RsFileChunkMapRequest *ns); +virtual int SendFileChunkMap(RsFileChunkMap *ns); +virtual RsFileRequest *GetFileRequest(); +virtual RsFileData *GetFileData(); +virtual RsFileChunkMapRequest *GetFileChunkMapRequest(); +virtual RsFileChunkMap *GetFileChunkMap(); // Rest of P3Interface virtual int tick(); @@ -101,8 +105,7 @@ void locked_SortnStoreItem(RsItem *item); SecurityPolicy *globsec; // Temporary storage... - std::list in_result, in_search, - in_request, in_data, in_service; + std::list in_result, in_search, in_request, in_data, in_service,in_chunkmap,in_chunkmap_request; private: diff --git a/libretroshare/src/serialiser/rsbaseitems.cc b/libretroshare/src/serialiser/rsbaseitems.cc index cec3d2c1e..6bc8fead8 100644 --- a/libretroshare/src/serialiser/rsbaseitems.cc +++ b/libretroshare/src/serialiser/rsbaseitems.cc @@ -26,6 +26,7 @@ #include "serialiser/rsbaseserial.h" #include "serialiser/rsbaseitems.h" +#include "serialiser/rstlvbase.h" /*** #define RSSERIAL_DEBUG 1 @@ -39,6 +40,8 @@ uint32_t RsFileItemSerialiser::size(RsItem *i) { RsFileRequest *rfr; RsFileData *rfd; + RsFileChunkMapRequest *rfcmr; + RsFileChunkMap *rfcm; if (NULL != (rfr = dynamic_cast(i))) { @@ -48,6 +51,14 @@ uint32_t RsFileItemSerialiser::size(RsItem *i) { return sizeData(rfd); } + else if (NULL != (rfcmr = dynamic_cast(i))) + { + return sizeChunkMapReq(rfcmr); + } + else if (NULL != (rfcm = dynamic_cast(i))) + { + return sizeChunkMap(rfcm); + } return 0; } @@ -57,6 +68,8 @@ bool RsFileItemSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize { RsFileRequest *rfr; RsFileData *rfd; + RsFileChunkMapRequest *rfcmr; + RsFileChunkMap *rfcm; if (NULL != (rfr = dynamic_cast(i))) { @@ -66,7 +79,14 @@ bool RsFileItemSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize { return serialiseData(rfd, data, pktsize); } - + else if (NULL != (rfcmr = dynamic_cast(i))) + { + return serialiseChunkMapReq(rfcmr,data,pktsize); + } + else if (NULL != (rfcm = dynamic_cast(i))) + { + return serialiseChunkMap(rfcm,data,pktsize); + } return false; } @@ -90,6 +110,12 @@ RsItem *RsFileItemSerialiser::deserialise(void *data, uint32_t *pktsize) case RS_PKT_SUBTYPE_FI_DATA: return deserialiseData(data, pktsize); break; + case RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST: + return deserialiseChunkMapReq(data, pktsize); + break; + case RS_PKT_SUBTYPE_FI_CHUNK_MAP: + return deserialiseChunkMap(data, pktsize); + break; default: return NULL; break; @@ -238,7 +264,25 @@ void RsFileData::clear() { fd.TlvClear(); } - +std::ostream &RsFileChunkMap::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileChunkMap", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printIndent(out, int_Indent); out << "chunks: " << (void*)(compressed_map._map[0]) << "..." << std::endl ; + printRsItemEnd(out, "RsFileChunkMap", indent); + return out; +} +std::ostream &RsFileChunkMapRequest::print(std::ostream &out, uint16_t indent) +{ + printRsItemBase(out, "RsFileChunkMapRequest", indent); + uint16_t int_Indent = indent + 2; + printIndent(out, int_Indent); out << "PeerId: " << PeerId() << std::endl ; + printIndent(out, int_Indent); out << " hash: " << hash << std::endl ; + printRsItemEnd(out, "RsFileChunkMapRequest", indent); + return out; +} std::ostream &RsFileData::print(std::ostream &out, uint16_t indent) { printRsItemBase(out, "RsFileData", indent); @@ -344,7 +388,207 @@ RsFileData *RsFileItemSerialiser::deserialiseData(void *data, uint32_t *pktsize) return item; } +uint32_t RsFileItemSerialiser::sizeChunkMapReq(RsFileChunkMapRequest *item) +{ + uint32_t s = 8; /* header */ + s += 1 ; // is_client + s += GetTlvStringSize(item->hash) ; // hash + return s; +} +uint32_t RsFileItemSerialiser::sizeChunkMap(RsFileChunkMap *item) +{ + uint32_t s = 8; /* header */ + s += 1 ; // is_client + s += GetTlvStringSize(item->hash) ; // hash + s += 4 ; // compressed map size + s += 4 * item->compressed_map._map.size() ; // compressed chunk map + + return s; +} +/* serialise the data to the buffer */ +bool RsFileItemSerialiser::serialiseChunkMapReq(RsFileChunkMapRequest *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeChunkMapReq(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt8(data, tlvsize, &offset, item->is_client); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +bool RsFileItemSerialiser::serialiseChunkMap(RsFileChunkMap *item, void *data, uint32_t *pktsize) +{ + uint32_t tlvsize = sizeChunkMap(item); + uint32_t offset = 0; + + if (*pktsize < tlvsize) + return false; /* not enough space */ + + *pktsize = tlvsize; + + bool ok = true; + + ok &= setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize); + +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Header: " << ok << std::endl; +#endif + + /* skip the header */ + offset += 8; + + /* add mandatory parts first */ + ok &= setRawUInt8(data, tlvsize, &offset, item->is_client); + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_VALUE, item->hash); + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_map._map.size()); + + for(uint32_t i=0;icompressed_map._map.size();++i) + ok &= setRawUInt32(data, tlvsize, &offset, item->compressed_map._map[i]); + + if (offset != tlvsize) + { + ok = false; +#ifdef RSSERIAL_DEBUG + std::cerr << "RsFileItemSerialiser::serialiseData() Size Error! " << std::endl; +#endif + } + + return ok; +} +RsFileChunkMapRequest *RsFileItemSerialiser::deserialiseChunkMapReq(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileChunkMapRequest *item = new RsFileChunkMapRequest(); + item->clear(); + + /* skip the header */ + offset += 8; + uint8_t tmp ; + ok &= getRawUInt8(data, *pktsize, &offset, &tmp); item->is_client = tmp; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} +RsFileChunkMap *RsFileItemSerialiser::deserialiseChunkMap(void *data, uint32_t *pktsize) +{ + /* get the type and size */ + uint32_t rstype = getRsItemId(data); + uint32_t rssize = getRsItemSize(data); + + uint32_t offset = 0; + + if ((RS_PKT_VERSION1 != getRsItemVersion(rstype)) || + (RS_PKT_CLASS_BASE != getRsItemClass(rstype)) || + (RS_PKT_TYPE_FILE != getRsItemType(rstype)) || + (RS_PKT_SUBTYPE_FI_CHUNK_MAP != getRsItemSubType(rstype))) + { + return NULL; /* wrong type */ + } + + if (*pktsize < rssize) /* check size */ + return NULL; /* not enough data */ + + /* set the packet length */ + *pktsize = rssize; + + bool ok = true; + + /* ready to load */ + RsFileChunkMap *item = new RsFileChunkMap(); + item->clear(); + + /* skip the header */ + offset += 8; + uint8_t tmp ; + ok &= getRawUInt8(data, *pktsize, &offset, &tmp); item->is_client = tmp; + ok &= GetTlvString(data, *pktsize, &offset, TLV_TYPE_STR_VALUE, item->hash); // file hash + uint32_t size =0; + ok &= getRawUInt32(data, *pktsize, &offset, &size); + + if(ok) + { + item->compressed_map._map.resize(size) ; + + for(uint32_t i=0;icompressed_map._map[i])); + } + + if (offset != rssize) + { + /* error */ + delete item; + return NULL; + } + + if (!ok) + { + delete item; + return NULL; + } + + return item; +} /*************************************************************************/ /*************************************************************************/ @@ -696,7 +940,6 @@ bool RsServiceSerialiser::serialise(RsItem *i, void *data, uint32_t *pktsize) #ifdef RSSERIAL_DEBUG std::cerr << "tlvsize : " << tlvsize << std::endl; #endif - uint32_t offset = 0; if (*pktsize < tlvsize) return false; /* not enough space */ diff --git a/libretroshare/src/serialiser/rsbaseitems.h b/libretroshare/src/serialiser/rsbaseitems.h index d97a3e4c6..473b56f25 100644 --- a/libretroshare/src/serialiser/rsbaseitems.h +++ b/libretroshare/src/serialiser/rsbaseitems.h @@ -28,15 +28,20 @@ #include +#include #include "serialiser/rsserial.h" #include "serialiser/rstlvtypes.h" const uint8_t RS_PKT_TYPE_FILE = 0x01; const uint8_t RS_PKT_TYPE_CACHE = 0x02; -const uint8_t RS_PKT_SUBTYPE_FI_REQUEST = 0x01; -const uint8_t RS_PKT_SUBTYPE_FI_DATA = 0x02; -const uint8_t RS_PKT_SUBTYPE_FI_TRANSFER = 0x03; +const uint8_t RS_PKT_SUBTYPE_FI_REQUEST = 0x01; +const uint8_t RS_PKT_SUBTYPE_FI_DATA = 0x02; +const uint8_t RS_PKT_SUBTYPE_FI_TRANSFER = 0x03; +const uint8_t RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST = 0x04; +const uint8_t RS_PKT_SUBTYPE_FI_CHUNK_MAP = 0x05; +const uint8_t RS_PKT_SUBTYPE_FI_CRC32_MAP_REQUEST = 0x06; +const uint8_t RS_PKT_SUBTYPE_FI_CRC32_MAP = 0x07; const uint8_t RS_PKT_SUBTYPE_CACHE_ITEM = 0x01; const uint8_t RS_PKT_SUBTYPE_CACHE_REQUEST = 0x02; @@ -77,32 +82,68 @@ std::ostream &print(std::ostream &out, uint16_t indent = 0); RsTlvFileData fd; }; +class RsFileChunkMapRequest: public RsItem +{ + public: + RsFileChunkMapRequest() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CHUNK_MAP_REQUEST) + {} + virtual ~RsFileChunkMapRequest() {} + virtual void clear() {} + + bool is_client ; // is the request for a client, or a server ? + std::string hash ; // hash of the file for which we request the chunk map + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; + +class RsFileChunkMap: public RsItem +{ + public: + RsFileChunkMap() + :RsItem(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, RS_PKT_TYPE_FILE, RS_PKT_SUBTYPE_FI_CHUNK_MAP) + {} + virtual ~RsFileChunkMap() {} + virtual void clear() {} + + bool is_client ; // is the request for a client, or a server ? + std::string hash ; // hash of the file for which we request the chunk map + CompressedChunkMap compressed_map ; // Chunk map of the file. + + std::ostream &print(std::ostream &out, uint16_t indent = 0); +}; /**************************************************************************/ class RsFileItemSerialiser: public RsSerialType { public: - RsFileItemSerialiser() - :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, - RS_PKT_TYPE_FILE) + RsFileItemSerialiser() + :RsSerialType(RS_PKT_VERSION1, RS_PKT_CLASS_BASE, + RS_PKT_TYPE_FILE) { return; } -virtual ~RsFileItemSerialiser() { return; } - -virtual uint32_t size(RsItem *); -virtual bool serialise (RsItem *item, void *data, uint32_t *size); -virtual RsItem * deserialise(void *data, uint32_t *size); + virtual ~RsFileItemSerialiser() { return; } + + virtual uint32_t size(RsItem *); + virtual bool serialise (RsItem *item, void *data, uint32_t *size); + virtual RsItem * deserialise(void *data, uint32_t *size); private: - /* sub types */ -virtual uint32_t sizeReq(RsFileRequest *); -virtual bool serialiseReq (RsFileRequest *item, void *data, uint32_t *size); -virtual RsFileRequest * deserialiseReq(void *data, uint32_t *size); + /* sub types */ + virtual uint32_t sizeReq(RsFileRequest *); + virtual uint32_t sizeData(RsFileData *); + virtual uint32_t sizeChunkMapReq(RsFileChunkMapRequest *); + virtual uint32_t sizeChunkMap(RsFileChunkMap *); -virtual uint32_t sizeData(RsFileData *); -virtual bool serialiseData (RsFileData *item, void *data, uint32_t *size); -virtual RsFileData * deserialiseData(void *data, uint32_t *size); + virtual bool serialiseReq (RsFileRequest *item, void *data, uint32_t *size); + virtual bool serialiseData (RsFileData *item, void *data, uint32_t *size); + virtual bool serialiseChunkMapReq(RsFileChunkMapRequest *item, void *data, uint32_t *size); + virtual bool serialiseChunkMap(RsFileChunkMap *item, void *data, uint32_t *size); + virtual RsFileRequest *deserialiseReq(void *data, uint32_t *size); + virtual RsFileChunkMapRequest *deserialiseChunkMapReq(void *data, uint32_t *size); + virtual RsFileChunkMap *deserialiseChunkMap(void *data, uint32_t *size); + virtual RsFileData *deserialiseData(void *data, uint32_t *size); }; /**************************************************************************/ diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index da5371e32..ea5ae3c21 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -1202,7 +1202,7 @@ void p3turtle::sendFileData(const std::string& peerId, const std::string& hash, sendItem(item) ; } -void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& hash) +void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& hash,bool is_client) { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ @@ -1229,16 +1229,18 @@ void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& 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 ; + std::cerr << "p3turtle::sendChunkMapRequest: consistency error!" << std::endl ; #ifdef P3TURTLE_DEBUG std::cerr << "p3turtle: sending chunk map req to peer " << peerId << ", hash=0x" << hash << ") through tunnel " << (void*)item->tunnel_id << ", next peer=" << item->PeerId() << std::endl ; @@ -1246,7 +1248,7 @@ void p3turtle::sendChunkMapRequest(const std::string& peerId,const std::string& sendItem(item) ; } -void p3turtle::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& cmap) +void p3turtle::sendChunkMap(const std::string& peerId,const std::string& hash,const CompressedChunkMap& cmap,bool is_client) { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ @@ -1274,11 +1276,13 @@ void p3turtle::sendChunkMap(const std::string& peerId,const std::string& hash,co 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) ; } diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h index e9abfa16b..1822417a3 100644 --- a/libretroshare/src/turtle/p3turtle.h +++ b/libretroshare/src/turtle/p3turtle.h @@ -284,10 +284,10 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle,/* public f 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) ; + 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) ; + 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) ;