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); } }