void CRoutingZone::DbgWriteBootstrapFile() { DebugLogWarning(_T("Writing special bootstrap nodes.dat - not intended for normal use")); try { // Write a saved contact list. CUInt128 uID; CSafeBufferedFile file; CFileException fexp; if (file.Open(m_sFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary|CFile::shareDenyWrite, &fexp)) { setvbuf(file.m_pStream, NULL, _IOFBF, 32768); // The bootstrap method gets a very nice sample of contacts to save. ContactMap mapContacts; CUInt128 uRandom(CUInt128((ULONG)0), 0); CUInt128 uDistance = uRandom; uDistance.Xor(uMe); GetClosestTo(2, uRandom, uDistance, 1200, &mapContacts, false, false); // filter out Kad1 nodes for (ContactMap::iterator itContactMap = mapContacts.begin(); itContactMap != mapContacts.end(); ) { ContactMap::iterator itCurContactMap = itContactMap; ++itContactMap; CContact* pContact = itCurContactMap->second; if (pContact->GetVersion() <= 1) mapContacts.erase(itCurContactMap); } // Start file with 0 to prevent older clients from reading it. file.WriteUInt32(0); // Now tag it with a version which happens to be 2 (1 till 0.48a). file.WriteUInt32(3); file.WriteUInt32(1); // if we would use version >=3, this would mean that this is not a normal nodes.dat file.WriteUInt32((uint32_t)mapContacts.size()); for (ContactMap::const_iterator itContactMap = mapContacts.begin(); itContactMap != mapContacts.end(); ++itContactMap) { CContact* pContact = itContactMap->second; pContact->GetClientID(&uID); file.WriteUInt128(&uID); file.WriteUInt32(pContact->GetIPAddress()); file.WriteUInt16(pContact->GetUDPPort()); file.WriteUInt16(pContact->GetTCPPort()); file.WriteUInt8(pContact->GetVersion()); } file.Close(); AddDebugLogLine( false, _T("Wrote %ld contact to bootstrap file."), mapContacts.size()); } else DebugLogError(_T("Unable to store Kad file: %s"), m_sFilename); } catch (CFileException* e) { e->Delete(); AddDebugLogLine(false, _T("CFileException in CRoutingZone::writeFile")); } }
void CKademlia::StatsAddClosestDistance(CUInt128 uDist){ if (uDist.Get32BitChunk(0) > 0){ uint32_t nToAdd = (0xFFFFFFFF / uDist.Get32BitChunk(0)) / 2; if (m_liStatsEstUsersProbes.Find(nToAdd) == NULL) m_liStatsEstUsersProbes.AddHead(nToAdd); } if (m_liStatsEstUsersProbes.GetCount() > 100) m_liStatsEstUsersProbes.RemoveTail(); }
// UInt128 values are stored a little weird way... // Four little-endian 32-bit numbers, stored in // big-endian order CUInt128 CFileDataIO::ReadUInt128() const { CUInt128 value; for (int i = 0; i < 4; i++) { // Four 32bits chunks value.Set32BitChunk(i, ReadUInt32()); } return value; }
CContact *CRoutingZone::GetContact(const CUInt128& id) const throw() { if (IsLeaf()) { return m_bin->GetContact(id); } else { CUInt128 distance = CKademlia::GetPrefs()->GetKadID(); distance ^= id; return m_subZones[distance.GetBitNumber(m_level)]->GetContact(id); } }
bool CSearchManager::FindNodeFWCheckUDP(){ CancelNodeFWCheckUDPSearch(); CUInt128 uID; uID.SetValueRandom(); DebugLog(_T("Starting NODEFWCHECKUDP Kad Search")); CSearch *pSearch = new CSearch; pSearch->m_uType = CSearch::NODEFWCHECKUDP; pSearch->m_uTarget = uID; return StartSearch(pSearch); }
CContact *CRoutingZone::GetContact(const CUInt128 &uID) const { if (IsLeaf()) return m_pBin->GetContact(uID); else{ CUInt128 uDistance; CKademlia::GetPrefs()->GetKadID(&uDistance); uDistance.Xor(uID); return m_pSubZones[uDistance.GetBitNumber(m_uLevel)]->GetContact(uID); } }
bool CKadID::SetKey(CHolder<CPublicKey>& pKey, UINT eAlgorithm) { if(m_PublicKey) return m_PublicKey->GetSize() == pKey->GetSize() && memcmp(m_PublicKey->GetKey(), pKey->GetKey(), m_PublicKey->GetSize()) == 0; CUInt128 ID; MakeID(pKey, ID.GetData(), ID.GetSize(), eAlgorithm); if(CompareTo(ID) != 0) return false; m_PublicKey = pKey; return true; }
CUInt128 CKademlia::MakeCloseTarget(int *pDistance) { if(!m_pKadHandler) { if(pDistance) *pDistance = -1; return 0; } CUInt128 uMyID = m_pRootZone->GetID(); NodeMap Nodes; m_pRootZone->GetClosestNodes(uMyID, Nodes, Cfg()->GetInt("BucketSize")); if(Nodes.size() < 2) { if(pDistance) *pDistance = -1; return 0; } // Find Median distance difference between nodes closest to us vector<CUInt128> Diff; for(NodeMap::iterator np = Nodes.begin(), n = np++; np != Nodes.end(); n = np++) Diff.push_back(np->first - n->first); CUInt128 Sep = Median(Diff); // generate ID that is closer to us than the closest node by a few difference CUInt128 uDistance = Nodes.begin()->first; for(int i=0; i < 3 && uDistance > Sep; i++) uDistance = uDistance - Sep; CUInt128 uCloser = uMyID ^ uDistance; // count the matchign bits UINT uLevel=0; for(; uLevel < uMyID.GetBitSize(); uLevel++) { if(uCloser.GetBit(uLevel) != uMyID.GetBit(uLevel)) break; } // add a few more matching bytes for(UINT i=0; i < 4 && uLevel < uMyID.GetBitSize() - 1; i++) { uCloser.SetBit(uLevel, uMyID.GetBit(uLevel)); uLevel++; } if(pDistance) *pDistance = (int)uMyID.GetBitSize() - uLevel; // create a random ID that we are closest to CUInt128 uRandom(uCloser, uLevel); //wstring sTest = (uMyID ^ uRandom).ToBin(); return uRandom; }
bool CIndexed::SendStoreRequest(const CUInt128& uKeyID) { Load* pLoad; if(m_mapLoad.Lookup(CCKey(uKeyID.GetData()), pLoad)) { if(pLoad->uTime < (uint32)time(NULL)) { m_mapLoad.RemoveKey(CCKey(uKeyID.GetData())); m_uTotalIndexLoad--; delete pLoad; return true; } return false; } return true; }
void CKademlia::StatsAddClosestDistance(const CUInt128& distance) { if (distance.Get32BitChunk(0) > 0) { uint32_t toAdd = (0xFFFFFFFF / distance.Get32BitChunk(0)) / 2; std::list<uint32_t>::iterator it = m_statsEstUsersProbes.begin(); for (; it != m_statsEstUsersProbes.end(); ++it) { if (*it == toAdd) { break; } } if (it == m_statsEstUsersProbes.end()) { m_statsEstUsersProbes.push_front(toAdd); } } if (m_statsEstUsersProbes.size() > 100) { m_statsEstUsersProbes.pop_back(); } }
bool CSearchManager::FindNodeSpecial(const CUInt128& id, CKadClientSearcher *requester) { // Do a node lookup. AddDebugLogLineN(logKadSearch, wxT("Starting NODESPECIAL Kad Search for ") + id.ToHexString()); CSearch *search = new CSearch; search->SetSearchTypes(CSearch::NODESPECIAL); search->SetTargetID(id); search->SetNodeSpecialSearchRequester(requester); return StartSearch(search); }
bool CSearchManager::FindNodeSpecial(const CUInt128 &uID, CKadClientSearcher* pRequester){ // Do a node lookup. CString strDbgID; uID.ToHexString(&strDbgID); DebugLog(_T("Starting NODESPECIAL Kad Search for %s"), strDbgID); CSearch *pSearch = new CSearch; pSearch->m_uType = CSearch::NODESPECIAL; pSearch->m_uTarget = uID; pSearch->SetNodeSpecialSearchRequester(pRequester); return StartSearch(pSearch); }
void KadUDPPublisher::PublishNextDecoy(void) { KademliaProtectorSystemReference ref; Vector v_files; GetNextDecoyToPublish(v_files); if(v_files.Size()==0) return; DonkeyFile *file=(DonkeyFile*)v_files.Get(0); //if(!file->m_last_publish.HasTimedOut(60*60)){ // return; //} ref.System()->LogToFile("KadUDPPublisher::PublishNextDecoy(void) BEGIN"); //file->m_last_publish.Refresh(); Vector v_contacts; //publish ourselves as a source for this file CUInt128 key; key.setValueBE(file->m_hash); ref.System()->GetContactManager()->GetContactsForKey(key,v_contacts); while(v_contacts.Size()>20) { //TYDEBUG v_contacts.Remove(rand()%v_contacts.Size()); } TRACE("Publishing decoy %s\n",file->m_shash.c_str()); for(int i=0; i<(int)v_contacts.Size(); i++) { if(rand()&1) continue; PublishSource(key.getDataPtr(),(KadContact*)v_contacts.Get(i)); } }
CUInt128 CJSKadID::FromValue(v8::Local<v8::Value> value) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); CUInt128 Value; if(value->IsString()) Value.FromHex(CJSEngine::GetWStr(value)); else if(value->IsObject()) { if(CKadIDObj* pVariant = GetCObject<CKadIDObj>(value->ToObject())) Value = pVariant->m_Value; else if(CVariantPrx* pVariant = GetCObject<CVariantPrx>(value->ToObject())) Value = pVariant->GetCopy(); } else { sint64 iValue = value->IntegerValue(); if(iValue < 0) Value = CUInt128(true); else Value = CUInt128((sint32)iValue); } return Value; }
CUInt128::CUInt128(const CUInt128 &uValue, UINT uNumBits) { // Copy the whole ULONGs UINT uNumULONGs = uNumBits / 32; for (UINT iIndex=0; iIndex<uNumULONGs; iIndex++) m_uData[iIndex] = uValue.m_uData[iIndex]; // Copy the remaining bits for (UINT iIndex=(32*uNumULONGs); iIndex<uNumBits; iIndex++) SetBitNumber(iIndex, uValue.GetBitNumber(iIndex)); // Pad with random bytes (Not seeding based on time to allow multiple different ones to be created in quick succession) for (UINT iIndex=uNumBits; iIndex<128; iIndex++) SetBitNumber(iIndex, (rand()%2)); }
CUInt128::CUInt128(const CUInt128 &value, UINT numBits) { // Copy the whole ULONGs UINT numULONGs = numBits / 32; for (UINT i=0; i<numULONGs; i++) m_data[i] = value.m_data[i]; // Copy the remaining bits for (UINT i=(32*numULONGs); i<numBits; i++) setBitNumber(i, value.getBitNumber(i)); // Pad with random bytes (Not seeding based on time to allow multiple different ones to be created in quick succession) for (UINT i=numBits; i<128; i++) setBitNumber(i, (rand()%2)); }
void CRoutingZone::GetClosestTo(uint32_t maxType, const CUInt128& target, const CUInt128& distance, uint32_t maxRequired, ContactMap *result, bool emptyFirst, bool inUse) const { // If leaf zone, do it here if (IsLeaf()) { m_bin->GetClosestTo(maxType, target, maxRequired, result, emptyFirst, inUse); return; } // otherwise, recurse in the closer-to-the-target subzone first int closer = distance.GetBitNumber(m_level); m_subZones[closer]->GetClosestTo(maxType, target, distance, maxRequired, result, emptyFirst, inUse); // if still not enough tokens found, recurse in the other subzone too if (result->size() < maxRequired) { m_subZones[1-closer]->GetClosestTo(maxType, target, distance, maxRequired, result, false, inUse); } }
void CRoutingZone::GetClosestTo(uint32 uMaxType, const CUInt128 &uTarget, const CUInt128 &uDistance, uint32 uMaxRequired, ContactMap *pmapResult, bool bEmptyFirst, bool bInUse) const { // If leaf zone, do it here if (IsLeaf()) { m_pBin->GetClosestTo(uMaxType, uTarget, uMaxRequired, pmapResult, bEmptyFirst, bInUse); return; } // otherwise, recurse in the closer-to-the-target subzone first int iCloser = uDistance.GetBitNumber(m_uLevel); m_pSubZones[iCloser]->GetClosestTo(uMaxType, uTarget, uDistance, uMaxRequired, pmapResult, bEmptyFirst, bInUse); // if still not enough tokens found, recurse in the other subzone too if (pmapResult->size() < uMaxRequired) m_pSubZones[1-iCloser]->GetClosestTo(uMaxType, uTarget, uDistance, uMaxRequired, pmapResult, false, bInUse); }
bool CIndexed::AddLoad(const CUInt128& uKeyID, uint32 uTime) { //This is needed for when you restart the client. if((uint32)time(NULL)>uTime) return false; Load* pLoad; if(m_mapLoad.Lookup(CCKey(uKeyID.GetData()), pLoad)) return false; pLoad = new Load(); pLoad->uKeyID.SetValue(uKeyID); pLoad->uTime = uTime; m_mapLoad.SetAt(CCKey(pLoad->uKeyID.GetData()), pLoad); m_uTotalIndexLoad++; return true; }
void CRoutingZone::ReadBootstrapNodesDat(CFileDataIO& file){ // Bootstrap versions of nodes.dat files, are in the style of version 1 nodes.dats. The difference is that // they will contain more contacts 500-1000 instead 50, and those contacts are not added into the routingtable // but used to sent Bootstrap packets too. The advantage is that on a list with a high ratio of dead nodes, // we will be able to bootstrap faster than on a normal nodes.dat and more important, if we would deliver // a normal nodes.dat with eMule, those 50 nodes would be kinda DDOSed because everyone adds them to their routing // table, while with this style, we don't actually add any of the contacts to our routing table in the end and we // ask only one of those 1000 contacts one time (well or more untill we find an alive one). if (!CKademlia::s_liBootstapList.IsEmpty()){ ASSERT( false ); return; } uint32_t uNumContacts = file.ReadUInt32(); if (uNumContacts != 0 && uNumContacts * 25 == (file.GetLength() - file.GetPosition())) { uint32_t uValidContacts = 0; CUInt128 uID; while ( uNumContacts ) { file.ReadUInt128(&uID); uint32_t uIP = file.ReadUInt32(); uint16_t uUDPPort = file.ReadUInt16(); uint16_t uTCPPort = file.ReadUInt16(); uint8_t uContactVersion = file.ReadUInt8(); uint32_t uhostIP = ntohl(uIP); if (::IsGoodIPPort(uhostIP, uUDPPort)) { if (::theApp.ipfilter->IsFiltered(uhostIP)) { if (::thePrefs.GetLogFilteredIPs()) AddDebugLogLine(false, _T("Ignored kad contact (IP=%s:%u)--read known.dat -- - IP filter (%s)") , ipstr(uhostIP), uUDPPort, ::theApp.ipfilter->GetLastHit()); } else if (uUDPPort == 53 && uContactVersion <= KADEMLIA_VERSION5_48a) { if (::thePrefs.GetLogFilteredIPs()) AddDebugLogLine(false, _T("Ignored kad contact (IP=%s:%u)--read known.dat") , ipstr(uhostIP), uUDPPort); } else if (uContactVersion > 1) // only kad2 nodes { // we want the 50 nodes closest to our own ID (provides randomness between different users and gets has good chances to get a bootstrap with close Nodes which is a nice start for our routing table) CUInt128 uDistance = uMe; uDistance.Xor(uID); uValidContacts++; // don't bother if we already have 50 and the farest distance is smaller than this contact if (CKademlia::s_liBootstapList.GetCount() < 50 || CKademlia::s_liBootstapList.GetTail()->GetDistance() > uDistance){ // look were to put this contact into the proper position bool bInserted = false; CContact* pContact = new CContact(uID, uIP, uUDPPort, uTCPPort, uMe, uContactVersion, 0, false); for (POSITION pos = CKademlia::s_liBootstapList.GetHeadPosition(); pos != NULL; CKademlia::s_liBootstapList.GetNext(pos)){ if (CKademlia::s_liBootstapList.GetAt(pos)->GetDistance() > uDistance){ CKademlia::s_liBootstapList.InsertBefore(pos, pContact); bInserted = true; break; } } if (!bInserted){ ASSERT( CKademlia::s_liBootstapList.GetCount() < 50 ); CKademlia::s_liBootstapList.AddTail(pContact); } else if (CKademlia::s_liBootstapList.GetCount() > 50) delete CKademlia::s_liBootstapList.RemoveTail(); } } } uNumContacts--; } AddLogLine( false, GetResString(IDS_KADCONTACTSREAD), CKademlia::s_liBootstapList.GetCount()); DebugLog(_T("Loaded Bootstrap nodes.dat, selected %u out of %u valid contacts"), CKademlia::s_liBootstapList.GetCount(), uValidContacts); } }
void CIndexed::SendValidKeywordResult(const CUInt128& uKeyID, const SSearchTerm* pSearchTerms, uint32 uIP, uint16 uPort, bool bOldClient, bool bKad2, uint16 uStartPosition) { KeyHash* pCurrKeyHash; if(m_mapKeyword.Lookup(CCKey(uKeyID.GetData()), pCurrKeyHash)) { byte byPacket[1024*50]; CByteIO byIO(byPacket,sizeof(byPacket)); byIO.WriteByte(OP_KADEMLIAHEADER); if(bKad2) { byIO.WriteByte(KADEMLIA2_SEARCH_RES); byIO.WriteUInt128(Kademlia::CKademlia::GetPrefs()->GetKadID()); } else byIO.WriteByte(KADEMLIA_SEARCH_RES); byIO.WriteUInt128(uKeyID); byIO.WriteUInt16(50); uint16 uMaxResults = 300; int iCount = 0-uStartPosition; POSITION pos1 = pCurrKeyHash->mapSource.GetStartPosition(); while( pos1 != NULL ) { CCKey key1; Source* pCurrSource; pCurrKeyHash->mapSource.GetNextAssoc( pos1, key1, pCurrSource ); for(POSITION pos2 = pCurrSource->ptrlEntryList.GetHeadPosition(); pos2 != NULL; ) { CEntry* pCurrName = pCurrSource->ptrlEntryList.GetNext(pos2); if ( !pSearchTerms || SearchTermsMatch(pSearchTerms, pCurrName) ) { if( iCount < 0 ) iCount++; else if( (uint16)iCount < uMaxResults ) { if((!bOldClient || pCurrName->m_uSize <= OLD_MAX_EMULE_FILE_SIZE)) { iCount++; byIO.WriteUInt128(pCurrName->m_uSourceID); byIO.WriteTagList(pCurrName->m_listTag); if( iCount % 50 == 0 ) { uint32 uLen = sizeof(byPacket)-byIO.GetAvailable(); CKademlia::GetUDPListener()->SendPacket(byPacket, uLen, uIP, uPort); byIO.Reset(); byIO.WriteByte(OP_KADEMLIAHEADER); if(bKad2) { if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA2_SEARCH_RES", uIP, uPort); byIO.WriteByte(KADEMLIA2_SEARCH_RES); byIO.WriteUInt128(Kademlia::CKademlia::GetPrefs()->GetKadID()); } else { if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA_SEARCH_RES", uIP, uPort); byIO.WriteByte(KADEMLIA_SEARCH_RES); } byIO.WriteUInt128(uKeyID); byIO.WriteUInt16(50); } } } else { pos1 = NULL; break; } } } } if(iCount > 0) { uint16 uCountLeft = (uint16)iCount % 50; if( uCountLeft ) { uint32 uLen = sizeof(byPacket)-byIO.GetAvailable(); if(bKad2) { memcpy(byPacket+18+16, &uCountLeft, 2); if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA2_SEARCH_RES", uIP, uPort); } else { memcpy(byPacket+18, &uCountLeft, 2); if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA_SEARCH_RES", uIP, uPort); } CKademlia::GetUDPListener()->SendPacket(byPacket, uLen, uIP, uPort); } } } Clean(); }
bool CIndexed::AddKeyword(const CUInt128& uKeyID, const CUInt128& uSourceID, Kademlia::CEntry* pEntry, uint8& uLoad) { if( !pEntry ) return false; if( m_uTotalIndexKeyword > KADEMLIAMAXENTRIES ) { uLoad = 100; return false; } if( pEntry->m_uSize == 0 || pEntry->m_fileName.IsEmpty() || pEntry->m_listTag.size() == 0 || pEntry->m_tLifetime < time(NULL)) return false; KeyHash* pCurrKeyHash; if(!m_mapKeyword.Lookup(CCKey(uKeyID.GetData()), pCurrKeyHash)) { Source* pCurrSource = new Source; pCurrSource->uSourceID.SetValue(uSourceID); pCurrSource->ptrlEntryList.AddHead(pEntry); pCurrKeyHash = new KeyHash; pCurrKeyHash->uKeyID.SetValue(uKeyID); pCurrKeyHash->mapSource.SetAt(CCKey(pCurrSource->uSourceID.GetData()), pCurrSource); m_mapKeyword.SetAt(CCKey(pCurrKeyHash->uKeyID.GetData()), pCurrKeyHash); uLoad = 1; m_uTotalIndexKeyword++; return true; } else { uint32 uIndexTotal = pCurrKeyHash->mapSource.GetCount(); if ( uIndexTotal > KADEMLIAMAXINDEX ) { uLoad = 100; //Too many entries for this Keyword.. return false; } Source* pCurrSource; if(pCurrKeyHash->mapSource.Lookup(CCKey(uSourceID.GetData()), pCurrSource)) { if (pCurrSource->ptrlEntryList.GetCount() > 0) { if( uIndexTotal > KADEMLIAMAXINDEX - 5000 ) { uLoad = 100; //We are in a hot node.. If we continued to update all the publishes //while this index is full, popular files will be the only thing you index. return false; } delete pCurrSource->ptrlEntryList.GetHead(); pCurrSource->ptrlEntryList.RemoveHead(); } else m_uTotalIndexKeyword++; uLoad = (uint8)((uIndexTotal*100)/KADEMLIAMAXINDEX); pCurrSource->ptrlEntryList.AddHead(pEntry); return true; } else { pCurrSource = new Source; pCurrSource->uSourceID.SetValue(uSourceID); pCurrSource->ptrlEntryList.AddHead(pEntry); pCurrKeyHash->mapSource.SetAt(CCKey(pCurrSource->uSourceID.GetData()), pCurrSource); m_uTotalIndexKeyword++; uLoad = (uint8)((uIndexTotal*100)/KADEMLIAMAXINDEX); return true; } } }
bool CIndexed::AddNotes(const CUInt128& uKeyID, const CUInt128& uSourceID, Kademlia::CEntry* pEntry, uint8& uLoad) { if( !pEntry ) return false; if( pEntry->m_uIP == 0 || pEntry->m_listTag.size() == 0 ) return false; SrcHash* pCurrNoteHash; if(!m_mapNotes.Lookup(CCKey(uKeyID.GetData()), pCurrNoteHash)) { Source* pCurrNote = new Source; pCurrNote->uSourceID.SetValue(uSourceID); pCurrNote->ptrlEntryList.AddHead(pEntry); SrcHash* pCurrNoteHash = new SrcHash; pCurrNoteHash->uKeyID.SetValue(uKeyID); pCurrNoteHash->ptrlistSource.AddHead(pCurrNote); m_mapNotes.SetAt(CCKey(pCurrNoteHash->uKeyID.GetData()), pCurrNoteHash); uLoad = 1; m_uTotalIndexNotes++; return true; } else { uint32 uSize = pCurrNoteHash->ptrlistSource.GetSize(); for(POSITION pos1 = pCurrNoteHash->ptrlistSource.GetHeadPosition(); pos1 != NULL; ) { Source* pCurrNote = pCurrNoteHash->ptrlistSource.GetNext(pos1); if( pCurrNote->ptrlEntryList.GetSize() ) { CEntry* pCurrEntry = pCurrNote->ptrlEntryList.GetHead(); if(pCurrEntry->m_uIP == pEntry->m_uIP || pCurrEntry->m_uSourceID == pEntry->m_uSourceID) { delete pCurrNote->ptrlEntryList.RemoveHead(); pCurrNote->ptrlEntryList.AddHead(pEntry); uLoad = (uint8)((uSize*100)/KADEMLIAMAXNOTESPERFILE); return true; } } else { //This should never happen! pCurrNote->ptrlEntryList.AddHead(pEntry); ASSERT(0); uLoad = (uint8)((uSize*100)/KADEMLIAMAXNOTESPERFILE); m_uTotalIndexKeyword++; return true; } } if( uSize > KADEMLIAMAXNOTESPERFILE ) { Source* pCurrNote = pCurrNoteHash->ptrlistSource.RemoveTail(); delete pCurrNote->ptrlEntryList.RemoveTail(); pCurrNote->uSourceID.SetValue(uSourceID); pCurrNote->ptrlEntryList.AddHead(pEntry); pCurrNoteHash->ptrlistSource.AddHead(pCurrNote); uLoad = 100; return true; } else { Source* pCurrNote = new Source; pCurrNote->uSourceID.SetValue(uSourceID); pCurrNote->ptrlEntryList.AddHead(pEntry); pCurrNoteHash->ptrlistSource.AddHead(pCurrNote); uLoad = (uint8)((uSize*100)/KADEMLIAMAXNOTESPERFILE); m_uTotalIndexKeyword++; return true; } } }
void CIndexed::SendValidNoteResult(const CUInt128& uKeyID, uint32 uIP, uint16 uPort, bool bKad2, uint64 uFileSize) { try { SrcHash* pCurrNoteHash; if(m_mapNotes.Lookup(CCKey(uKeyID.GetData()), pCurrNoteHash)) { byte byPacket[1024*50]; CByteIO byIO(byPacket,sizeof(byPacket)); byIO.WriteByte(OP_KADEMLIAHEADER); if(bKad2) { byIO.WriteByte(KADEMLIA2_SEARCH_RES); byIO.WriteUInt128(Kademlia::CKademlia::GetPrefs()->GetKadID()); } else byIO.WriteByte(KADEMLIA_SEARCH_NOTES_RES); byIO.WriteUInt128(uKeyID); byIO.WriteUInt16(50); uint16 uMaxResults = 150; uint16 uCount = 0; for(POSITION pos1 = pCurrNoteHash->ptrlistSource.GetHeadPosition(); pos1 != NULL; ) { Source* pCurrNote = pCurrNoteHash->ptrlistSource.GetNext(pos1); if( pCurrNote->ptrlEntryList.GetSize() ) { CEntry* pCurrName = pCurrNote->ptrlEntryList.GetHead(); if( uCount < uMaxResults ) { if( !uFileSize || !pCurrName->m_uSize || uFileSize == pCurrName->m_uSize ) { byIO.WriteUInt128(pCurrName->m_uSourceID); byIO.WriteTagList(pCurrName->m_listTag); uCount++; if( uCount % 50 == 0 ) { uint32 uLen = sizeof(byPacket)-byIO.GetAvailable(); CKademlia::GetUDPListener()->SendPacket(byPacket, uLen, uIP, uPort); byIO.Reset(); byIO.WriteByte(OP_KADEMLIAHEADER); if(bKad2) { if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA2_SEARCH_RES", uIP, uPort); byIO.WriteByte(KADEMLIA2_SEARCH_RES); byIO.WriteUInt128(Kademlia::CKademlia::GetPrefs()->GetKadID()); } else { if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA_SEARCH_NOTES_RES", uIP, uPort); byIO.WriteByte(KADEMLIA_SEARCH_NOTES_RES); } byIO.WriteUInt128(uKeyID); byIO.WriteUInt16(50); } } } else { break; } } } uint16 uCountLeft = uCount % 50; if( uCountLeft ) { uint32 uLen = sizeof(byPacket)-byIO.GetAvailable(); if(bKad2) { memcpy(byPacket+18+16, &uCountLeft, 2); if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA2_SEARCH_RES", uIP, uPort); } else { memcpy(byPacket+18, &uCountLeft, 2); if (thePrefs.GetDebugClientKadUDPLevel() > 0) DebugSend("KADEMLIA_SEARCH_NOTES_RES", uIP, uPort); } CKademlia::GetUDPListener()->SendPacket(byPacket, uLen, uIP, uPort); } } } catch(...) { AddDebugLogLine(false, _T("Exception in CIndexed::SendValidNoteResult")); } }
void CKadLookupGraph::OnPaint() { m_aNodesDrawRects.RemoveAll(); CPaintDC pdc(this); CRect rcClnt; GetClientRect(&rcClnt); if (rcClnt.IsRectEmpty()) return; CMemDC dc(&pdc, rcClnt); CPen* pOldPen = dc.SelectObject(&m_penAxis); if (g_xpStyle.IsThemeActive() && g_xpStyle.IsAppThemed()) { HTHEME hTheme = g_xpStyle.OpenThemeData(NULL, L"ListView"); if (hTheme) { g_xpStyle.DrawThemeBackground(hTheme, dc.m_hDC, 3, 0, &rcClnt, NULL); g_xpStyle.CloseThemeData(hTheme); } } else { dc.Rectangle(&rcClnt); } rcClnt.DeflateRect(1, 1, 1, 1); dc.FillSolidRect(rcClnt, GetSysColor(COLOR_WINDOW)); rcClnt.DeflateRect(1, 1, 1, 1); COLORREF crOldTextColor = dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); CFont* pOldFont = dc.SelectObject(AfxGetMainWnd()->GetFont()); if (!m_bInitializedFontMetrics) { TEXTMETRIC tm; dc.GetTextMetrics(&tm); // why is 'tm.tmMaxCharWidth' and 'tm.tmAveCharWidth' that wrong? CRect rcLabel; dc.DrawText(_T("888"), 3, &rcLabel, DT_CALCRECT); m_iMaxNumLabelWidth = rcLabel.Width(); if (m_iMaxNumLabelWidth <= 0) m_iMaxNumLabelWidth = 3*8; m_iMaxLabelHeight = tm.tmHeight; if (m_iMaxLabelHeight <= 0) m_iMaxLabelHeight = 8; m_bInitializedFontMetrics = true; } int iLeftBorder = 3; int iRightBorder = 8; int iTopBorder = m_iMaxLabelHeight; int iBottomBorder = m_iMaxLabelHeight; int iBaseLineX = iLeftBorder; int iBaseLineY = rcClnt.bottom - iBottomBorder; UINT uHistWidth = rcClnt.Width() - iLeftBorder - iRightBorder; UINT uHistHeight = rcClnt.Height() - iTopBorder - iBottomBorder; if (uHistHeight == 0) { dc.SelectObject(pOldFont); dc.SetTextColor(crOldTextColor); return; } dc.MoveTo(iBaseLineX, rcClnt.top + iTopBorder); dc.LineTo(iBaseLineX, iBaseLineY); dc.LineTo(iBaseLineX + uHistWidth, iBaseLineY); dc.SelectObject(&m_penAux); CRect rcLabel(rcClnt); rcLabel.left = iBaseLineX; rcLabel.bottom = m_iMaxLabelHeight; dc.DrawText(m_strYaxis, m_strYaxis.GetLength(), &rcLabel, DT_LEFT | DT_TOP | DT_NOCLIP); rcLabel = rcClnt; rcLabel.top = rcClnt.bottom - m_iMaxLabelHeight + 1; dc.DrawText(m_strXaxis, m_strXaxis.GetLength(), &rcLabel, DT_RIGHT | DT_BOTTOM | DT_NOCLIP); if (m_pLookupHistory != NULL && m_pLookupHistory->GetHistoryEntries().GetCount() >= 1) { // How many nodes can we show without scrolling? sint32 uMaxNodes = uHistWidth / NODE_ENTRY_WIDTH; uint32 uNodeEntryWidth = 0; if (m_pLookupHistory->GetHistoryEntries().GetCount() > uMaxNodes /*|| !m_pLookupHistory->IsSearchStopped()*/) uNodeEntryWidth = NODE_ENTRY_WIDTH; // While the search is running, use a fixed width else uNodeEntryWidth = uHistWidth / m_pLookupHistory->GetHistoryEntries().GetCount(); // when the search is finished, use all available screen space sint32 iVisibleNodes = min(uMaxNodes, m_pLookupHistory->GetHistoryEntries().GetCount()); // Set the scaling. 3 times the highest distance of the 1/3 closest nodes is the max distance CArray<CUInt128> aClosest; for (int i = 1; i <= iVisibleNodes; i++) { if (aClosest.GetCount() < ((iVisibleNodes / 3 == 0) ? 1 : (iVisibleNodes / 3))) aClosest.Add(m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance); else { int iReplace = -1; for (int j = 0; j < aClosest.GetCount(); j++) { if ((iReplace == (-1) && aClosest[j] > m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance) || (iReplace >= 0 && aClosest[j] > aClosest[iReplace])) { iReplace = j; } } if (iReplace >= 0) aClosest[iReplace] = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance; } } CUInt128 uTmpScalingDistance((ULONG)0); for (int j = 0; j < aClosest.GetCount(); j++) { if (aClosest[j] > uTmpScalingDistance) uTmpScalingDistance = aClosest[j]; } // Convert it to uint64 by cutting of the less significant bits for easier and fast calculating uint64 uScalingDistance = 0; uint8 byStartChunk; for (byStartChunk = 0; byStartChunk < 3; byStartChunk++) { if (uTmpScalingDistance.Get32BitChunk(byStartChunk) > 0) { uScalingDistance = ((uint64)uTmpScalingDistance.Get32BitChunk(byStartChunk) << 32) + (uint64)uTmpScalingDistance.Get32BitChunk(byStartChunk + 1); break; } } if (uScalingDistance == 0) { byStartChunk = 2; uScalingDistance = uTmpScalingDistance.Get32BitChunk(3); } uScalingDistance /= (uHistHeight - NODE_ENTRY_HEIGHT); uScalingDistance *= 3; ASSERT(uScalingDistance > 0); if (uScalingDistance == 0) uScalingDistance = 1; //if (m_bDbgLog) // AddDebugLogLine(false, _T("KadGraph: Considering %u of %u Nodes, 1/3 Max Distance found: %s"), iVisibleNodes, m_pLookupHistory->GetHistoryEntries().GetCount(), uTmpScalingDistance.ToHexString()); CUInt128 uMaxScalingDistance(uTmpScalingDistance); uMaxScalingDistance.Add(uTmpScalingDistance); uMaxScalingDistance.Add(uTmpScalingDistance); // wow, what a mess, now lets collect drawing points for (int i = 1; i <= iVisibleNodes; i++) { CUInt128 uTmpDist = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - i]->m_uDistance; uint64 uDrawYPos; if (uTmpDist > uMaxScalingDistance) uDrawYPos = iTopBorder; else { uDrawYPos = (((uint64)uTmpDist.Get32BitChunk(byStartChunk) << 32) + (uint64)uTmpDist.Get32BitChunk(byStartChunk + 1)); if (uDrawYPos > 0) uDrawYPos /= uScalingDistance; uDrawYPos = (iBaseLineY - NODE_ENTRY_HEIGHT) - uDrawYPos; } //if (m_bDbgLog) // AddDebugLogLine(false, _T("KadGraph: Drawing Node %u of %u, Distance: %s, Y-Pos: %u"), (iVisibleNodes - i) + 1, iVisibleNodes, uTmpDist.ToHexString(), uDrawYPos); ASSERT( uDrawYPos <= (uHistHeight) ); uint32 nXOffset = 0; //if (uMaxNodes > iVisibleNodes && !m_pLookupHistory->IsSearchStopped()) // Fixed width for ongoing searches // nXOffset = NODE_ENTRY_WIDTH * (uMaxNodes - iVisibleNodes); CPoint pointNode(uHistWidth - nXOffset - (i * uNodeEntryWidth), (uint32)uDrawYPos); m_aNodesDrawRects.Add(CRect(pointNode, CSize(NODE_ENTRY_WIDTH, NODE_ENTRY_HEIGHT))); } ASSERT( iVisibleNodes == m_aNodesDrawRects.GetCount() ); // find HotItem (if any) m_iHotItemIdx = (-1); CPoint ptCursor; if (GetCursorPos(&ptCursor)) { CRect rectWnd; GetWindowRect(&rectWnd); if (rectWnd.PtInRect(ptCursor)) { ScreenToClient(&ptCursor); m_iHotItemIdx = CheckHotItem(ptCursor); } } m_pToolTip->Activate(m_iHotItemIdx >= 0 ? TRUE : FALSE); UpdateToolTip(); CArray<bool> abHotItemConnected; if (m_iHotItemIdx >= 0) { abHotItemConnected.SetSize(iVisibleNodes); for (int i = 0; i < iVisibleNodes; i++) abHotItemConnected[i] = (m_iHotItemIdx == i); } // start drawing, beginning with the arrowClines connecting the nodes // if possible use GDI+ for Anti Aliasing extern bool g_bGdiPlusInstalled; ULONG_PTR gdiplusToken = 0; Gdiplus::GdiplusStartupInput gdiplusStartupInput; if (g_bGdiPlusInstalled && Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Gdiplus::Ok) { { Gdiplus::Graphics gdipGraphic(dc); gdipGraphic.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); Gdiplus::AdjustableArrowCap gdipArrow(6, 4); Gdiplus::Pen gdipPenGray(Gdiplus::Color(192, 192, 192), 0.8f); gdipPenGray.SetCustomEndCap(&gdipArrow); Gdiplus::Pen gdipPenDarkGray(Gdiplus::Color(100, 100, 100), 0.8f); gdipPenDarkGray.SetCustomEndCap(&gdipArrow); Gdiplus::Pen gdipPenRed(Gdiplus::Color(255, 32, 32), 0.8f); gdipPenRed.SetCustomEndCap(&gdipArrow); for (int i = 0; i < iVisibleNodes; i++) { const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)]; for (int j = 0; j < sEntry->m_liReceivedFromIdx.GetCount(); j++) { int iIdx = sEntry->m_liReceivedFromIdx[j]; if (iIdx >= m_pLookupHistory->GetHistoryEntries().GetCount() - iVisibleNodes) { CPoint pFrom = m_aNodesDrawRects[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)].CenterPoint(); CPoint pointTo = m_aNodesDrawRects[i].CenterPoint(); Gdiplus::Pen* pen; if (m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1) == m_iHotItemIdx) { abHotItemConnected[i] = true; pen = &gdipPenRed; } else if (i == m_iHotItemIdx) { abHotItemConnected[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)] = true; pen = &gdipPenDarkGray; } else pen = &gdipPenGray; gdipGraphic.DrawLine(pen, pFrom.x, pFrom.y, pointTo.x, pointTo.y); } } } } Gdiplus::GdiplusShutdown(gdiplusToken); } else { for (int i = 0; i < iVisibleNodes; i++) { const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)]; for (int j = 0; j < sEntry->m_liReceivedFromIdx.GetCount(); j++) { int iIdx = sEntry->m_liReceivedFromIdx[j]; if (iIdx >= m_pLookupHistory->GetHistoryEntries().GetCount() - iVisibleNodes) { CPoint pFrom = m_aNodesDrawRects[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)].CenterPoint(); CPoint pointTo = m_aNodesDrawRects[i].CenterPoint(); if (m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1) == m_iHotItemIdx) { abHotItemConnected[i] = true; dc.SelectObject(&m_penRed); } else { if (i == m_iHotItemIdx) abHotItemConnected[m_pLookupHistory->GetHistoryEntries().GetCount() - (iIdx + 1)] = true; dc.SelectObject(&m_penAux); } POINT aptPoly[3]; POINT pBase; float vecLine[2]; float vecLeft[2]; int nWidth = 4; // set to point aptPoly[0].x = pointTo.x; aptPoly[0].y = pointTo.y; // build the line vector vecLine[0] = (float) aptPoly[0].x - pFrom.x; vecLine[1] = (float) aptPoly[0].y - pFrom.y; // build the arrow base vector - normal to the line vecLeft[0] = -vecLine[1]; vecLeft[1] = vecLine[0]; // setup length parameters float fLength = (float) sqrt(vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1]); float th = nWidth / (2.0f * fLength); float ta = nWidth / (2.0f * (tanf(0.3f) / 2.0f) * fLength); // find the base of the arrow pBase.x = (int) (aptPoly[0].x + -ta * vecLine[0]); pBase.y = (int) (aptPoly[0].y + -ta * vecLine[1]); // build the points on the sides of the arrow aptPoly[1].x = (int) (pBase.x + th * vecLeft[0]); aptPoly[1].y = (int) (pBase.y + th * vecLeft[1]); aptPoly[2].x = (int) (pBase.x + -th * vecLeft[0]); aptPoly[2].y = (int) (pBase.y + -th * vecLeft[1]); dc.MoveTo(pFrom); dc.LineTo(aptPoly[0].x, aptPoly[0].y); dc.Polygon(aptPoly, 3); } } } } // draw the nodes images for (int i = 0; i < iVisibleNodes; i++) { CPoint pointNode = m_aNodesDrawRects[i].CenterPoint(); pointNode.x -= 8; pointNode.y -= 8; uint8 byIconIdx = 0; const CLookupHistory::SLookupHistoryEntry* sEntry = m_pLookupHistory->GetHistoryEntries()[m_pLookupHistory->GetHistoryEntries().GetCount() - (i + 1)]; if (sEntry->m_dwAskedContactsTime > 0) { if (sEntry->m_uRespondedContact > 0) byIconIdx = sEntry->m_bProvidedCloser ? 0 : 1; // green or blue else if (sEntry->m_dwAskedContactsTime + SEC2MS(3) < ::GetTickCount()) byIconIdx = 3; // red else byIconIdx = 2; // yellow } else if (sEntry->m_bForcedInteresting) byIconIdx = 2; else ASSERT( false ); if (m_iHotItemIdx >= 0 && !abHotItemConnected[i]) m_iml.DrawEx(&dc, byIconIdx, pointNode, CSize(0, 0), CLR_NONE, GetSysColor(COLOR_WINDOW), ILD_BLEND50); else m_iml.Draw(&dc, byIconIdx, pointNode, ILD_NORMAL); if (sEntry->m_dwAskedSearchItemTime > 0) { // Draw the Icon indicating that we asked this Node for results // enough space above? if not below CPoint pointIndicator = pointNode; if (pointIndicator.y - 16 - 4 >= iTopBorder) pointIndicator.y -= 20; else pointIndicator.y += 20; switch (m_pLookupHistory->GetType()) { case Kademlia::CSearch::FILE: case Kademlia::CSearch::KEYWORD: case Kademlia::CSearch::NOTES: { int nOverlayImage = 0; if (sEntry->m_uRespondedSearchItem > 0) nOverlayImage = 1; else if (sEntry->m_dwAskedSearchItemTime + SEC2MS(5) < ::GetTickCount()) nOverlayImage = 2; m_iml.Draw(&dc, 4, pointIndicator, ILD_NORMAL | INDEXTOOVERLAYMASK(nOverlayImage)); break; } case Kademlia::CSearch::STOREFILE: m_iml.Draw(&dc, 6, pointIndicator, ILD_NORMAL); break; case Kademlia::CSearch::STOREKEYWORD: case Kademlia::CSearch::STORENOTES: m_iml.Draw(&dc, 5, pointIndicator, ILD_NORMAL); break; /* Nothing to show case CSearch::NODE: case CSearch::NODECOMPLETE: case CSearch::NODESPECIAL: case CSearch::NODEFWCHECKUDP: case CSearch::FINDBUDDY: default:*/ } } } } m_bDbgLog = false; dc.SelectObject(pOldPen); dc.SelectObject(pOldFont); dc.SetTextColor(crOldTextColor); }
// Needed for ASSERT_EQUALS with CUInt128 template<> wxString StringFrom<CUInt128>(const CUInt128& value) { return value.ToHexString(); }
CKademlia::CKademlia(uint16 Port, bool bIPv6, const CVariant& Config, const string& Version) { m_Protocol = KAD_PROT_VER; if(!Version.empty()) m_Version += Version; else m_Version = "v " STR(KAD_PROT_MJR) "." STR(KAD_PROT_MIN); m_pConfig = new CKadConfig(this); if(Config.IsValid()) m_pConfig->Merge(Config); LoadData(); if(m_pKadKey->GetAlgorithm() == CAbstractKey::eUndefined) { m_pKadKey->SetAlgorithm(CAbstractKey::eECP); //m_pKadKey->GenerateKey("secp256r1"); // NIST: P-256 m_pKadKey->GenerateKey("brainpoolP256r1"); // dont trust NIST (NSA) curves, use brainpool LogLine(LOG_INFO, L"Generated new Private NodeKey"); SaveData(); } m_pSocket = new CSmartSocket(SEC2MS(Cfg()->GetInt("ConnectionTimeout")), this); CScoped<CPublicKey> pKey = m_pKadKey->PublicKey(); CUInt128 ID; CKadID::MakeID(pKey, ID.GetData(), ID.GetSize()); LogLine(LOG_INFO, L"Neo Kad ID: %s", ID.ToHex().c_str()); uint64 RecvKey; CAbstractKey::Fold(ID.GetData(), ID.GetSize(),(byte*)&RecvKey, sizeof(RecvKey)); m_pSocket->SetupCrypto(RecvKey, m_pKadKey); #ifdef _DEBUG LogLine(LOG_INFO, L"Socket PassKey is %I64u", RecvKey); #endif m_Port = 0; m_IPv4 = CAddress(CAddress::IPv4); m_IPv6 = CAddress(CAddress::IPv6); for(int i=Port; i < Port + 1000; i++) { CUTPSocketListner* pSocketListner = new CUTPSocketListner(m_pSocket); CUTPSocketListner* pSocketListnerV6 = bIPv6 ? new CUTPSocketListner(m_pSocket) : NULL; bool bV4 = pSocketListner->Bind(i, CAddress(CAddress::IPv4)); bool bV6 = !pSocketListnerV6 || pSocketListnerV6->Bind(i, CAddress(CAddress::IPv6)); if(bV4 && bV6) { m_pSocket->InstallListener(pSocketListner); if(pSocketListnerV6) m_pSocket->InstallListener(pSocketListnerV6); m_Port = i; break; } delete pSocketListner; delete pSocketListnerV6; } }
void CDataIO::WriteUInt128(const CUInt128& uVal) { WriteArray(uVal.GetData(), sizeof(uint32)*4); }
void CDataIO::writeUInt128(const CUInt128& val) { writeArray(val.getData(), sizeof(uint32)*4); }
void CRoutingZone::OnSmallTimer() { if (!IsLeaf()) return; CContact *pContact = NULL; time_t tNow = time(NULL); ContactList listEntries; // Remove dead entries m_pBin->GetEntries(&listEntries); for (ContactList::iterator itContactList = listEntries.begin(); itContactList != listEntries.end(); ++itContactList) { pContact = *itContactList; if ( pContact->GetType() == 4) { if (((pContact->m_tExpires > 0) && (pContact->m_tExpires <= tNow))) { if(!pContact->InUse()) { //----------------------------------------------------------------- CString strID; CUInt128 uId = pContact->GetClientID(); uId.ToHexString(&strID); CString strIP; pContact->GetIPAddress(&strIP); TRACE(_T("DelContact id=%s ip=%s %u %u %u\n"), strID, strIP, pContact->GetTCPPort(), pContact->GetUDPPort(), CKademlia::GetRoutingZone()->GetNumContacts()); //----------------------------------------------------------------- m_pBin->RemoveContact(pContact); delete pContact; } continue; } } if(pContact->m_tExpires == 0) pContact->m_tExpires = tNow; } pContact = m_pBin->GetOldest(); if( pContact != NULL ) { if ( pContact->m_tExpires >= tNow || pContact->GetType() == 4) { m_pBin->RemoveContact(pContact); m_pBin->m_listEntries.push_back(pContact); pContact = NULL; } } if(pContact != NULL) { pContact->CheckingType(); if (pContact->GetVersion() >= 2/*47a*/) { //--->xt if (thePrefs.GetDebugClientKadUDPLevel() > 0) //DebugSend("KADEMLIA2_HELLO_REQ", pContact->GetIPAddress(), pContact->GetUDPPort()); CKademlia::GetUDPListener()->SendMyDetails(KADEMLIA2_HELLO_REQ, pContact->GetIPAddress(), pContact->GetUDPPort(), true); } else { //--->xt if (thePrefs.GetDebugClientKadUDPLevel() > 0) //DebugSend("KADEMLIA_HELLO_REQ", pContact->GetIPAddress(), pContact->GetUDPPort()); CKademlia::GetUDPListener()->SendMyDetails(KADEMLIA_HELLO_REQ, pContact->GetIPAddress(), pContact->GetUDPPort(), false); if (pContact->CheckIfKad2()) { //--->xt if (thePrefs.GetDebugClientKadUDPLevel() > 0) //DebugSend("KADEMLIA2_HELLO_REQ", pContact->GetIPAddress(), pContact->GetUDPPort()); CKademlia::GetUDPListener()->SendMyDetails(KADEMLIA2_HELLO_REQ, pContact->GetIPAddress(), pContact->GetUDPPort(), true); } } } }