From 90a436bd5ff436e012330bb915ad5358dd58639d Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 9 Oct 2026 15:53:24 -0400 Subject: [PATCH] maintain heardFrom list --- libi2pd_client/TorrentsDHT.cpp | 39 +++++++++++++++++++++++++++++----- libi2pd_client/TorrentsDHT.h | 4 ++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index b61c03f4..01ee02d3 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -595,6 +595,7 @@ namespace torrents } if (type) { + UpdateHeardFrom (id); switch (type) { case 'r': @@ -680,6 +681,7 @@ namespace torrents } if (type == 'q') { + UpdateHeardFrom (id); auto node = UpdateNode (std::make_shared (id, from.GetIdentHash (), fromPort)); if (!node) return; if (query == "ping") @@ -765,7 +767,7 @@ namespace torrents void TorrentsDHT::HandleAnnouncePeer (std::string_view transactionID, const NodeID& nodeID, const Torrent::InfoHash& infoHash, uint64_t token) { - LogPrint (eLogDebug, "TorrentsDHT: Announce peer received"); + LogPrint (eLogDebug, "TorrentsDHT: Announce peer received from ", nodeID.ToBase64 ()); auto it = m_Torrents.find (infoHash); if (it != m_Torrents.end ()) { @@ -786,6 +788,8 @@ namespace torrents else LogPrint (eLogInfo, "TorrentsDHT: Announce peer token not found"); } + else + LogPrint (eLogInfo, "TorrentsDHT: Torrent for announce not found"); } void TorrentsDHT::HandleResponse (std::string_view transactionID, const NodeID& nodeID, @@ -849,7 +853,12 @@ namespace torrents memcpy (nodeInfo.data (), nodes.data (), nodeInfo.size ()); auto node = std::make_shared(nodeInfo); if (info && info->AddNode (node)) - SendPingQuery (node->peer, node->port); + { + if (m_HeardFrom.contains (node->id)) + UpdateNode (node); + else + SendPingQuery (node->peer, node->port); + } nodes = nodes.substr (nodeInfo.size ()); } if (info) @@ -883,7 +892,12 @@ namespace torrents memcpy (nodeInfo.data (), nodes.data (), nodeInfo.size ()); auto node = std::make_shared(nodeInfo); if (info && info->AddNode (node)) - SendPingQuery (node->peer, node->port); + { + if (m_HeardFrom.contains (node->id)) + UpdateNode (node); + else + SendPingQuery (node->peer, node->port); + } nodes = nodes.substr (nodeInfo.size ()); } if (info) @@ -1104,6 +1118,11 @@ namespace torrents return node; } + void TorrentsDHT::UpdateHeardFrom (const NodeID& nodeID) + { + m_HeardFrom[nodeID] = i2p::util::GetMonotonicSeconds (); + } + void TorrentsDHT::ScheduleDHTUpdateCheck () { m_DHTUpdateCheckTimer.cancel (); @@ -1153,6 +1172,16 @@ namespace torrents it++; } } + { + auto it = m_HeardFrom.begin (); + while (it != m_HeardFrom.end ()) + { + if (ts > it->second + DHT_HEARD_FROM_EXPIRATION_TIME) + it = m_HeardFrom.erase (it); + else + it++; + } + } ScheduleDHTExpirationCheck (); } } @@ -1215,7 +1244,7 @@ namespace torrents for (auto it1: getpeers) { LogPrint (eLogDebug, "TorrentsDHT: get_peers response timeout after attempt #", it1->numAttempts); - if (m_RoutingTable && it1->lastNode) + if (m_RoutingTable && it1->lastNode && !m_HeardFrom.contains (it1->lastNode->id)) { auto bucket = m_RoutingTable->FindBucket (it1->lastNode->id); if (bucket && bucket->nodes.size () > MAX_BUCKET_CAPACITY/2) @@ -1226,7 +1255,7 @@ namespace torrents for (auto it1: findnode) { LogPrint (eLogDebug, "TorrentsDHT: find_node response timeout after attempt #", it1->numAttempts); - if (m_RoutingTable && it1->lastNode) + if (m_RoutingTable && it1->lastNode && !m_HeardFrom.contains (it1->lastNode->id)) { auto bucket = m_RoutingTable->FindBucket (it1->lastNode->id); if (bucket && bucket->nodes.size () > MAX_BUCKET_CAPACITY/2) diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index 47840f48..7d6f9656 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -51,11 +51,13 @@ namespace torrents constexpr int DHT_TORRENT_PEER_EXPIRATION_TIME = 3*3600; // in seconds constexpr int DHT_INCOMING_GET_PEERS_TOKEN_EXPIRATION_TIME = 600; // in seconds constexpr int DHT_EMPTY_TORRENT_EXPIRATION_TIME = 30; // in seconds + constexpr int DHT_HEARD_FROM_EXPIRATION_TIME = 290; // in seconds constexpr int DHT_QUERY_EXPIRATION_TIME = 25; // in seconds constexpr int DHT_MAX_NUM_GET_PEERS_ATTEMPTS = 22; constexpr int DHT_MAX_NUM_FIND_NODE_ATTEMPTS = 8; constexpr int DHT_MAX_NUM_CLOSEST_NODES_TO_ANNOUNCE = 4; + using Distance = Torrent::InfoHash; struct NodeID: public Torrent::InfoHash { @@ -279,6 +281,7 @@ namespace torrents void Load (const std::filesystem::path& file); void Explore (); std::shared_ptr UpdateNode (std::shared_ptr node); // return true if added + void UpdateHeardFrom (const NodeID& nodeID); void ScheduleDHTUpdateCheck (); void HandleDHTUpdateCheckTimer (const boost::system::error_code& ecode); @@ -300,6 +303,7 @@ namespace torrents uint16_t m_Port; NodeID m_NodeID; std::unique_ptr m_RoutingTable; + std::map m_HeardFrom; // nodeid -> time in monotonic seconds // transactionID -> (ident, port, query, request info, time in monotonic seconds) std::unordered_map, uint64_t > > m_Queries; std::map > m_Torrents;