From 1477210aa176ef00310f6e4e2289074a5b101bd2 Mon Sep 17 00:00:00 2001 From: upstream svn Date: Thu, 25 Mar 2010 12:33:23 +0000 Subject: [PATCH] Upstream tarball 10057 --- .svn-revision | 2 +- src/DownloadQueue.cpp | 11 ++ src/DownloadQueue.h | 5 + src/ECSpecialCoreTags.cpp | 18 +- src/ExternalConn.cpp | 295 ++++++++++++++++++++++----------- src/ExternalConn.h | 87 +--------- src/PartFile.cpp | 1 + src/PartFile.h | 4 +- src/amule-remote-gui.cpp | 62 ++++--- src/amule-remote-gui.h | 74 ++++----- src/libs/ec/abstracts/ECCodes.abstract | 3 + src/libs/ec/cpp/ECCodes.h | 6 +- src/libs/ec/cpp/ECSpecialTags.h | 70 ++++---- src/libs/ec/java/ECCodes.java | 2 + 14 files changed, 342 insertions(+), 298 deletions(-) diff --git a/.svn-revision b/.svn-revision index 95afea96..2a982d1d 100644 --- a/.svn-revision +++ b/.svn-revision @@ -1 +1 @@ -10053 +10057 diff --git a/src/DownloadQueue.cpp b/src/DownloadQueue.cpp index 92a96794..3eda132c 100644 --- a/src/DownloadQueue.cpp +++ b/src/DownloadQueue.cpp @@ -177,6 +177,17 @@ uint16 CDownloadQueue::GetFileCount() const } +void CDownloadQueue::CopyFileList(std::vector& out_list) const +{ + wxMutexLocker lock(m_mutex); + + out_list.reserve(m_filelist.size()); + for (FileQueue::const_iterator it = m_filelist.begin(); it != m_filelist.end(); ++it) { + out_list.push_back(*it); + } +} + + CServer* CDownloadQueue::GetUDPServer() const { wxMutexLocker lock( m_mutex ); diff --git a/src/DownloadQueue.h b/src/DownloadQueue.h index a3f356dd..6a334020 100644 --- a/src/DownloadQueue.h +++ b/src/DownloadQueue.h @@ -246,6 +246,11 @@ public: uint16 GetFileCount() const; /** + * Makes a copy of the file list. + */ + void CopyFileList(std::vector& out_list) const; + + /** * Returns the current number of downloading files. */ uint16 GetDownloadingFileCount() const; diff --git a/src/ECSpecialCoreTags.cpp b/src/ECSpecialCoreTags.cpp index e720a225..ca362b13 100644 --- a/src/ECSpecialCoreTags.cpp +++ b/src/ECSpecialCoreTags.cpp @@ -122,9 +122,9 @@ CEC_ConnState_Tag::CEC_ConnState_Tag(EC_DETAIL_LEVEL detail_level) : CECTag(EC_T AddTag(CECTag(EC_TAG_CLIENT_ID, theApp->GetID())); } -CEC_PartFile_Tag::CEC_PartFile_Tag(CPartFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap) +CEC_PartFile_Tag::CEC_PartFile_Tag(const CPartFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap) : -CECTag(EC_TAG_PARTFILE, file->ECID()) +CEC_SharedFile_Tag(file, detail_level, valuemap, EC_TAG_PARTFILE) { AddTag(EC_TAG_PARTFILE_STATUS, file->GetStatus(), valuemap); AddTag(EC_TAG_PARTFILE_STOPPED, file->IsStopped(), valuemap); @@ -171,21 +171,13 @@ CECTag(EC_TAG_PARTFILE, file->ECID()) if (detail_level == EC_DETAIL_UPDATE) { return; } - - AddTag(EC_TAG_PARTFILE_NAME, file->GetFileName().GetPrintable(), valuemap); - - AddTag(EC_TAG_PARTFILE_HASH, file->GetFileHash(), valuemap); AddTag(EC_TAG_PARTFILE_PARTMETID, file->GetPartMetNumber(), valuemap); - - AddTag(EC_TAG_PARTFILE_SIZE_FULL, file->GetFileSize(), valuemap); - - AddTag(EC_TAG_PARTFILE_ED2K_LINK, - theApp->CreateED2kLink(file, (theApp->IsConnectedED2K() && !theApp->serverconnect->IsLowID())), valuemap); } -CEC_SharedFile_Tag::CEC_SharedFile_Tag(const CKnownFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap) -: CECTag(EC_TAG_KNOWNFILE, file->ECID()) +CEC_SharedFile_Tag::CEC_SharedFile_Tag(const CKnownFile *file, EC_DETAIL_LEVEL detail_level, + CValueMap *valuemap, ec_tagname_t name) +: CECTag(name, file->ECID()) { AddTag(EC_TAG_KNOWNFILE_REQ_COUNT, file->statistic.GetRequests(), valuemap); AddTag(EC_TAG_KNOWNFILE_REQ_COUNT_ALL, file->statistic.GetAllTimeRequests(), valuemap); diff --git a/src/ExternalConn.cpp b/src/ExternalConn.cpp index 13afe712..4aa49c17 100644 --- a/src/ExternalConn.cpp +++ b/src/ExternalConn.cpp @@ -56,6 +56,141 @@ #include "kademlia/kademlia/UDPFirewallTester.h" +//-------------------- File_Encoder -------------------- + + +/* + * Encode 'obtained parts' info to be sent to remote gui + */ +class CKnownFile_Encoder { + // number of sources for each part for progress bar colouring + RLE_Data m_enc_data; +protected: + const CKnownFile *m_file; +public: + CKnownFile_Encoder(const CKnownFile *file = 0) { m_file = file; } + + virtual ~CKnownFile_Encoder() {} + + virtual void Encode(CECTag *parent_tag); + + virtual void ResetEncoder() + { + m_enc_data.ResetEncoder(); + } + + virtual void SetShared() { } + virtual bool IsShared() { return true; } + virtual bool IsDownload() { return m_file->IsPartFile(); } + const CKnownFile * GetFile() { return m_file; } +}; + +/*! + * PartStatus strings and gap lists are quite long - RLE encoding will help. + * + * Instead of sending each time full part-status string, send + * RLE encoded difference from previous one. + * + * PartFileEncoderData class is used for decode only, + * while CPartFile_Encoder is used for encode only. + */ +class CPartFile_Encoder : public CKnownFile_Encoder { + // blocks requested for download + RLE_Data m_req_status; + // gap list + RLE_Data m_gap_status; + // source names + SourcenameItemMap m_sourcenameItemMap; + // counter for unique source name ids + int m_sourcenameID; + // not all part files are shared (only when at least one part is complete) + bool m_shared; + + // cast inherited member to CPartFile + CPartFile * m_PartFile() { wxASSERT(m_file->IsPartFile()); return (CPartFile *)m_file; } +public: + // encoder side + CPartFile_Encoder(const CPartFile *file = 0) : CKnownFile_Encoder(file) + { + m_sourcenameID = 0; + m_shared = false; + } + + virtual ~CPartFile_Encoder() {} + + // encode - take data from m_file + virtual void Encode(CECTag *parent_tag); + + // Encoder may reset history if full info requested + virtual void ResetEncoder(); + + virtual void SetShared() { m_shared = true; } + virtual bool IsShared() { return m_shared; } + virtual bool IsDownload() { return true; } +}; + +class CFileEncoderMap : public std::map { + typedef std::set IDSet; +public: + ~CFileEncoderMap(); + void UpdateEncoders(); +}; + +CFileEncoderMap::~CFileEncoderMap() +{ + // DeleteContents() causes infinite recursion here! + for (iterator it = begin(); it != end(); it++) { + delete it->second; + } +} + +// Check if encoder contains files that are no longer used +// or if we have new files without encoder yet. +void CFileEncoderMap::UpdateEncoders() +{ + IDSet curr_files, dead_files; + // Downloads + std::vector downloads; + theApp->downloadqueue->CopyFileList(downloads); + for (uint32 i = downloads.size(); i--;) { + uint32 id = downloads[i]->ECID(); + curr_files.insert(id); + if (!count(id)) { + (*this)[id] = new CPartFile_Encoder(downloads[i]); + } + } + // Shares + std::vector shares; + theApp->sharedfiles->CopyFileList(shares); + for (uint32 i = shares.size(); i--;) { + uint32 id = shares[i]->ECID(); + if (shares[i]->IsPartFile()) { // we already have it + (*this)[id]->SetShared(); + continue; + } + curr_files.insert(id); + if (!count(id)) { + (*this)[id] = new CKnownFile_Encoder(shares[i]); + } + } + // Check for removed files, and store them in a set for deletion. + // (std::map documentation is unclear if a construct like + // iterator to_del = it++; erase(to_del) ; + // works or invalidates it too.) + for (iterator it = begin(); it != end(); it++) { + if (!curr_files.count(it->first)) { + dead_files.insert(it->first); + } + } + // then delete them + for (IDSet::iterator it = dead_files.begin(); it != dead_files.end(); it++) { + iterator it2 = find(*it); + delete it2->second; + erase(it2); + } +} + + //-------------------- CECServerSocket -------------------- class CECServerSocket : public CECMuleSocket @@ -82,15 +217,9 @@ private: uint64_t m_passwd_salt; CLoggerAccess m_LoggerAccess; - CPartFile_Encoder_Map m_part_encoder; - CKnownFile_Encoder_Map m_shared_encoder; + CFileEncoderMap m_FileEncoder; CObjTagMap m_obj_tagmap; - CECPacket *ProcessRequest2( - const CECPacket *request, - CPartFile_Encoder_Map &, - CKnownFile_Encoder_Map &, - CObjTagMap &); - + CECPacket *ProcessRequest2(const CECPacket *request); }; @@ -98,10 +227,7 @@ CECServerSocket::CECServerSocket(ECNotifier *notifier) : CECMuleSocket(true), m_conn_state(CONN_INIT), -m_passwd_salt(GetRandomUint64()), -m_part_encoder(), -m_shared_encoder(), -m_obj_tagmap() +m_passwd_salt(GetRandomUint64()) { wxASSERT(theApp->ECServerHandler); theApp->ECServerHandler->AddSocket(this); @@ -134,8 +260,7 @@ const CECPacket *CECServerSocket::OnPacketReceived(const CECPacket *packet) // 2) verify password reply = Authenticate(packet); } else { - reply = ProcessRequest2( - packet, m_part_encoder, m_shared_encoder, m_obj_tagmap); + reply = ProcessRequest2(packet); } return reply; } @@ -448,7 +573,7 @@ static CECPacket *Get_EC_Response_StatRequest(const CECPacket *request, CLoggerA return response; } -static CECPacket *Get_EC_Response_GetSharedFiles(const CECPacket *request, CKnownFile_Encoder_Map &encoders) +static CECPacket *Get_EC_Response_GetSharedFiles(const CECPacket *request, CFileEncoderMap &encoders) { wxASSERT(request->GetOpCode() == EC_OP_GET_SHARED_FILES); @@ -459,7 +584,7 @@ static CECPacket *Get_EC_Response_GetSharedFiles(const CECPacket *request, CKnow // request can contain list of queried items CTagSet queryitems(request); - encoders.UpdateEncoders(theApp->sharedfiles); + encoders.UpdateEncoders(); for (uint32 i = 0; i < theApp->sharedfiles->GetFileCount(); ++i) { CKnownFile *cur_file = (CKnownFile *)theApp->sharedfiles->GetFileByIndex(i); @@ -469,43 +594,38 @@ static CECPacket *Get_EC_Response_GetSharedFiles(const CECPacket *request, CKnow } CEC_SharedFile_Tag filetag(cur_file, detail_level); - CKnownFile_Encoder &enc = encoders[cur_file]; + CKnownFile_Encoder *enc = encoders[cur_file->ECID()]; if ( detail_level != EC_DETAIL_UPDATE ) { - enc.ResetEncoder(); + enc->ResetEncoder(); } - enc.Encode(&filetag); + enc->Encode(&filetag); response->AddTag(filetag); } return response; } -static CECPacket *Get_EC_Response_GetSharedFiles(CKnownFile_Encoder_Map &encoders, CObjTagMap &tagmap) +static CECPacket *Get_EC_Response_GetUpdate(CFileEncoderMap &encoders, CObjTagMap &tagmap) { CECPacket *response = new CECPacket(EC_OP_SHARED_FILES); - encoders.UpdateEncoders(theApp->sharedfiles); - for (uint32 i = 0; i < theApp->sharedfiles->GetFileCount(); ++i) { - CKnownFile *cur_file = (CKnownFile *)theApp->sharedfiles->GetFileByIndex(i); - - // - // Hashes of tags are maintained on "per-object" basis. So, in this mode only - // same kind of objects can go into particular query type. - // But files from download queue (aka partfiles) need to be listed both as downloads - // and as shares (with different tag content). - // So simply increment the object pointer - it's only a map key and never used for referencing. - // - void * mapKey = cur_file; - if (!cur_file) continue; + encoders.UpdateEncoders(); + for (CFileEncoderMap::iterator it = encoders.begin(); it != encoders.end(); ++it) { + const CKnownFile *cur_file = it->second->GetFile(); + CValueMap &valuemap = tagmap.GetValueMap(cur_file); if (cur_file->IsPartFile()) { - mapKey = (void *) ((char *)mapKey + 1); - } + CEC_PartFile_Tag filetag((const CPartFile*) cur_file, EC_DETAIL_INC_UPDATE, &valuemap); + // Add information if partfile is shared + filetag.AddTag(EC_TAG_PARTFILE_SHARED, it->second->IsShared(), &valuemap); - CValueMap &valuemap = tagmap.GetValueMap(mapKey); - CEC_SharedFile_Tag filetag(cur_file, EC_DETAIL_INC_UPDATE, &valuemap); - CKnownFile_Encoder &enc = encoders[cur_file]; - enc.Encode(&filetag); - - response->AddTag(filetag); + CPartFile_Encoder * enc = (CPartFile_Encoder *) encoders[cur_file->ECID()]; + enc->Encode(&filetag); + response->AddTag(filetag); + } else { + CEC_SharedFile_Tag filetag(cur_file, EC_DETAIL_INC_UPDATE, &valuemap); + CKnownFile_Encoder * enc = encoders[cur_file->ECID()]; + enc->Encode(&filetag); + response->AddTag(filetag); + } } return response; } @@ -546,25 +666,7 @@ static CECPacket *Get_EC_Response_GetClientQueue(const CECPacket *request, CObjT } -static CECPacket *Get_EC_Response_GetDownloadQueue(CPartFile_Encoder_Map &encoders, CObjTagMap &tagmap) -{ - CECPacket *response = new CECPacket(EC_OP_DLOAD_QUEUE); - - encoders.UpdateEncoders(theApp->downloadqueue); - for (unsigned int i = 0; i < theApp->downloadqueue->GetFileCount(); i++) { - CPartFile *cur_file = theApp->downloadqueue->GetFileByIndex(i); - - CValueMap &valuemap = tagmap.GetValueMap(cur_file); - CEC_PartFile_Tag filetag(cur_file, EC_DETAIL_INC_UPDATE, &valuemap); - CPartFile_Encoder &enc = encoders[cur_file]; - enc.Encode(&filetag); - - response->AddTag(filetag); - } - return response; -} - -static CECPacket *Get_EC_Response_GetDownloadQueue(const CECPacket *request, CPartFile_Encoder_Map &encoders) +static CECPacket *Get_EC_Response_GetDownloadQueue(const CECPacket *request, CFileEncoderMap &encoders) { CECPacket *response = new CECPacket(EC_OP_DLOAD_QUEUE); @@ -573,7 +675,7 @@ static CECPacket *Get_EC_Response_GetDownloadQueue(const CECPacket *request, CPa // request can contain list of queried items CTagSet queryitems(request); - encoders.UpdateEncoders(theApp->downloadqueue); + encoders.UpdateEncoders(); for (unsigned int i = 0; i < theApp->downloadqueue->GetFileCount(); i++) { CPartFile *cur_file = theApp->downloadqueue->GetFileByIndex(i); @@ -584,15 +686,15 @@ static CECPacket *Get_EC_Response_GetDownloadQueue(const CECPacket *request, CPa CEC_PartFile_Tag filetag(cur_file, detail_level); - CPartFile_Encoder &enc = encoders[cur_file]; + CPartFile_Encoder * enc = (CPartFile_Encoder *) encoders[cur_file->ECID()]; if ( detail_level != EC_DETAIL_UPDATE ) { - enc.ResetEncoder(); + enc->ResetEncoder(); } - enc.Encode(&filetag); + enc->Encode(&filetag); response->AddTag(filetag); } - return response; + return response; } @@ -917,22 +1019,12 @@ void CPartFile_Encoder::Encode(CECTag *parent) // // Source part frequencies // - // These are not always populated, don't send a tag in this case - // - if (!m_file->m_SrcpartFrequency.empty()) { - int part_enc_size; - bool changed; - const uint8 *part_enc_data = m_part_status.Encode(m_file->m_SrcpartFrequency, part_enc_size, changed); - if (changed) { - parent->AddTag(CECTag(EC_TAG_PARTFILE_PART_STATUS, part_enc_size, part_enc_data)); - } - delete[] part_enc_data; - } + CKnownFile_Encoder::Encode(parent); // // Gaps // - const CGapList& gaplist = m_file->GetNewGapList(); + const CGapList& gaplist = m_PartFile()->GetNewGapList(); const size_t gap_list_size = gaplist.size(); ArrayOfUInts64 gaps; gaps.reserve(gap_list_size * 2); @@ -955,7 +1047,7 @@ void CPartFile_Encoder::Encode(CECTag *parent) // Requested blocks // ArrayOfUInts64 req_buffer; - const CPartFile::CReqBlockPtrList& requestedblocks = m_file->GetRequestedBlockList(); + const CPartFile::CReqBlockPtrList& requestedblocks = m_PartFile()->GetRequestedBlockList(); CPartFile::CReqBlockPtrList::const_iterator curr_pos2 = requestedblocks.begin(); for ( ; curr_pos2 != requestedblocks.end(); ++curr_pos2 ) { @@ -978,7 +1070,7 @@ void CPartFile_Encoder::Encode(CECTag *parent) CECEmptyTag sourceNames(EC_TAG_PARTFILE_SOURCE_NAMES); typedef std::map strIntMap; strIntMap nameMap; - const CPartFile::SourceSet &sources = m_file->GetSourceList(); + const CPartFile::SourceSet &sources = m_PartFile()->GetSourceList(); for (CPartFile::SourceSet::const_iterator it = sources.begin(); it != sources.end(); ++it) { CUpDownClient *cur_src = *it; if (cur_src->GetRequestFile() != m_file || cur_src->GetClientFilename().Length() == 0) { @@ -1037,13 +1129,16 @@ void CPartFile_Encoder::Encode(CECTag *parent) void CPartFile_Encoder::ResetEncoder() { - m_part_status.ResetEncoder(); + CKnownFile_Encoder::ResetEncoder(); m_gap_status.ResetEncoder(); m_req_status.ResetEncoder(); } void CKnownFile_Encoder::Encode(CECTag *parent) { + // + // Source part frequencies + // // Reference to the availability list const ArrayOfUInts16& list = m_file->IsPartFile() ? ((CPartFile*)m_file)->m_SrcpartFrequency : @@ -1102,8 +1197,7 @@ static CECPacket *GetStatsGraphs(const CECPacket *request) return response; } -CECPacket *CECServerSocket::ProcessRequest2(const CECPacket *request, - CPartFile_Encoder_Map &enc_part_map, CKnownFile_Encoder_Map &enc_shared_map, CObjTagMap &objmap) +CECPacket *CECServerSocket::ProcessRequest2(const CECPacket *request) { if ( !request ) { @@ -1168,24 +1262,28 @@ CECPacket *CECServerSocket::ProcessRequest2(const CECPacket *request, // // case EC_OP_GET_SHARED_FILES: - if ( request->GetDetailLevel() == EC_DETAIL_INC_UPDATE ) { - response = Get_EC_Response_GetSharedFiles(enc_shared_map, objmap); - } else { - response = Get_EC_Response_GetSharedFiles(request, enc_shared_map); + if ( request->GetDetailLevel() != EC_DETAIL_INC_UPDATE ) { + response = Get_EC_Response_GetSharedFiles(request, m_FileEncoder); } break; case EC_OP_GET_DLOAD_QUEUE: + if ( request->GetDetailLevel() != EC_DETAIL_INC_UPDATE ) { + response = Get_EC_Response_GetDownloadQueue(request, m_FileEncoder); + } + break; + // + // This will evolve into an update-all for inc tags + // + case EC_OP_GET_UPDATE: if ( request->GetDetailLevel() == EC_DETAIL_INC_UPDATE ) { - response = Get_EC_Response_GetDownloadQueue(enc_part_map, objmap); - } else { - response = Get_EC_Response_GetDownloadQueue(request, enc_part_map); + response = Get_EC_Response_GetUpdate(m_FileEncoder, m_obj_tagmap); } break; case EC_OP_GET_ULOAD_QUEUE: - response = Get_EC_Response_GetClientQueue(request, objmap, EC_OP_ULOAD_QUEUE); + response = Get_EC_Response_GetClientQueue(request, m_obj_tagmap, EC_OP_ULOAD_QUEUE); break; case EC_OP_GET_WAIT_QUEUE: - response = Get_EC_Response_GetClientQueue(request, objmap, EC_OP_WAIT_QUEUE); + response = Get_EC_Response_GetClientQueue(request, m_obj_tagmap, EC_OP_WAIT_QUEUE); break; case EC_OP_PARTFILE_REMOVE_NO_NEEDED: case EC_OP_PARTFILE_REMOVE_FULL_QUEUE: @@ -1307,7 +1405,7 @@ CECPacket *CECServerSocket::ProcessRequest2(const CECPacket *request, case EC_OP_SEARCH_RESULTS: if ( request->GetDetailLevel() == EC_DETAIL_INC_UPDATE ) { - response = Get_EC_Response_Search_Results(objmap); + response = Get_EC_Response_Search_Results(m_obj_tagmap); } else { response = Get_EC_Response_Search_Results(request); } @@ -1522,13 +1620,12 @@ CECPacket *CECServerSocket::ProcessRequest2(const CECPacket *request, response = new CECPacket(EC_OP_NOOP); } break; - - default: - AddLogLineM(false, wxString::Format(_("External Connection: invalid opcode received: %#x"), request->GetOpCode())); - wxFAIL; - response = new CECPacket(EC_OP_FAILED); - response->AddTag(CECTag(EC_TAG_STRING, wxTRANSLATE("Invalid opcode (wrong protocol version?)"))); - break; + } + if (!response) { + AddLogLineM(false, wxString::Format(_("External Connection: invalid opcode received: %#x"), request->GetOpCode())); + wxFAIL; + response = new CECPacket(EC_OP_FAILED); + response->AddTag(CECTag(EC_TAG_STRING, wxTRANSLATE("Invalid opcode (wrong protocol version?)"))); } return response; } diff --git a/src/ExternalConn.h b/src/ExternalConn.h index 54a71357..6e54feb1 100644 --- a/src/ExternalConn.h +++ b/src/ExternalConn.h @@ -39,89 +39,6 @@ class wxSocketServer; class wxSocketEvent; -// -// T - type of item -// E - type of encoder -// C - type of container in theApp -template -class CFileEncoderMap : public std::map { - public: - void UpdateEncoders(C *container) - { - // check if encoder contains files that no longer in container - // or, we have new files without encoder yet - std::set curr_files, dead_files; - for (unsigned int i = 0; i < container->GetFileCount(); i++) { - // cast for case of 'const' - T *cur_file = (T *)container->GetFileByIndex(i); - curr_files.insert(cur_file); - if ( this->count(cur_file) == 0 ) { - this->operator [](cur_file) = E(cur_file); - } - } - // - // curr_files set is created to minimize lookup time in download queue, - // since GetFileByID have loop inside leading to O(n), in this case - // it will mean O(n^2) - typename std::map::iterator i; - for(i = this->begin(); i != this->end(); i++) { - if ( curr_files.count(i->first) == 0 ) { - dead_files.insert(i->first); - } - } - typename std::set::iterator j; - for(j = dead_files.begin(); j != dead_files.end(); j++) { - this->erase(*j); - } - } -}; - -/*! - * PartStatus strings and gap lists are quite long - RLE encoding will help. - * - * Instead of sending each time full part-status string, send - * RLE encoded difference from previous one. - * - * PartFileEncoderData class is used for decode only, - * while CPartFile_Encoder is used for encode only. - */ -class CPartFile_Encoder : public PartFileEncoderData { - CPartFile *m_file; - SourcenameItemMap m_sourcenameItemMap; - int m_sourcenameID; - public: - // encoder side - CPartFile_Encoder(CPartFile *file = 0) { m_file = file; m_sourcenameID = 0; } - - // encode - take data from m_file - void Encode(CECTag *parent_tag); - - // Encoder may reset history if full info requested - void ResetEncoder(); -}; - -typedef CFileEncoderMap CPartFile_Encoder_Map; - -/* - * Encode 'obtained parts' info to be sent to remote gui - */ -class CKnownFile_Encoder { - RLE_Data m_enc_data; - CKnownFile *m_file; - public: - CKnownFile_Encoder(CKnownFile *file = 0) { m_file = file; } - - // encode - take data from m_file - void Encode(CECTag *parent_tag); - - void ResetEncoder() - { - m_enc_data.ResetEncoder(); - } -}; - -typedef CFileEncoderMap CKnownFile_Encoder_Map; - template class CTagSet : public std::set { void InSet(const CECTag *tag, uint32) @@ -146,9 +63,9 @@ class CTagSet : public std::set { class CObjTagMap { - std::map m_obj_map; + std::map m_obj_map; public: - CValueMap &GetValueMap(void *object) + CValueMap &GetValueMap(const void *object) { return m_obj_map[object]; } diff --git a/src/PartFile.cpp b/src/PartFile.cpp index df079bd9..e92e10a9 100644 --- a/src/PartFile.cpp +++ b/src/PartFile.cpp @@ -3590,6 +3590,7 @@ CPartFile::CPartFile(CEC_PartFile_Tag *tag) : CKnownFile(tag->ID()) m_kbpsDown = 0; m_iDownPriorityEC = 0; m_a4af_source_count = 0; + m_isShared = false; } /* diff --git a/src/PartFile.h b/src/PartFile.h index 80180bf6..c6e3821f 100644 --- a/src/PartFile.h +++ b/src/PartFile.h @@ -408,9 +408,11 @@ private: uint32 m_kbpsDown; uint8 m_iDownPriorityEC; + bool m_isShared; SourcenameItemMap m_SourcenameItemMap; public: - SourcenameItemMap &GetSourcenameItemMap() { return m_SourcenameItemMap; } + bool IsShared() const { return m_isShared; } + SourcenameItemMap &GetSourcenameItemMap() { return m_SourcenameItemMap; } #endif public: bool IsHashSetNeeded() const { return m_hashsetneeded; } diff --git a/src/amule-remote-gui.cpp b/src/amule-remote-gui.cpp index e3e5ce62..e8c51d7c 100644 --- a/src/amule-remote-gui.cpp +++ b/src/amule-remote-gui.cpp @@ -161,11 +161,13 @@ void CamuleRemoteGuiApp::OnPollTimer(wxTimerEvent&) } case 2: if (amuledlg->m_sharedfileswnd->IsShown()) { - sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE); + // update both downloads and shared files + sharedfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); } else if (amuledlg->m_serverwnd->IsShown()) { //serverlist->FullReload(EC_OP_GET_SERVER_LIST); } else if (amuledlg->m_transferwnd->IsShown()) { - downloadqueue->DoRequery(EC_OP_GET_DLOAD_QUEUE, EC_TAG_PARTFILE); + // update both downloads and shared files + sharedfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); switch(amuledlg->m_transferwnd->clientlistctrl->GetListView()) { case vtUploading: uploadqueue->ReQueryUp(); @@ -370,7 +372,7 @@ void CamuleRemoteGuiApp::Startup() { // Forward wxLog events to CLogger wxLog::SetActiveTarget(new CLoggerTarget); serverlist->FullReload(EC_OP_GET_SERVER_LIST); - sharedfiles->DoRequery(EC_OP_GET_SHARED_FILES, EC_TAG_KNOWNFILE); + sharedfiles->DoRequery(EC_OP_GET_UPDATE, EC_TAG_KNOWNFILE); // Start the Poll Timer poll_timer->Start(1000); @@ -1047,6 +1049,37 @@ void CSharedFilesRem::SetFilePrio(CKnownFile *file, uint8 prio) m_conn->SendPacket(&req); } +void CSharedFilesRem::ProcessUpdate(const CECPacket *reply, CECPacket *, int) +{ + // First update download list + theApp->downloadqueue->ProcessUpdate(reply, NULL, EC_TAG_PARTFILE); + + std::set core_files; + for (size_t i = 0;i < reply->GetTagCount();i++) { + CEC_SharedFile_Tag *tag = (CEC_SharedFile_Tag *)reply->GetTagByIndex(i); + uint32 id = tag->ID(); + CPartFile* partfile = theApp->downloadqueue->GetFileByID(id); + // Skip file if it is a partfile that isn't shared + if (partfile && !partfile->IsShared()) { + continue; + } + core_files.insert(id); + if ( m_items_hash.count(id) ) { + // Item already known: update it + ProcessItemUpdate(tag, m_items_hash[id]); + } else { + AddItem(CreateItem(tag)); + } + } + for(iterator it = begin(); it != end();) { + iterator it2 = it++; + if ( core_files.count(GetItemID(*it2)) == 0 ) { + RemoveItem(it2); + } + } +} + + /* * List of uploading and waiting clients. */ @@ -1270,19 +1303,13 @@ bool CDownQueueRem::AddLink(const wxString &link, uint8 cat) } -void CDownQueueRem::StopUDPRequests() -{ - // have no idea what is it about -} - - void CDownQueueRem::ResetCatParts(int cat) { // Called when category is deleted. Command will be performed on the remote side, // but files still should be updated here right away, or drawing errors (colour not available) // will happen. - for ( uint16 i = 0; i < GetFileCount(); i++ ) { - CPartFile* file = GetFileByIndex( i ); + for (iterator it = begin(); it != end(); it++) { + CPartFile* file = *it; if ( file->GetCategory() == cat ) { // Reset the category @@ -1295,18 +1322,6 @@ void CDownQueueRem::ResetCatParts(int cat) } -bool CDownQueueRem::IsPartFile(const CKnownFile *) const -{ - // hope i understand it right - return true; -} - - -void CDownQueueRem::OnConnectionState(bool) -{ -} - - CPartFile *CDownQueueRem::CreateItem(CEC_PartFile_Tag *tag) { CPartFile *file = new CPartFile(tag); @@ -1355,6 +1370,7 @@ void CDownQueueRem::ProcessItemUpdate(CEC_PartFile_Tag *tag, CPartFile *file) tag->LastDateChanged(&file->m_lastDateChanged); tag->DownloadActiveTime(&file->m_nDlActiveTime); tag->AvailablePartCount(&file->m_availablePartsCount); + tag->Shared(&file->m_isShared); tag->GetLostDueToCorruption(&file->m_iLostDueToCorruption); tag->GetGainDueToCompression(&file->m_iGainDueToCompression); diff --git a/src/amule-remote-gui.h b/src/amule-remote-gui.h index 19e04d93..51f03cf0 100644 --- a/src/amule-remote-gui.h +++ b/src/amule-remote-gui.h @@ -127,6 +127,7 @@ protected: std::map m_items_hash; // for GetByIndex + // fixme, remove this when GUI is unlocked (replace with iterator) std::vector m_idx_items; // .size() is O(N) operation in stl @@ -184,6 +185,10 @@ public: { } + typedef typename std::list::iterator iterator; + iterator begin() { return m_items.begin(); } + iterator end() { return m_items.end(); } + uint32 GetCount() { return m_item_count; @@ -211,8 +216,8 @@ public: void Flush() { - m_items.erase(this->m_items.begin(), this->m_items.end()); - m_items_hash.erase(this->m_items_hash.begin(), this->m_items_hash.end()); + m_items.clear(); + m_items_hash.clear(); m_item_count = 0; } @@ -320,12 +325,32 @@ public: for (size_t i = 0;i < reply->GetTagCount();i++) { G *tag = (G *)reply->GetTagByIndex(i); // initialize item data from EC tag - T *item = this->CreateItem(tag); - AddItem(item); + AddItem(CreateItem(tag)); + } + } + + void RemoveItem(iterator & it) + { + I item_id = GetItemID(*it); + // remove item from m_idx_items + for(int idx = 0;idx < m_item_count;idx++) { + if ( this->GetItemID(m_idx_items[idx]) == item_id ) { + m_idx_items[idx] = m_idx_items[m_item_count-1]; + break; + } } + // reduce count + m_item_count--; + // remove from map + m_items_hash.erase(item_id); + // item may contain data that need to be freed externally, before + // dtor is called and memory freed + DeleteItem(*it); + + m_items.erase(it); } - void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type) + virtual void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type) { std::set core_files; for (size_t i = 0;i < reply->GetTagCount();i++) { @@ -348,37 +373,14 @@ public: } else { // Incremental mode: new items always carry full info, // so we can add it right away - T *item = this->CreateItem(tag); - AddItem(item); + AddItem(CreateItem(tag)); } } } - std::list del_ids; - for(typename std::list::iterator j = this->m_items.begin(); j != this->m_items.end(); j++) { - I item_id = GetItemID(*j); - if ( core_files.count(item_id) == 0 ) { - del_ids.push_back(item_id); - } - } - for(typename std::list::iterator j = del_ids.begin(); j != del_ids.end(); j++) { - for(int idx = 0;idx < m_item_count;idx++) { - if ( this->GetItemID(m_idx_items[idx]) == *j ) { - m_idx_items[idx] = m_idx_items[m_item_count-1]; - break; - } - } - m_item_count--; - m_items_hash.erase(*j); - for(typename std::list::iterator k = this->m_items.begin(); k != this->m_items.end(); k++) { - if ( *j == GetItemID(*k) ) { - // item may contain data that need to be freed externally, before - // dtor is called and memory freed - this->DeleteItem(*k); - - this->m_items.erase(k); - - break; - } + for(iterator it = begin(); it != end();) { + iterator it2 = it++; + if ( core_files.count(GetItemID(*it2)) == 0 ) { + RemoveItem(it2); } } } @@ -505,9 +507,6 @@ public: CPartFile* GetFileByID(uint32 id) { return GetByID(id); } CPartFile* GetFileByIndex(unsigned int idx) { return GetByIndex(idx); } - bool IsPartFile(const CKnownFile* totest) const; - void OnConnectionState(bool bConnected); - // // User actions // @@ -519,7 +518,7 @@ public: // // Actions // - void StopUDPRequests(); + void StopUDPRequests() {} void AddFileLinkToDownload(CED2KFileLink*, uint8); bool AddLink(const wxString &link, uint8 category = 0); void UnsetCompletedFilesExist(); @@ -568,6 +567,7 @@ public: uint32 GetItemID(CKnownFile *); void ProcessItemUpdate(CEC_SharedFile_Tag *, CKnownFile *); bool Phase1Done(const CECPacket *); + void ProcessUpdate(const CECPacket *reply, CECPacket *full_req, int req_type); }; class CKnownFilesRem { diff --git a/src/libs/ec/abstracts/ECCodes.abstract b/src/libs/ec/abstracts/ECCodes.abstract index 4178bf6e..7a4a616e 100644 --- a/src/libs/ec/abstracts/ECCodes.abstract +++ b/src/libs/ec/abstracts/ECCodes.abstract @@ -141,6 +141,8 @@ EC_OP_AUTH_SALT 0x4F EC_OP_AUTH_PASSWD 0x50 EC_OP_IPFILTER_UPDATE 0x51 + +EC_OP_GET_UPDATE 0x52 [/Section] [Section Content] @@ -221,6 +223,7 @@ EC_TAG_PARTFILE 0x0300 EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS 0x031C EC_TAG_PARTFILE_AVAILABLE_PARTS 0x031D EC_TAG_PARTFILE_HASH 0x031E + EC_TAG_PARTFILE_SHARED 0x031F EC_TAG_KNOWNFILE 0x0400 EC_TAG_KNOWNFILE_XFERRED 0x0401 diff --git a/src/libs/ec/cpp/ECCodes.h b/src/libs/ec/cpp/ECCodes.h index 2ebfe572..e5cfdf4e 100644 --- a/src/libs/ec/cpp/ECCodes.h +++ b/src/libs/ec/cpp/ECCodes.h @@ -125,7 +125,8 @@ enum ECOpCodes { EC_OP_KAD_BOOTSTRAP_FROM_IP = 0x4E, EC_OP_AUTH_SALT = 0x4F, EC_OP_AUTH_PASSWD = 0x50, - EC_OP_IPFILTER_UPDATE = 0x51 + EC_OP_IPFILTER_UPDATE = 0x51, + EC_OP_GET_UPDATE = 0x52 }; enum ECTagNames { @@ -198,6 +199,7 @@ enum ECTagNames { EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS = 0x031C, EC_TAG_PARTFILE_AVAILABLE_PARTS = 0x031D, EC_TAG_PARTFILE_HASH = 0x031E, + EC_TAG_PARTFILE_SHARED = 0x031F, EC_TAG_KNOWNFILE = 0x0400, EC_TAG_KNOWNFILE_XFERRED = 0x0401, EC_TAG_KNOWNFILE_XFERRED_ALL = 0x0402, @@ -525,6 +527,7 @@ wxString GetDebugNameECOpCodes(uint8 arg) case 0x4F: return wxT("EC_OP_AUTH_SALT"); case 0x50: return wxT("EC_OP_AUTH_PASSWD"); case 0x51: return wxT("EC_OP_IPFILTER_UPDATE"); + case 0x52: return wxT("EC_OP_GET_UPDATE"); default: return CFormat(wxT("unknown %d 0x%x")) % arg % arg; } } @@ -601,6 +604,7 @@ wxString GetDebugNameECTagNames(uint16 arg) case 0x031C: return wxT("EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS"); case 0x031D: return wxT("EC_TAG_PARTFILE_AVAILABLE_PARTS"); case 0x031E: return wxT("EC_TAG_PARTFILE_HASH"); + case 0x031F: return wxT("EC_TAG_PARTFILE_SHARED"); case 0x0400: return wxT("EC_TAG_KNOWNFILE"); case 0x0401: return wxT("EC_TAG_KNOWNFILE_XFERRED"); case 0x0402: return wxT("EC_TAG_KNOWNFILE_XFERRED_ALL"); diff --git a/src/libs/ec/cpp/ECSpecialTags.h b/src/libs/ec/cpp/ECSpecialTags.h index f5ce02d8..9400bc1d 100644 --- a/src/libs/ec/cpp/ECSpecialTags.h +++ b/src/libs/ec/cpp/ECSpecialTags.h @@ -202,22 +202,46 @@ class CEC_ConnState_Tag : public CECTag { bool IsKadRunning() const { return (GetInt() & 0x10) != 0; } }; -class CEC_PartFile_Tag : public CECTag { - public: - CEC_PartFile_Tag(CPartFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap = NULL); +class CEC_SharedFile_Tag : public CECTag { + public: + CEC_SharedFile_Tag(const CKnownFile *file, EC_DETAIL_LEVEL detail_level, + CValueMap *valuemap = NULL, ec_tagname_t name = EC_TAG_KNOWNFILE); // template needs it - uint32 ID() const { return GetInt(); } - + uint32 ID() const { return GetInt(); } + CMD4Hash FileHash() const { return GetTagByNameSafe(EC_TAG_PARTFILE_HASH)->GetMD4Data(); } wxString FileHashString() const { return FileHash().Encode(); } - uint16 PartMetID() const { return GetTagByNameSafe(EC_TAG_PARTFILE_PARTMETID)->GetInt(); } wxString FileName() const { return GetTagByNameSafe(EC_TAG_PARTFILE_NAME)->GetStringData(); } + wxString FilePath() const { return GetTagByNameSafe(EC_TAG_KNOWNFILE_FILENAME)->GetStringData(); } uint64 SizeFull() const { return GetTagByNameSafe(EC_TAG_PARTFILE_SIZE_FULL)->GetInt(); } + wxString FileEd2kLink() const { return GetTagByNameSafe(EC_TAG_PARTFILE_ED2K_LINK)->GetStringData(); } + + uint8 Prio(uint8 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_PRIO, target); } + uint16 GetRequests(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_REQ_COUNT, target); } + uint32 GetAllRequests(uint32 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_REQ_COUNT_ALL, target); } + + uint16 GetAccepts(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_ACCEPT_COUNT, target); } + uint32 GetAllAccepts(uint32 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_ACCEPT_COUNT_ALL, target); } + + uint64 GetXferred(uint64 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_XFERRED, target); } + uint64 GetAllXferred(uint64 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_XFERRED_ALL, target); } + + uint16 GetCompleteSourcesLow(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_LOW, target); } + uint16 GetCompleteSourcesHigh(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_HIGH, target); } + + wxString GetAICHHash() const { return GetTagByNameSafe(EC_TAG_KNOWNFILE_AICH_MASTERHASH)->GetStringData(); } +}; + +class CEC_PartFile_Tag : public CEC_SharedFile_Tag { + public: + CEC_PartFile_Tag(const CPartFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap = NULL); + + uint16 PartMetID() const { return GetTagByNameSafe(EC_TAG_PARTFILE_PARTMETID)->GetInt(); } + uint64 SizeXfer(uint64 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_SIZE_XFER, target); } uint64 SizeDone(uint64 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_SIZE_DONE, target); } - wxString FileEd2kLink() const { return GetTagByNameSafe(EC_TAG_PARTFILE_ED2K_LINK)->GetStringData(); } uint8 FileStatus(uint8 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_STATUS, target); } bool Stopped(bool *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_STOPPED, target); } uint16 SourceCount(uint16 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_SOURCE_COUNT, target); } @@ -231,6 +255,7 @@ class CEC_PartFile_Tag : public CECTag { time_t LastDateChanged(time_t *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_LAST_RECV, target); } uint32 DownloadActiveTime(uint32 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_DOWNLOAD_ACTIVE, target); } uint16 AvailablePartCount(uint16 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_AVAILABLE_PARTS, target); } + bool Shared(bool *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_SHARED, target); } uint64 GetLostDueToCorruption(uint64 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_LOST_CORRUPTION, target); } uint64 GetGainDueToCompression(uint64 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_GAINED_COMPRESSION, target); } @@ -245,37 +270,6 @@ class CEC_PartFile_Tag : public CECTag { wxString GetFileStatusString() const; }; -class CEC_SharedFile_Tag : public CECTag { - public: - CEC_SharedFile_Tag(const CKnownFile *file, EC_DETAIL_LEVEL detail_level, CValueMap *valuemap = NULL); - - // template needs it - uint32 ID() const { return GetInt(); } - - CMD4Hash FileHash() const { return GetTagByNameSafe(EC_TAG_PARTFILE_HASH)->GetMD4Data(); } - wxString FileHashString() const { return FileHash().Encode(); } - - wxString FileName() const { return GetTagByNameSafe(EC_TAG_PARTFILE_NAME)->GetStringData(); } - wxString FilePath() const { return GetTagByNameSafe(EC_TAG_KNOWNFILE_FILENAME)->GetStringData(); } - uint64 SizeFull() const { return GetTagByNameSafe(EC_TAG_PARTFILE_SIZE_FULL)->GetInt(); } - wxString FileEd2kLink() const { return GetTagByNameSafe(EC_TAG_PARTFILE_ED2K_LINK)->GetStringData(); } - - uint8 Prio(uint8 *target = 0) const { return AssignIfExist(EC_TAG_PARTFILE_PRIO, target); } - uint16 GetRequests(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_REQ_COUNT, target); } - uint32 GetAllRequests(uint32 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_REQ_COUNT_ALL, target); } - - uint16 GetAccepts(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_ACCEPT_COUNT, target); } - uint32 GetAllAccepts(uint32 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_ACCEPT_COUNT_ALL, target); } - - uint64 GetXferred(uint64 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_XFERRED, target); } - uint64 GetAllXferred(uint64 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_XFERRED_ALL, target); } - - uint16 GetCompleteSourcesLow(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_LOW, target); } - uint16 GetCompleteSourcesHigh(uint16 *target = 0) const { return AssignIfExist(EC_TAG_KNOWNFILE_COMPLETE_SOURCES_HIGH, target); } - - wxString GetAICHHash() const { return GetTagByNameSafe(EC_TAG_KNOWNFILE_AICH_MASTERHASH)->GetStringData(); } -}; - class CEC_UpDownClient_Tag : public CECTag { public: CEC_UpDownClient_Tag(const CUpDownClient* client, EC_DETAIL_LEVEL detail_level, CValueMap* valuemap); diff --git a/src/libs/ec/java/ECCodes.java b/src/libs/ec/java/ECCodes.java index 66fa760f..1abb3186 100644 --- a/src/libs/ec/java/ECCodes.java +++ b/src/libs/ec/java/ECCodes.java @@ -116,6 +116,7 @@ public final static byte EC_OP_KAD_BOOTSTRAP_FROM_IP = 0x4E; public final static byte EC_OP_AUTH_SALT = 0x4F; public final static byte EC_OP_AUTH_PASSWD = 0x50; public final static byte EC_OP_IPFILTER_UPDATE = 0x51; +public final static byte EC_OP_GET_UPDATE = 0x52; public final static short EC_TAG_STRING = 0x0000; public final static short EC_TAG_PASSWD_HASH = 0x0001; @@ -186,6 +187,7 @@ public final static short EC_TAG_PARTFILE_SAVED_ICH = 0x031B; public final static short EC_TAG_PARTFILE_SOURCE_NAMES_COUNTS = 0x031C; public final static short EC_TAG_PARTFILE_AVAILABLE_PARTS = 0x031D; public final static short EC_TAG_PARTFILE_HASH = 0x031E; +public final static short EC_TAG_PARTFILE_SHARED = 0x031F; public final static short EC_TAG_KNOWNFILE = 0x0400; public final static short EC_TAG_KNOWNFILE_XFERRED = 0x0401; public final static short EC_TAG_KNOWNFILE_XFERRED_ALL = 0x0402; -- 2.11.4.GIT