extract multiple nodeInfo from 'nodes' param in responses

This commit is contained in:
orignal
2026-10-06 10:06:24 -04:00
parent 48d7540837
commit efe6c56297
2 changed files with 55 additions and 28 deletions
+51 -25
View File
@@ -536,7 +536,11 @@ namespace torrents
{
auto bytesRead = f.gcount();
if (bytesRead == nodeInfo.size ())
sortedNodes.emplace (std::make_shared<Node>(nodeInfo));
{
auto node = std::make_shared<Node>(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<std::string_view> 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<Node> (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<Node> (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<std::string_view>& values, const NodeInfo& nodeInfo)
uint64_t token, const std::vector<std::string_view>& 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<Node>(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<GetPeersRequestInfo> info,
const NodeID& nodeID, uint64_t token, const NodeInfo& nodeInfo)
void TorrentsDHT::HandleGetPeersResponseNodes (std::shared_ptr<GetPeersRequestInfo> info,
const NodeID& nodeID, uint64_t token, std::string_view nodes)
{
auto node = UpdateNode (std::make_shared<Node>(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<Node>(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<Node>(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<Node> TorrentsDHT::UpdateNode (std::shared_ptr<Node> 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");
+4 -3
View File
@@ -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<std::string_view>& values, const NodeInfo& nodeInfo);
void HandleGetPeersResponseNode (std::shared_ptr<GetPeersRequestInfo> info,
const NodeID& nodeID, uint64_t token, const NodeInfo& nodeInfo);
const std::vector<std::string_view>& values, std::string_view nodes);
void HandleGetPeersResponseNodes (std::shared_ptr<GetPeersRequestInfo> info,
const NodeID& nodeID, uint64_t token, std::string_view nodes);
void HandleGetPeersResponsePeersAndAnnounce (std::shared_ptr<GetPeersRequestInfo> info,
const std::vector<std::string_view>& 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);