void DecodePartMetFile(const CFileDataIO& file) { uint16_t PartCount = 0; uint8_t version = file.ReadUInt8(); cout << "Version : " << VersionInfo(version, PartMetFile) << endl; if (version != PARTFILE_VERSION && version != PARTFILE_SPLITTEDVERSION && version != PARTFILE_VERSION_LARGEFILE) { cerr << "File seems to be corrupt, invalid version!" << endl; return; } bool isnewstyle = (version == PARTFILE_SPLITTEDVERSION); if (!isnewstyle) { uint8_t test[4]; file.Seek(24, wxFromStart); file.Read(test, 4); file.Seek(1, wxFromStart); if (test[0] == 0 && test[1] == 0 && test[2] == 2 && test[3] == 1) { isnewstyle = true; } } if (isnewstyle) { uint32_t temp = file.ReadUInt32(); if (temp == 0) { PrintHashsetFromFile(file); } else { file.Seek(2, wxFromStart); PrintDateFromFile(file); cout << "FileHash : " << file.ReadHash() << '\n'; } } else { PrintDateFromFile(file); PrintHashsetFromFile(file); } uint32_t tagCount = file.ReadUInt32(); cout << "TagCount : " << tagCount << '\n'; for (; tagCount > 0; tagCount--) { CTag tag(file, true); if (tag.GetNameID() == FT_FILESIZE) { PartCount = (tag.GetInt() + (PARTSIZE - 1)) / PARTSIZE; } cout << '\t' << tag << '\n'; } if (isnewstyle && (file.GetPosition() < file.GetLength())) { file.Seek(1, wxFromCurrent); cout << "HashSet : "; for (uint16_t i = 0; i < PartCount && (file.GetPosition() + 16 < file.GetLength()); i++) { if (i) { cout << ", "; } cout << file.ReadHash(); } } cout << '\n'; }
CTag::CTag(const CFileDataIO& data, bool bOptUTF8) { // Zero variables to allow for safe deletion m_uType = m_uName = m_nSize = m_uVal = 0; m_pData = NULL; try { m_uType = data.ReadUInt8(); if (m_uType & 0x80) { m_uType &= 0x7F; m_uName = data.ReadUInt8(); } else { uint16 length = data.ReadUInt16(); if (length == 1) { m_uName = data.ReadUInt8(); } else { m_uName = 0; m_Name = data.ReadOnlyString(utf8strNone,length); } } // NOTE: It's very important that we read the *entire* packet data, // even if we do not use each tag. Otherwise we will get in trouble // when the packets are returned in a list - like the search results // from a server. If we cannot do this, then we throw an exception. switch (m_uType) { case TAGTYPE_STRING: m_pstrVal = new wxString(data.ReadString(bOptUTF8)); break; case TAGTYPE_UINT32: m_uVal = data.ReadUInt32(); break; case TAGTYPE_UINT64: m_uVal = data.ReadUInt64(); break; case TAGTYPE_UINT16: m_uVal = data.ReadUInt16(); m_uType = TAGTYPE_UINT32; break; case TAGTYPE_UINT8: m_uVal = data.ReadUInt8(); m_uType = TAGTYPE_UINT32; break; case TAGTYPE_FLOAT32: //#warning Endianess problem? data.Read(&m_fVal, 4); break; case TAGTYPE_HASH16: m_hashVal = new CMD4Hash(data.ReadHash()); break; case TAGTYPE_BOOL: printf("***NOTE: %s; Reading BOOL tag\n", __FUNCTION__); data.ReadUInt8(); break; case TAGTYPE_BOOLARRAY: { printf("***NOTE: %s; Reading BOOL Array tag\n", __FUNCTION__); uint16 len = data.ReadUInt16(); // 07-Apr-2004: eMule versions prior to 0.42e.29 used the formula "(len+7)/8"! //#warning This seems to be off by one! 8 / 8 + 1 == 2, etc. data.Seek((len / 8) + 1, wxFromCurrent); break; } case TAGTYPE_BLOB: // 07-Apr-2004: eMule versions prior to 0.42e.29 handled the "len" as int16! m_nSize = data.ReadUInt32(); // Since the length is 32b, this check is needed to avoid // huge allocations in case of bad tags. if (m_nSize > data.GetLength() - data.GetPosition()) { throw CInvalidPacket(wxT("Malformed tag")); } m_pData = new unsigned char[m_nSize]; data.Read(m_pData, m_nSize); break; default: if (m_uType >= TAGTYPE_STR1 && m_uType <= TAGTYPE_STR16) { uint8 length = m_uType - TAGTYPE_STR1 + 1; m_pstrVal = new wxString(data.ReadOnlyString(bOptUTF8, length)); m_uType = TAGTYPE_STRING; } else { // Since we cannot determine the length of this tag, we // simply have to abort reading the file. throw CInvalidPacket(CFormat(wxT("Unknown tag type encounted %x, cannot proceed!")) % m_uType); } } } catch (...) { if (m_uType == TAGTYPE_BLOB) { delete[] m_pData; } throw; } }
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); } }