📄 search.cpp
字号:
searchTerms.WriteUInt16(0); } else { // Start position range (0x8000 to 0xFFFF) searchTerms.WriteUInt16(0x8000); searchTerms.Write(m_searchTermsData, m_searchTermsDataSize); } DebugSend(Kad2SearchKeyReq, from->GetIPAddress(), from->GetUDPPort()); } else { if (m_searchTermsDataSize == 0) { searchTerms.WriteUInt8(0); // We send this extra byte to flag we handle large files. searchTerms.WriteUInt8(0); } else { // Set to 2 to flag we handle large files. searchTerms.WriteUInt8(2); searchTerms.Write(m_searchTermsData, m_searchTermsDataSize); } DebugSendF(wxT("KadSearchReq(Keyword)"), from->GetIPAddress(), from->GetUDPPort()); } if (from->GetVersion() >= 6) { CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA2_SEARCH_KEY_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else if (from->GetVersion() >= 3) { CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA2_SEARCH_KEY_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } else { CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA_SEARCH_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); } m_totalRequestAnswers++; break; } case NOTES: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: Notes")); // Write complete packet. CMemFile searchTerms; searchTerms.WriteUInt128(m_target); if (from->GetVersion() >= 3) { // Find file we are storing info about. uint8_t fileid[16]; m_target.ToByteArray(fileid); CKnownFile *file = theApp->sharedfiles->GetFileByID(CMD4Hash(fileid)); if (file) { // Start position range (0x0 to 0x7FFF) searchTerms.WriteUInt64(file->GetFileSize()); DebugSend(Kad2SearchNotesReq, from->GetIPAddress(), from->GetUDPPort()); if (from->GetVersion() >= 6) { CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA2_SEARCH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else { CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA2_SEARCH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } } else { PrepareToStop(); break; } } else { searchTerms.WriteUInt128(CKademlia::GetPrefs()->GetKadID()); DebugSend(KadSearchNotesReq, from->GetIPAddress(), from->GetUDPPort()); CKademlia::GetUDPListener()->SendPacket(searchTerms, KADEMLIA_SEARCH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); } m_totalRequestAnswers++; break; } case STOREFILE: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: StoreFile")); // Try to store ourselves as a source to a Node. // As a safeguard, check to see if we already stored to the max nodes. if (m_answers > SEARCHSTOREFILE_TOTAL) { PrepareToStop(); break; } // Find the file we are trying to store as a source to. uint8_t fileid[16]; m_target.ToByteArray(fileid); CKnownFile* file = theApp->sharedfiles->GetFileByID(CMD4Hash(fileid)); if (file) { // We store this mostly for GUI reasons. m_fileName = file->GetFileName().GetPrintable(); // Get our clientID for the packet. CUInt128 id(CKademlia::GetPrefs()->GetClientHash()); TagPtrList taglist; //We can use type for different types of sources. //1 HighID sources.. //2 cannot be used as older clients will not work. //3 Firewalled Kad Source. //4 >4GB file HighID Source. //5 >4GB file Firewalled Kad source. //6 Firewalled source with Direct Callback (supports >4GB) bool directCallback = false; if (theApp->IsFirewalled()) { directCallback = (Kademlia::CKademlia::IsRunning() && !Kademlia::CUDPFirewallTester::IsFirewalledUDP(true) && Kademlia::CUDPFirewallTester::IsVerified()); if (directCallback) { // firewalled, but direct udp callback is possible so no need for buddies // We are not firewalled.. taglist.push_back(new CTagVarInt(TAG_SOURCETYPE, 6)); taglist.push_back(new CTagVarInt(TAG_SOURCEPORT, thePrefs::GetPort())); if (!CKademlia::GetPrefs()->GetUseExternKadPort()) { taglist.push_back(new CTagInt16(TAG_SOURCEUPORT, CKademlia::GetPrefs()->GetInternKadPort())); } if (from->GetVersion() >= 2) { taglist.push_back(new CTagVarInt(TAG_FILESIZE, file->GetFileSize())); } } else if (theApp->clientlist->GetBuddy()) { // We are firewalled, make sure we have a buddy. // We send the ID to our buddy so they can do a callback. CUInt128 buddyID(true); buddyID ^= CKademlia::GetPrefs()->GetKadID(); taglist.push_back(new CTagInt8(TAG_SOURCETYPE, file->IsLargeFile() ? 5 : 3)); taglist.push_back(new CTagVarInt(TAG_SERVERIP, theApp->clientlist->GetBuddy()->GetIP())); taglist.push_back(new CTagVarInt(TAG_SERVERPORT, theApp->clientlist->GetBuddy()->GetUDPPort())); uint8_t hashBytes[16]; buddyID.ToByteArray(hashBytes); taglist.push_back(new CTagString(TAG_BUDDYHASH, CMD4Hash(hashBytes).Encode())); taglist.push_back(new CTagVarInt(TAG_SOURCEPORT, thePrefs::GetPort())); if (!CKademlia::GetPrefs()->GetUseExternKadPort()) { taglist.push_back(new CTagInt16(TAG_SOURCEUPORT, CKademlia::GetPrefs()->GetInternKadPort())); } if (from->GetVersion() >= 2) { taglist.push_back(new CTagVarInt(TAG_FILESIZE, file->GetFileSize())); } } else { // We are firewalled, but lost our buddy.. Stop everything. PrepareToStop(); break; } } else { // We're not firewalled.. taglist.push_back(new CTagInt8(TAG_SOURCETYPE, file->IsLargeFile() ? 4 : 1)); taglist.push_back(new CTagVarInt(TAG_SOURCEPORT, thePrefs::GetPort())); if (!CKademlia::GetPrefs()->GetUseExternKadPort()) { taglist.push_back(new CTagInt16(TAG_SOURCEUPORT, CKademlia::GetPrefs()->GetInternKadPort())); } if (from->GetVersion() >= 2) { taglist.push_back(new CTagVarInt(TAG_FILESIZE, file->GetFileSize())); } } taglist.push_back(new CTagInt8(TAG_ENCRYPTION, CPrefs::GetMyConnectOptions(true, true))); // Send packet CKademlia::GetUDPListener()->SendPublishSourcePacket(*from, m_target, id, taglist); m_totalRequestAnswers++; // Delete all tags. for (TagPtrList::const_iterator it = taglist.begin(); it != taglist.end(); ++it) { delete *it; } } else { PrepareToStop(); } break; } case STOREKEYWORD: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: StoreKeyword")); // Try to store keywords to a Node. // As a safeguard, check to see if we already stored to the max nodes. if (m_answers > SEARCHSTOREKEYWORD_TOTAL) { PrepareToStop(); break; } uint16_t count = m_fileIDs.size(); if (count == 0) { PrepareToStop(); break; } else if (count > 150) { count = 150; } UIntList::const_iterator itListFileID = m_fileIDs.begin(); uint8_t fileid[16]; while (count && (itListFileID != m_fileIDs.end())) { uint16_t packetCount = 0; CMemFile packetdata(1024*50); // Allocate a good amount of space. packetdata.WriteUInt128(m_target); packetdata.WriteUInt16(0); // Will be updated before sending. while ((packetCount < 50) && (itListFileID != m_fileIDs.end())) { CUInt128 id(*itListFileID); id.ToByteArray(fileid); CKnownFile *pFile = theApp->sharedfiles->GetFileByID(CMD4Hash(fileid)); if (pFile) { count--; packetCount++; packetdata.WriteUInt128(id); PreparePacketForTags(&packetdata, pFile); } ++itListFileID; } // Correct file count. uint64_t current_pos = packetdata.GetPosition(); packetdata.Seek(16); packetdata.WriteUInt16(packetCount); packetdata.Seek(current_pos); // Send packet if (from->GetVersion() >= 6) { DebugSend(Kad2PublishKeyReq, from->GetIPAddress(), from->GetUDPPort()); CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA2_PUBLISH_KEY_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else if (from->GetVersion() >= 2) { DebugSend(Kad2PublishKeyReq, from->GetIPAddress(), from->GetUDPPort()); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA2_PUBLISH_KEY_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } else { DebugSend(KadPublishReq, from->GetIPAddress(), from->GetUDPPort()); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA_PUBLISH_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); } } m_totalRequestAnswers++; break; } case STORENOTES: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: StoreNotes")); // Find file we are storing info about. uint8_t fileid[16]; m_target.ToByteArray(fileid); CKnownFile* file = theApp->sharedfiles->GetFileByID(CMD4Hash(fileid)); if (file) { CMemFile packetdata(1024*2); // Send the hash of the file we're storing info about. packetdata.WriteUInt128(m_target); // Send our ID with the info. packetdata.WriteUInt128(CKademlia::GetPrefs()->GetKadID()); // Create our taglist. TagPtrList taglist; taglist.push_back(new CTagString(TAG_FILENAME, file->GetFileName().GetPrintable())); if (file->GetFileRating() != 0) { taglist.push_back(new CTagVarInt(TAG_FILERATING, file->GetFileRating())); } if (!file->GetFileComment().IsEmpty()) { taglist.push_back(new CTagString(TAG_DESCRIPTION, file->GetFileComment())); } if (from->GetVersion() >= 2) { taglist.push_back(new CTagVarInt(TAG_FILESIZE, file->GetFileSize())); } packetdata.WriteTagPtrList(taglist); // Send packet if (from->GetVersion() >= 6) { DebugSend(Kad2PublishNotesReq, from->GetIPAddress(), from->GetUDPPort()); CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA2_PUBLISH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else if (from->GetVersion() >= 2) { DebugSend(Kad2PublishNotesReq, from->GetIPAddress(), from->GetUDPPort()); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA2_PUBLISH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } else { DebugSend(KadPublishNotesReq, from->GetIPAddress(), from->GetUDPPort()); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA_PUBLISH_NOTES_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); } m_totalRequestAnswers++; // Delete all tags. for (TagPtrList::const_iterator it = taglist.begin(); it != taglist.end(); ++it) { delete *it; } } else { PrepareToStop(); } break; } case FINDBUDDY: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: FindBuddy")); // Send a buddy request as we are firewalled. // As a safeguard, check to see if we already requested the max nodes. if (m_answers > SEARCHFINDBUDDY_TOTAL) { PrepareToStop(); break; } CMemFile packetdata; // Send the ID we used to find our buddy. Used for checks later and allows users to callback someone if they change buddies. packetdata.WriteUInt128(m_target); // Send client hash so they can do a callback. packetdata.WriteUInt128(CKademlia::GetPrefs()->GetClientHash()); // Send client port so they can do a callback. packetdata.WriteUInt16(thePrefs::GetPort()); DebugSend(KadFindBuddyReq, from->GetIPAddress(), from->GetUDPPort()); if (from->GetVersion() >= 6) { CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA_FINDBUDDY_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else { CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA_FINDBUDDY_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } m_answers++; break; } case FINDSOURCE: { AddDebugLogLineM(false, logKadSearch, wxT("Search request type: FindSource")); // Try to find if this is a buddy to someone we want to contact. // As a safeguard, check to see if we already requested the max nodes. if (m_answers > SEARCHFINDSOURCE_TOTAL) { PrepareToStop(); break; } CMemFile packetdata(34); // This is the ID that the person we want to contact used to find a buddy. packetdata.WriteUInt128(m_target); if (m_fileIDs.size() != 1) { throw wxString(wxT("Kademlia.CSearch.processResponse: m_fileIDs.size() != 1")); } // Currently, we limit the type of callbacks for sources. We must know a file this person has for it to work. packetdata.WriteUInt128(m_fileIDs.front()); // Send our port so the callback works. packetdata.WriteUInt16(thePrefs::GetPort()); // Send packet DebugSend(KadCallbackReq, from->GetIPAddress(), from->GetUDPPort()); if (from->GetVersion() >= 6) { CUInt128 clientID = from->GetClientID(); CKademlia::GetUDPListener()->SendPacket(packetdata, KADEMLIA_CALLBACK_REQ, from->GetIPAddress(), from->GetUDPPort(), from->GetUDPKey(), &clientID); } else { CKademlia::GetUDPListener()->SendPacket( packetdata, KADEMLIA_CALLBACK_REQ, from->GetIPAddress(), from->GetUDPPort(), 0, NULL); wxASSERT(from->GetUDPKey() == CKadUDPKey(0)); } m_answers++; break; } case NODESPECIAL: { // we are looking for the IP of a given NodeID, so we just check if we 0 distance and if so, report the // tip to the requester if (fromDistance == 0) { m_nodeSpecialSearchRequester-> KadSearchIPByNodeIDResult(KCSR_SUCCEEDED, wxUINT32_SWAP_ALWAYS(from->GetIPAddress()), from->GetTCPPort()); m_nodeSpecialSearchRequester = NULL; PrepareToStop(); } break; } case NODECOMPLETE: AddDebugLogLineM(false, logKadSearch, wxT("Search request type: NodeComplete")); break; case NODE: AddDebugLogLineM(false, logKadSearch, wxT("Search request type: Node")); break; default: AddDebugLogLineM(false, logKadSearch, wxString::Format(wxT("Search result type: Unknown (%i)"),m_type)); break; }}void CSearch::ProcessResult(const CUInt128& answer, TagPtrList *info){ wxString type = wxT("Unknown"); switch (m_type) { case FILE: type = wxT("File"); ProcessResultFile(answer, info); break; case KEYWORD: type = wxT("Keyword"); ProcessResultKeyword(answer, info); break; case NOTES: type = wxT("Notes"); ProcessResultNotes(answer, info); break; } AddDebugLogLineM(false, logKadSearch, wxT("Got result (") + type + wxT(")"));}void CSearch::ProcessResultFile(const CUInt128& answer, TagPtrList *info){ // Process a possible source to a file. // Set of data we could receive from the result. uint8_t type = 0; uint32_t ip = 0; uint16_t tcp = 0; uint16_t udp = 0; uint32_t buddyip = 0; uint16_t buddyport = 0; uint8_t byCryptOptions = 0; // 0 = not supported. CUInt128 buddy; for (TagPtrList::const_iterator it = info->begin(); it != info->end(); ++it) { CTag *tag = *it; if (!tag->GetName().Cmp(TAG_SOURCETYPE)) { type = tag->GetInt(); } else if (!tag->GetName().Cmp(TAG_SOURCEIP)) { ip = tag->GetInt(); } else if (!tag->GetName().Cmp(TAG_SOURCEPORT)) { tcp = tag->GetInt(); } else if (!tag->GetName().Cmp(TAG_SOURCEUPORT)) { udp = tag->GetInt(); } else if (!tag->GetName().Cmp((TAG_SERVERIP))) { buddyip = tag->GetInt(); } else if (!tag->GetName().Cmp(TAG_SERVERPORT)) { buddyport = tag->GetInt(); } else if (!tag->GetName().Cmp(TAG_BUDDYHASH)) { CMD4Hash hash; // TODO: Error handling if (!hash.Decode(tag->GetStr())) {#ifdef __DEBUG__ printf("Invalid buddy-hash: '%s'\n", (const char*)tag->GetStr().fn_str());#endif } buddy.SetValueBE(hash.GetHash()); } else if (!tag->GetName().Cmp(TAG_ENCRYPTION)) { byCryptOptions = (uint8)tag->GetInt(); } delete tag; } delete info; // Process source based on its type. Currently only one method is needed to process all types. switch( type ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -