diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/ECIESX25519AEADRatchetSession.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/ECIESX25519AEADRatchetSession.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd/ECIESX25519AEADRatchetSession.cpp 2026-10-07 00:42:43.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd/ECIESX25519AEADRatchetSession.cpp 2026-10-07 00:29:17.000000000 +0000 @@ -396,7 +396,5 @@ if (len < 3) return; size_t offset = 0; - // the block header is three bytes: without all of them the size field below - // would be read past the end of the payload - while (offset + 3 <= len) + while (offset < len) { uint8_t blk = buf[offset]; diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd_client/TorrentsDHT.cpp /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd_client/TorrentsDHT.cpp --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd_client/TorrentsDHT.cpp 2026-10-07 00:42:43.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd_client/TorrentsDHT.cpp 2026-10-07 00:29:17.000000000 +0000 @@ -144,17 +144,4 @@ } - std::list > RoutingTable::GetNodes () - { - std::list > nodes; - auto bucket = m_Buckets; - while (bucket) - { - for (auto it: bucket->nodes) - nodes.emplace_back (it.second); - bucket = bucket->next; - } - return nodes; - } - Bucket * RoutingTable::FindBucket (const Torrent::InfoHash& id) const { @@ -226,7 +213,7 @@ } - std::list > RoutingTable::GetNodesToPing (uint64_t ts) + std::list RoutingTable::GetNodesToPing (uint64_t ts) { - std::list > toPing; + std::list toPing; auto bucket = m_Buckets; while (bucket) @@ -236,5 +223,5 @@ for (const auto& it: bucket->nodes) if (ts > it.second->lastUpdateTime + DHT_NODE_SEND_PING_TIME) - toPing.push_back (it.second); + toPing.push_back (it.first); } bucket = bucket->next; @@ -254,5 +241,5 @@ it->second = node; bucket->lastUpdateTime = i2p::util::GetMonotonicSeconds (); - return false; + return true; } if (bucket->IsFull ()) @@ -486,5 +473,5 @@ void TorrentsDHT::Save (const std::filesystem::path& file) { - if (m_RoutingTable) + if (!m_Nodes.empty ()) { std::ofstream f(file, std::ofstream::binary); @@ -499,7 +486,7 @@ } int numSaved = 0; - for (auto it: m_RoutingTable->GetNodes ()) + for (auto it: m_Nodes) { - auto nodeInfo = it->GetNodeInfo (); + auto nodeInfo = it.second->GetNodeInfo (); if (f.write ((const char *)nodeInfo.data (), nodeInfo.size ())) numSaved++; @@ -554,6 +541,7 @@ { for (auto it: sortedNodes) - m_RoutingTable->AddNode (it); - LogPrint (eLogInfo, "TorrentsDHT: DHT nodes loaded ", + if (m_Nodes.emplace (it->id, it).second) + m_RoutingTable->AddNode (it); + LogPrint (eLogInfo, "TorrentsDHT: ", m_Nodes.size (), " total DHT nodes loaded ", m_RoutingTable->GetNumNodes (), " to ", m_RoutingTable->GetNumBuckets (), " buckets"); } @@ -1079,7 +1067,10 @@ return nullptr; } - if (m_RoutingTable && m_RoutingTable->AddNode (node)) + auto [it, inserted] = m_Nodes.emplace (node->id, node); + if (inserted) LogPrint (eLogDebug, "TorrentsDHT: Node ", node->id.ToBase64 (), " added"); - return node; + it->second->lastUpdateTime = i2p::util::GetMonotonicSeconds (); + if (m_RoutingTable) m_RoutingTable->AddNode (it->second); + return it->second; } @@ -1118,8 +1109,19 @@ { auto ts = i2p::util::GetMonotonicSeconds (); + { + auto it = m_Nodes.begin (); + while (it != m_Nodes.end ()) + { + if (ts > it->second->lastUpdateTime + DHT_NODE_EXPIRATION_TIME) + it = m_Nodes.erase (it); + else + it++; + } + } if (m_RoutingTable) { m_RoutingTable->DeleteExpiredNodes (ts); - LogPrint (eLogDebug, "TorrentsDHT: Stats buckets ", m_RoutingTable->GetNumBuckets (), " nodes ", m_RoutingTable->GetNumNodes ()); + LogPrint (eLogDebug, "TorrentsDHT: Stats total nodes ", m_Nodes.size (), + " buckets ", m_RoutingTable->GetNumBuckets (), " nodes ", m_RoutingTable->GetNumNodes ()); } { @@ -1153,5 +1155,9 @@ auto toPing = m_RoutingTable->GetNodesToPing (ts); for (const auto& it: toPing) - SendPingQuery (it->peer, it->port); + { + auto it1 = m_Nodes.find (it); + if (it1 != m_Nodes.end ()) + SendPingQuery (it1->second->peer, it1->second->port); + } } ScheduleDHTSendPingCheck (); diff -U2 -r /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd_client/TorrentsDHT.h /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd_client/TorrentsDHT.h --- /var/lib/copr-rpmbuild/results/i2pd-git/upstream-unpacked/Source0/i2pd-openssl/libi2pd_client/TorrentsDHT.h 2026-10-07 00:42:43.000000000 +0000 +++ /var/lib/copr-rpmbuild/results/i2pd-git/srpm-unpacked/i2pd-openssl.tar.gz-extract/i2pd-openssl/libi2pd_client/TorrentsDHT.h 2026-10-07 00:29:17.000000000 +0000 @@ -131,5 +131,4 @@ size_t GetNumBuckets () const; size_t GetNumNodes () const; - std::list > GetNodes (); Bucket * FindBucket (const Torrent::InfoHash& id) const; @@ -142,5 +141,5 @@ std::list > > GetExploratoryTargets (std::mt19937& rng) const; // (target, node to send find_node to) size_t DeleteExpiredNodes (uint64_t ts); - std::list > GetNodesToPing (uint64_t ts); + std::list GetNodesToPing (uint64_t ts); void RemoveEmptyBuckets (); @@ -278,4 +277,5 @@ NodeID m_NodeID; std::unique_ptr m_RoutingTable; + std::map > m_Nodes; // transactionID -> (ident, port, query, get peers request info, time in monotonic seconds) std::unordered_map, uint64_t > > m_Queries;