mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-10-06 03:28:05 +00:00
handle get_peers query
This commit is contained in:
@@ -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]);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user