From 99ea8af015df77f20d4aeb8e908478ba89605f7b Mon Sep 17 00:00:00 2001 From: MrAlice Date: Tue, 23 Aug 2016 21:23:58 +0200 Subject: [PATCH] added logic for file list item exchange requests --- .../src/file_sharing/directory_storage.h | 4 +- libretroshare/src/file_sharing/p3filelists.cc | 144 +++++++++++++----- libretroshare/src/file_sharing/p3filelists.h | 8 +- .../src/file_sharing/rsfilelistitems.cc | 28 ++-- .../src/file_sharing/rsfilelistitems.h | 21 +-- 5 files changed, 140 insertions(+), 65 deletions(-) diff --git a/libretroshare/src/file_sharing/directory_storage.h b/libretroshare/src/file_sharing/directory_storage.h index fbc6b3297..309bff328 100644 --- a/libretroshare/src/file_sharing/directory_storage.h +++ b/libretroshare/src/file_sharing/directory_storage.h @@ -26,7 +26,9 @@ class DirectoryStorage virtual int searchHash(const RsFileHash& hash, std::list &results) const ; virtual int searchBoolExp(Expression * exp, std::list &results) const { NOT_IMPLEMENTED() ; return 0; } - bool getUpdateTS(EntryIndex index,time_t& recurs_max_modf_TS,time_t& last_update_TS) ; + bool getUpdateTS(EntryIndex index,time_t& recurs_max_modf_TS,time_t& local_update_TS) ; + bool setUpdateTS(EntryIndex index,time_t recurs_max_modf_TS,time_t local_update_TS) ; + uint32_t getEntryType(const EntryIndex& indx) ; // returns DIR_TYPE_*, not the internal directory storage stuff. virtual bool extractData(const EntryIndex& indx,DirDetails& d); diff --git a/libretroshare/src/file_sharing/p3filelists.cc b/libretroshare/src/file_sharing/p3filelists.cc index 5ef9af42a..6fa89bd35 100644 --- a/libretroshare/src/file_sharing/p3filelists.cc +++ b/libretroshare/src/file_sharing/p3filelists.cc @@ -555,6 +555,7 @@ bool p3FileDatabase::search(const RsFileHash &hash, FileSearchFlags hintflags, F NOT_IMPLEMENTED(); return false; } + return false; } int p3FileDatabase::filterResults(const std::list& firesults,std::list& results,FileSearchFlags flags,const RsPeerId& peer_id) const @@ -628,9 +629,9 @@ void p3FileDatabase::tickRecv() { switch(item->PacketSubType()) { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast(item) ) ; + case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: handleDirSyncRequest( dynamic_cast(item) ) ; break ; - case RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM: handleDirSyncContent( dynamic_cast(item) ) ; + case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: handleDirSyncResponse( dynamic_cast(item) ) ; break ; default: std::cerr << "(EE) unhandled packet subtype " << item->PacketSubType() << " in " << __PRETTY_FUNCTION__ << std::endl; @@ -645,59 +646,119 @@ void p3FileDatabase::tickSend() // go through the list of out requests and send them to the corresponding friends, if they are online. } -void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncReqItem *item) +void p3FileDatabase::handleDirSyncRequest(RsFileListsSyncRequestItem *item) { + RsFileListsSyncResponseItem *ritem = new RsFileListsSyncResponseItem; + // look at item TS. If local is newer, send the full directory content. - - time_t recurs_max_modf_TS, last_update_TS; - - P3FILELISTS_DEBUG() << "Received directory sync request. index=" << item->entry_index << ", flags=" << (void*)(intptr_t)item->flags << ", request id: " << std::hex << item->request_id << std::dec << ", last known TS: " << item->last_known_recurs_modf_TS << std::endl; - - if(!mLocalSharedDirs->getUpdateTS(item->entry_index,recurs_max_modf_TS,last_update_TS)) { - std::cerr << "(EE) Cannot get update TS for entry " << item->entry_index << " in local dir, asked by " << item->PeerId() << std::endl; - return ; + RS_STACK_MUTEX(mFLSMtx) ; + + P3FILELISTS_DEBUG() << "Received directory sync request. index=" << item->entry_index << ", flags=" << (void*)(intptr_t)item->flags << ", request id: " << std::hex << item->request_id << std::dec << ", last known TS: " << item->last_known_recurs_modf_TS << std::endl; + + uint32_t entry_type = mLocalSharedDirs->getEntryType(item->entry_index) ; + ritem->PeerId(item->PeerId()) ; + ritem->request_id = item->request_id; + ritem->entry_index = item->entry_index ; + + if(entry_type != DIR_TYPE_DIR) + { + P3FILELISTS_DEBUG() << " Directory does not exist anymore, or is not a directory. Answering with proper flags." << std::endl; + + ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED ; + } + else + { + time_t local_recurs_max_time,local_update_time; + mLocalSharedDirs->getUpdateTS(item->entry_index,local_recurs_max_time,local_update_time); + + if(item->last_known_recurs_modf_TS < local_recurs_max_time) + { + P3FILELISTS_DEBUG() << " Directory is more recent than what the friend knows. Sending full dir content as response." << std::endl; + + ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_SYNC_DIR_CONTENT; + ritem->last_known_recurs_modf_TS = local_recurs_max_time; + + mLocalSharedDirs->serialiseDirEntry(item->entry_index,ritem->directory_content_data) ; + } + else + { + P3FILELISTS_DEBUG() << " Directory is up to date w.r.t. what the friend knows. Sending ACK." << std::endl; + + ritem->flags = RsFileListsItem::FLAGS_SYNC_RESPONSE | RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE ; + ritem->last_known_recurs_modf_TS = local_update_time ; + } + } } - if(item->last_known_recurs_modf_TS < recurs_max_modf_TS) - { - // send full update of directory content - } - else - { - // send last recurs update TS. - } + // sends the response. + + sendItem(ritem); } -void p3FileDatabase::handleDirSyncContent(RsFileListsSyncDirItem *item) +void p3FileDatabase::handleDirSyncResponse(RsFileListsSyncResponseItem *item) { - // update the directory content for the specified friend. + // find the correct friend entry - // set the update TS, and the remote modif TS accordingly + uint32_t fi = 0 ; - // notify the GUI if the hierarchy has changed + P3FILELISTS_DEBUG() << "Handling sync response for directory with index " << item->entry_index << std::endl; + { + RS_STACK_MUTEX(mFLSMtx) ; + fi = locked_getFriendIndex(item->PeerId()); + + // make sure we have a remote directory for that friend. + + if(mRemoteDirectories.size() <= fi) + mRemoteDirectories.resize(fi+1,NULL) ; + + if(mRemoteDirectories[fi] == NULL) + mRemoteDirectories[fi] = new RemoteDirectoryStorage(item->PeerId(),makeRemoteFileName(item->PeerId())); + } + + if(item->flags & RsFileListsItem::FLAGS_ENTRY_WAS_REMOVED) + { + P3FILELISTS_DEBUG() << " removing directory with index " << item->entry_index << " because it does not exist." << std::endl; + mRemoteDirectories[fi]->removeDirectory(item->entry_index); + } + else if(item->flags & RsFileListsItem::FLAGS_ENTRY_UP_TO_DATE) + { + P3FILELISTS_DEBUG() << " Directory is up to date. Setting local TS." << std::endl; + + mRemoteDirectories[fi]->setUpdateTS(item->entry_index,item->last_known_recurs_modf_TS,time(NULL)); + } + else if(item->flags & RsFileListsItem::FLAGS_SYNC_DIR_CONTENT) + { + P3FILELISTS_DEBUG() << " Item contains directory data. Uptating." << std::endl; + + mRemoteDirectories[fi]->deserialiseUpdateEntry(item->entry_index,item->directory_content_data) ; + mRemoteDirectories[fi]->setUpdateTS(item->entry_index,item->last_known_recurs_modf_TS,time(NULL)); + +#warning should notify the GUI here + // notify the GUI if the hierarchy has changed + } } void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *rds,DirectoryStorage::EntryIndex e) { time_t now = time(NULL) ; - // get the info for this entry - - // compare TS - // if not up to date, request update, and return (content is not certified, so no need to recurs yet). // if up to date, return, because TS is about the last modif TS below, so no need to recurs either. - time_t recurs_max_modf_TS,last_update_TS ; + // get the info for this entry - if(!rds->getUpdateTS(e,recurs_max_modf_TS,last_update_TS)) + time_t recurs_max_modf_TS_remote_time,local_update_TS; + + if(!rds->getUpdateTS(e,recurs_max_modf_TS_remote_time,local_update_TS)) { - std::cerr << "(EE) Cannot get update TS for entry " << e << " in remote dir from " << rds->peerId() << std::endl; - return ; + std::cerr << "(EE) lockec_recursSweepRemoteDirectory(): cannot get update TS for directory with index " << e << ". This is a consistency bug." << std::endl; + return; } - if(now > last_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ) + // compare TS + + if(now > local_update_TS + DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ) // we need to compare local times only. We cannot compare local (now) with remote time. { // check if a request already exists and is not too old either: no need to re-ask. @@ -707,11 +768,11 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r if(it != mPendingSyncRequests.end()) { - std::cerr << "Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl; + P3FILELISTS_DEBUG() << "Not asking for sync of directory " << e << " to friend " << rds->peerId() << " because a recent pending request still exists." << std::endl; return ; } - std::cerr << "Asking for sync of directory " << e << " because it's " << (now - last_update_TS) << " secs old since last check." << std::endl; + P3FILELISTS_DEBUG() << "Asking for sync of directory " << e << " because it's " << (now - local_update_TS) << " secs old since last check." << std::endl; DirSyncRequestData data ; @@ -719,13 +780,24 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r mPendingSyncRequests[sync_req_id] = data ; - RsFileListsSyncReqItem *item = new RsFileListsSyncReqItem ; + RsFileListsSyncRequestItem *item = new RsFileListsSyncRequestItem ; item->entry_index = e ; - item->last_known_recurs_modf_TS = recurs_max_modf_TS ; + item->flags = RsFileListsItem::FLAGS_SYNC_REQUEST ; + item->request_id = sync_req_id ; + item->last_known_recurs_modf_TS = recurs_max_modf_TS_remote_time ; item->PeerId(rds->peerId()) ; sendItem(item) ; + // Dont recurs into sub-directories, since we dont know yet were to go. + return ; } + + for(DirectoryStorage::DirIterator it(rds,e);it;++it) + locked_recursSweepRemoteDirectory(rds,*it); } + + + + diff --git a/libretroshare/src/file_sharing/p3filelists.h b/libretroshare/src/file_sharing/p3filelists.h index 58a635d8d..a15333ace 100644 --- a/libretroshare/src/file_sharing/p3filelists.h +++ b/libretroshare/src/file_sharing/p3filelists.h @@ -37,8 +37,8 @@ class LocalDirectoryUpdater ; class RemoteDirectoryStorage ; class LocalDirectoryStorage ; -class RsFileListsSyncReqItem ; -class RsFileListsSyncDirItem ; +class RsFileListsSyncRequestItem ; +class RsFileListsSyncResponseItem ; class HashStorage ; @@ -167,8 +167,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub uint32_t locked_getFriendIndex(const RsPeerId& pid); const RsPeerId& locked_getFriendFromIndex(uint32_t indx) const; - void handleDirSyncRequest(RsFileListsSyncReqItem *) ; - void handleDirSyncContent(RsFileListsSyncDirItem *) ; + void handleDirSyncRequest (RsFileListsSyncRequestItem *) ; + void handleDirSyncResponse (RsFileListsSyncResponseItem *) ; std::map mFriendIndexMap ; std::vector mFriendIndexTab; diff --git a/libretroshare/src/file_sharing/rsfilelistitems.cc b/libretroshare/src/file_sharing/rsfilelistitems.cc index 198bcc9db..ae2d1dc5f 100644 --- a/libretroshare/src/file_sharing/rsfilelistitems.cc +++ b/libretroshare/src/file_sharing/rsfilelistitems.cc @@ -15,8 +15,8 @@ RsItem* RsFileListsSerialiser::deserialise(void *data, uint32_t *size) switch(getRsItemSubType(rstype)) { - case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return deserialFileListsSyncReqItem(data, size); - case RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM: return deserialFileListsSyncDirItem(data, size); + case RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM: return deserialFileListsSyncRequestItem(data, size); + case RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM: return deserialFileListsSyncResponseItem(data, size); case RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM: return deserialFileListsConfigItem (data, size); default: @@ -77,7 +77,7 @@ bool RsFileListsItem::serialise_header(void *data,uint32_t& pktsize,uint32_t& tl return true ; } -bool RsFileListsSyncReqItem::serialise(void *data, uint32_t& size) const +bool RsFileListsSyncRequestItem::serialise(void *data, uint32_t& size) const { uint32_t tlvsize,offset=0; bool ok = true; @@ -113,7 +113,7 @@ bool RsFileListsSyncReqItem::serialise(void *data, uint32_t& size) const return ok; } -bool RsFileListsSyncDirItem::serialise(void *data, uint32_t& size) const +bool RsFileListsSyncResponseItem::serialise(void *data, uint32_t& size) const { uint32_t tlvsize,offset=0; bool ok = true; @@ -154,12 +154,12 @@ bool RsFileListsSyncDirItem::serialise(void *data, uint32_t& size) const // Deserialisation // //============================================================================================================================// -RsFileListsSyncReqItem* RsFileListsSerialiser::deserialFileListsSyncReqItem(void *data, uint32_t *size) +RsFileListsSyncRequestItem* RsFileListsSerialiser::deserialFileListsSyncRequestItem(void *data, uint32_t *size) { bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM); uint32_t offset = 8; - RsFileListsSyncReqItem* item = new RsFileListsSyncReqItem(); + RsFileListsSyncRequestItem* item = new RsFileListsSyncRequestItem(); ok &= getRawUInt32(data, *size, &offset, &item->entry_index); ok &= getRawUInt32(data, *size, &offset, &item->flags); @@ -187,12 +187,12 @@ RsFileListsSyncReqItem* RsFileListsSerialiser::deserialFileListsSyncReqItem(void return item; } -RsFileListsSyncDirItem* RsFileListsSerialiser::deserialFileListsSyncDirItem(void *data, uint32_t *size) +RsFileListsSyncResponseItem* RsFileListsSerialiser::deserialFileListsSyncResponseItem(void *data, uint32_t *size) { bool ok = checkItemHeader(data,size,RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM); uint32_t offset = 8; - RsFileListsSyncDirItem* item = new RsFileListsSyncDirItem(); + RsFileListsSyncResponseItem* item = new RsFileListsSyncResponseItem(); uint32_t entry_index ; // index of the directory to sync uint32_t flags; // used to say that it's a request or a response, say that the directory has been removed, ask for further update, etc. @@ -262,7 +262,7 @@ bool RsFileListsSerialiser::checkItemHeader(void *data,uint32_t *size,uint8_t su // Sizes // //============================================================================================================================// -uint32_t RsFileListsSyncReqItem::serial_size()const +uint32_t RsFileListsSyncRequestItem::serial_size()const { uint32_t s = 8; //header size @@ -275,7 +275,7 @@ uint32_t RsFileListsSyncReqItem::serial_size()const return s; } -uint32_t RsFileListsSyncDirItem::serial_size()const +uint32_t RsFileListsSyncResponseItem::serial_size()const { uint32_t s = 8; //header size @@ -289,14 +289,14 @@ uint32_t RsFileListsSyncDirItem::serial_size()const return s; } -void RsFileListsSyncReqItem::clear() +void RsFileListsSyncRequestItem::clear() { } -void RsFileListsSyncDirItem::clear() +void RsFileListsSyncResponseItem::clear() { directory_content_data.TlvClear(); } -std::ostream& RsFileListsSyncReqItem::print(std::ostream &out, uint16_t indent) +std::ostream& RsFileListsSyncRequestItem::print(std::ostream &out, uint16_t indent) { printRsItemBase(out, "RsFileListsSyncReqItem", indent); uint16_t int_Indent = indent + 2; @@ -311,7 +311,7 @@ std::ostream& RsFileListsSyncReqItem::print(std::ostream &out, uint16_t indent) return out; } -std::ostream& RsFileListsSyncDirItem::print(std::ostream &out, uint16_t indent) +std::ostream& RsFileListsSyncResponseItem::print(std::ostream &out, uint16_t indent) { printRsItemBase(out, "RsFileListsSyncDirItem", indent); uint16_t int_Indent = indent + 2; diff --git a/libretroshare/src/file_sharing/rsfilelistitems.h b/libretroshare/src/file_sharing/rsfilelistitems.h index 5ddd1f063..a396574d1 100644 --- a/libretroshare/src/file_sharing/rsfilelistitems.h +++ b/libretroshare/src/file_sharing/rsfilelistitems.h @@ -38,7 +38,7 @@ // These items have "flag type" numbers, but this is not used. const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM = 0x01; -const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM = 0x02; +const uint8_t RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM = 0x02; const uint8_t RS_PKT_SUBTYPE_FILELISTS_CONFIG_ITEM = 0x03; /*! @@ -64,18 +64,19 @@ public: static const uint32_t FLAGS_SYNC_REQUEST = 0x0001 ; static const uint32_t FLAGS_SYNC_RESPONSE = 0x0002 ; - static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0004 ; - static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0008 ; + static const uint32_t FLAGS_SYNC_DIR_CONTENT = 0x0004 ; + static const uint32_t FLAGS_ENTRY_UP_TO_DATE = 0x0008 ; + static const uint32_t FLAGS_ENTRY_WAS_REMOVED = 0x0010 ; }; /*! * Use to request synchronization on a specific directory. Also used to respond that the directory is up to date. */ -class RsFileListsSyncReqItem : public RsFileListsItem +class RsFileListsSyncRequestItem : public RsFileListsItem { public: - RsFileListsSyncReqItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM) {} + RsFileListsSyncRequestItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_REQ_ITEM) {} virtual void clear(); virtual std::ostream &print(std::ostream &out, uint16_t indent); @@ -89,11 +90,11 @@ public: uint64_t request_id; // use to determine if changes that have occured since last hash }; -class RsFileListsSyncDirItem : public RsFileListsItem +class RsFileListsSyncResponseItem : public RsFileListsItem { public: - RsFileListsSyncDirItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_DIR_ITEM) {} + RsFileListsSyncResponseItem() : RsFileListsItem(RS_PKT_SUBTYPE_FILELISTS_SYNC_RSP_ITEM) {} virtual void clear(); virtual std::ostream &print(std::ostream &out, uint16_t indent); @@ -122,9 +123,9 @@ public: virtual RsItem* deserialise(void *data, uint32_t *size); private: - RsFileListsSyncReqItem *deserialFileListsSyncReqItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ - RsFileListsSyncDirItem *deserialFileListsSyncDirItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ - RsFileListsSyncDirItem *deserialFileListsConfigItem (void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ + RsFileListsSyncRequestItem *deserialFileListsSyncRequestItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ + RsFileListsSyncResponseItem *deserialFileListsSyncResponseItem(void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ + RsFileListsSyncResponseItem *deserialFileListsConfigItem (void *data, uint32_t *size); /* RS_PKT_SUBTYPE_SYNC_GRP */ bool checkItemHeader(void *data, uint32_t *size, uint8_t subservice_type); };