From efe6c56297745ef8a555586e52b97c8c6f7e2bb0 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 6 Oct 2026 10:06:24 -0400 Subject: [PATCH] extract multiple nodeInfo from 'nodes' param in responses --- libi2pd_client/TorrentsDHT.cpp | 76 +++++++++++++++++++++++----------- libi2pd_client/TorrentsDHT.h | 7 ++-- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index d948cbc4..07f2dd0a 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -536,7 +536,11 @@ namespace torrents { auto bytesRead = f.gcount(); if (bytesRead == nodeInfo.size ()) - sortedNodes.emplace (std::make_shared(nodeInfo)); + { + auto node = std::make_shared(nodeInfo); + if (node->VerifyID ()) + sortedNodes.emplace (node); + } } if (!sortedNodes.empty ()) { @@ -555,11 +559,12 @@ namespace torrents // response or error char type = 0; uint64_t token = 0; bool isMalformed = false; - NodeID id; NodeInfo nodeInfo; Torrent::InfoHash infoHash; + NodeID id; Torrent::InfoHash infoHash; + std::string_view nodes; std::string transactionID, query; std::vector values{""}; ParseDictionary (std::string_view ((const char *)buf, len), - [&type, &transactionID, &id, &values, &token, &infoHash, &query, &isMalformed, &nodeInfo] + [&type, &transactionID, &id, &values, &token, &infoHash, &query, &isMalformed, &nodes] (std::string_view key, std::string_view buf)->size_t { if (key == "y") @@ -583,7 +588,7 @@ namespace torrents else if (key == "r" || key == "a") { return ParseDictionary (buf, - [&id, &values, &token, &infoHash, &isMalformed, &nodeInfo](std::string_view key, std::string_view buf)->size_t + [&id, &values, &token, &infoHash, &isMalformed, &nodes](std::string_view key, std::string_view buf)->size_t { if (key == "id") { @@ -599,8 +604,8 @@ namespace torrents } else if (key == "nodes") { - auto [l, success] = ParseByteArray (buf, nodeInfo); - if (!success) isMalformed = true; + auto [value, l] = ExtractByteString (buf); + if (l) nodes = value; return l; } else if (key == "token") @@ -631,7 +636,7 @@ namespace torrents switch (type) { case 'r': - HandleResponse (transactionID, id, token, values, nodeInfo); + HandleResponse (transactionID, id, token, values, nodes); break; case 'e': LogPrint (eLogDebug, "TorrentsDHT: Error msg received"); @@ -713,13 +718,8 @@ namespace torrents } if (type == 'q') { - auto node = std::make_shared (id, from.GetIdentHash (), fromPort); - if (!node->VerifyID ()) - { - LogPrint (eLogInfo, "TorrentsDHT: Query received from node with invalid ID ", node->id.ToBase64 ()); - return; - } - node = UpdateNode (node); + auto node = UpdateNode (std::make_shared (id, from.GetIdentHash (), fromPort)); + if (!node) return; if (query == "ping") HandlePingQuery (from.GetIdentHash (), fromPort, transactionID, id); else if (query == "get_peers") @@ -809,7 +809,7 @@ namespace torrents } void TorrentsDHT::HandleResponse (std::string_view transactionID, const NodeID& nodeID, - uint64_t token, const std::vector& values, const NodeInfo& nodeInfo) + uint64_t token, const std::vector& values, std::string_view nodes) { uint16_t t = 0; if (transactionID.size () >= 2) @@ -832,15 +832,15 @@ namespace torrents { LogPrint (eLogDebug, "TorrentsDHT: get_peers response received from peer ", ident.ToBase64 (), "after attempt #", info->numAttempts); if (!values.empty () && values[0].empty ()) // nodes - HandleGetPeersResponseNode (info, nodeID, token, nodeInfo); + HandleGetPeersResponseNodes (info, nodeID, token, nodes); else //values HandleGetPeersResponsePeersAndAnnounce (info, values, token, ident, port + 1); // to rport break; } case eKRPCQueryFindNode: { - auto node = UpdateNode (std::make_shared(nodeInfo)); - LogPrint (eLogDebug, "TorrentsDHT: find_node response received ", node->id.ToBase64 ()); + LogPrint (eLogDebug, "TorrentsDHT: find_node response received"); + HandleFindNodeResponse (nodes); break; } case eKRPCQueryAnnouncePeer: @@ -856,15 +856,25 @@ namespace torrents LogPrint (eLogInfo, "TorrentsDHT: Query not found"); } - void TorrentsDHT::HandleGetPeersResponseNode (std::shared_ptr info, - const NodeID& nodeID, uint64_t token, const NodeInfo& nodeInfo) + void TorrentsDHT::HandleGetPeersResponseNodes (std::shared_ptr info, + const NodeID& nodeID, uint64_t token, std::string_view nodes) { - auto node = UpdateNode (std::make_shared(nodeInfo)); - if (info) + NodeInfo nodeInfo; + if (nodes.size () >= nodeInfo.size ()) // at least one node { - info->AddNode (node); - info->token = token; - SendNextGetPeersQuery (info); + while (nodes.size () >= nodeInfo.size ()) + { + memcpy (nodeInfo.data (), nodes.data (), nodeInfo.size ()); + auto node = UpdateNode (std::make_shared(nodeInfo)); + if (info && node) + info->AddNode (node); + nodes = nodes.substr (nodeInfo.size ()); + } + if (info) + { + info->token = token; + SendNextGetPeersQuery (info); + } } } @@ -887,6 +897,17 @@ namespace torrents SendAnnouncePeerQuery (info->torrent->GetInfoHash (), token, toIdent, toPort); } + void TorrentsDHT::HandleFindNodeResponse (std::string_view nodes) + { + NodeInfo nodeInfo; + while (nodes.size () >= nodeInfo.size ()) + { + memcpy (nodeInfo.data (), nodes.data (), nodeInfo.size ()); + UpdateNode (std::make_shared(nodeInfo)); + nodes = nodes.substr (nodeInfo.size ()); + } + } + void TorrentsDHT::SendDatagram (std::string_view msg, const i2p::data::IdentHash& toIdent, uint16_t toPort) { auto dest = m_Tunnel.GetLocalDestination (); @@ -1048,6 +1069,11 @@ namespace torrents std::shared_ptr TorrentsDHT::UpdateNode (std::shared_ptr node) { if (!node) return nullptr; + if (!node->VerifyID ()) + { + LogPrint (eLogInfo, "TorrentsDHT: Invalid node ID received ", node->id.ToBase64 ()); + return nullptr; + } auto [it, inserted] = m_Nodes.emplace (node->id, node); if (inserted) LogPrint (eLogDebug, "TorrentsDHT: Node ", node->id.ToBase64 (), " added"); diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index 9a382cad..97c5f652 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -225,11 +225,12 @@ namespace torrents void HandleFindNodeQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort, std::string_view transactionID, const NodeID& target); void HandleResponse (std::string_view transactionID, const NodeID& nodeID, uint64_t token, - const std::vector& values, const NodeInfo& nodeInfo); - void HandleGetPeersResponseNode (std::shared_ptr info, - const NodeID& nodeID, uint64_t token, const NodeInfo& nodeInfo); + const std::vector& values, std::string_view nodes); + void HandleGetPeersResponseNodes (std::shared_ptr info, + const NodeID& nodeID, uint64_t token, std::string_view nodes); void HandleGetPeersResponsePeersAndAnnounce (std::shared_ptr info, const std::vector& peers, uint64_t token, const i2p::data::IdentHash& toIdent, uint16_t toPort); + void HandleFindNodeResponse (std::string_view nodes); void HandleAnnouncePeer (std::string_view transactionID, const Torrent::InfoHash& infoHash, uint64_t token); void SendDatagram (std::string_view msg, const i2p::data::IdentHash& toIdent, uint16_t toPort);