handle get_peers query

This commit is contained in:
orignal
2026-09-22 20:49:14 -04:00
parent 2b67562c45
commit ef4ac934e8
4 changed files with 89 additions and 15 deletions
+22
View File
@@ -175,6 +175,16 @@ namespace torrents
return s.str ();
}
std::string CreateList (const std::vector<std::string>& items)
{
std::stringstream s;
s << 'l';
for (const auto& it: items)
s << it;
s << 'e';
return s.str ();
}
//------------------------------------
bool TorrentFile::Save (size_t offset, const uint8_t * buf, size_t len)
@@ -1066,6 +1076,18 @@ namespace torrents
return ret;
}
std::unordered_set<i2p::data::IdentHash> Torrent::GetAllPeers () const
{
std::unordered_set<i2p::data::IdentHash> ret;
for (const auto& it: m_TrackerStats)
{
const auto& peers = std::get<0>(it);
for (const auto& it1: peers)
ret.emplace (it1);
}
return ret;
}
uint64_t Torrent::GetNextTrackerRequestTime (size_t trackerID) const
{
if (trackerID < m_TrackerStats.size ()) return std::get<2>(m_TrackerStats[trackerID]);
+4 -2
View File
@@ -44,6 +44,7 @@ namespace torrents
std::string CreateByteString (std::string_view str);
std::string CreateInteger (int64_t v);
std::string CreateDictionary (const std::vector<std::pair<std::string_view, std::string_view> >& items);
std::string CreateList (const std::vector<std::string>& items);
constexpr size_t REQUEST_BLOCK_SIZE = 16384;
@@ -284,8 +285,9 @@ namespace torrents
Piece& GetPiece (int index) { return m_Pieces[index]; }
std::pair<std::vector<uint8_t>, boost::logic::tribool> CreateBitfield () const; // (bitfield, true - all false - none)
bool ApplyBitfield (const std::vector<uint8_t>& bitfield); // return true if complete
std::unordered_set<i2p::data::IdentHash> GetNonConnectedPeers ();
std::unordered_set<i2p::data::IdentHash> GetNonConnectedPeers (size_t trackerID);
std::unordered_set<i2p::data::IdentHash> GetNonConnectedPeers ();
std::unordered_set<i2p::data::IdentHash> GetNonConnectedPeers (size_t trackerID);
std::unordered_set<i2p::data::IdentHash> GetAllPeers () const;
RequestedBlock GetNextBlockToRequest (std::shared_ptr<PeerConnection> conn, bool skipRequested = true);
std::vector<PieceFileFragment> GetPieceFileFragments (int index) const;
std::vector<size_t> GetFilesCompleted () const; // completed size per file
+57 -11
View File
@@ -9,6 +9,7 @@
#ifndef NO_TORRENTS
#include <string.h>
#include <vector>
#include "TorrentsTunnel.h"
#include "TorrentsDHT.h"
@@ -264,9 +265,9 @@ namespace torrents
{
// query
char type = 0;
std::string transactionID, query, id;
std::string transactionID, query, id, infoHash;
ParseDictionary (std::string_view ((const char *)buf, len),
[&type, &transactionID, &query, &id](std::string_view key, std::string_view buf)->size_t
[&type, &transactionID, &query, &id, &infoHash](std::string_view key, std::string_view buf)->size_t
{
if (key == "y")
{
@@ -289,7 +290,7 @@ namespace torrents
else if (key == "a")
{
return ParseDictionary (buf,
[&id](std::string_view key, std::string_view buf)->size_t
[&id, &infoHash](std::string_view key, std::string_view buf)->size_t
{
if (key == "id")
{
@@ -297,25 +298,55 @@ namespace torrents
if (l) id = value;
return l;
}
else if (key == "info_hash")
{
auto [value, l] = ExtractByteString (buf);
if (l) infoHash = value;
return l;
}
return 0;
});
}
return 0;
});
if (type == 'q')
HandleQuery (from.GetIdentHash (), fromPort, transactionID, query, id);
{
if (query == "ping")
HandlePingQuery (from.GetIdentHash (), fromPort, transactionID, id);
else if (query == "get_peers")
HandleGetPeersQuery (from.GetIdentHash (), fromPort, transactionID, id, infoHash);
else
LogPrint (eLogDebug, "TorrentsDHT: Unexpected query ", query);
}
else if (type)
LogPrint (eLogInfo, "TorrentsDHT: Unxpected msg type ", (int)type);
}
void TorrentsDHT::HandleQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view query, std::string_view id)
void TorrentsDHT::HandlePingQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view id)
{
LogPrint (eLogDebug, "TorrentsDHT: Query msg received");
if (query == "ping")
SendPingResponse (transactionID, fromIdent, fromPort + 1); // to rport
else
LogPrint (eLogDebug, "TorrentsDHT: Unexpected query ", query);
LogPrint (eLogDebug, "TorrentsDHT: Ping query msg received");
SendPingResponse (transactionID, fromIdent, fromPort + 1); // to rport
}
void TorrentsDHT::HandleGetPeersQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view id, std::string_view infoHash)
{
LogPrint (eLogDebug, "TorrentsDHT: Get peers query msg received");
Torrent::InfoHash hash;
if (infoHash.size () < hash.size ())
{
LogPrint (eLogInfo, "TorrentsDHT: Requested info hash is too short ", infoHash.size ());
return;
}
memcpy (hash.data (), infoHash.data (), hash.size ());
auto torrent = m_Tunnel.FindTorrent (hash);
if (torrent)
{
auto peers = torrent->GetAllPeers ();
if (!peers.empty ())
SendGetPeersResponse (transactionID, peers, fromIdent, fromPort + 1); // to rport
}
}
void TorrentsDHT::HandleResponse (std::string_view transactionID, std::string_view id)
@@ -413,6 +444,21 @@ namespace torrents
}),
transactionID, toIdent, toPort);
}
void TorrentsDHT::SendGetPeersResponse (std::string_view transactionID, const std::unordered_set<i2p::data::IdentHash>& peers,
const i2p::data::IdentHash& toIdent, uint16_t toPort)
{
std::vector<std::string> values;
for (auto& it: peers)
values.emplace_back (CreateByteString (std::string_view ((const char *)it.data (), i2p::data::IdentHash::len)));
SendResponseMsg (CreateDictionary ({
{ "id", CreateByteString (std::string_view ((const char *)m_NodeID.data (), m_NodeID.size ())) },
{ "token", CreateByteString ("12345") }, // TODO:
{ "values", CreateList (values) }
}),
transactionID, toIdent, toPort);
}
}
}
+6 -2
View File
@@ -127,8 +127,10 @@ namespace torrents
void HandleDatagram (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort,
const uint8_t * buf, size_t len, const i2p::util::Mapping * options);
void HandleQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view query, std::string_view id);
void HandlePingQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view id);
void HandleGetPeersQuery (const i2p::data::IdentHash& fromIdent, uint16_t fromPort,
std::string_view transactionID, std::string_view id, std::string_view infoHash);
void HandleResponse (std::string_view transactionID, std::string_view id);
void SendDatagram (std::string_view msg, const i2p::data::IdentHash& toIdent, uint16_t toPort);
@@ -136,6 +138,8 @@ namespace torrents
void SendQueryMsg (std::string_view query, std::string_view arguments, const i2p::data::IdentHash& toIdent, uint16_t toPort);
void SendResponseMsg (std::string_view response, std::string_view transactionID, const i2p::data::IdentHash& toIdent, uint16_t toPort);
void SendPingResponse (std::string_view transactionID, const i2p::data::IdentHash& toIdent, uint16_t toPort);
void SendGetPeersResponse (std::string_view transactionID, const std::unordered_set<i2p::data::IdentHash>& peers,
const i2p::data::IdentHash& toIdent, uint16_t toPort);
private: