diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index 93bde6a5..b8eddfc2 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -17,18 +17,6 @@ namespace i2p { namespace torrents { - NodeDistance operator^(const NodeID& node1, const NodeID& node2) - { - NodeDistance d; - - d.l[0] = node1.l[0] ^ node2.l[0]; - d.l[1] = node1.l[1] ^ node2.l[1]; - d.l[2] = node1.l[2] ^ node2.l[2]; - d.l[3] = node1.l[3] ^ node2.l[3]; - d.l[4] = node1.l[4] ^ node2.l[4]; - - return d; - } RoutingTable::RoutingTable (const NodeID& ourNode): m_OurNode (ourNode) @@ -36,7 +24,7 @@ namespace torrents m_Buckets.push_back (std::make_shared ()); } - std::shared_ptr RoutingTable::FindBucket (const NodeID& id) + std::shared_ptr RoutingTable::FindBucket (const Torrent::InfoHash& id) const { if (m_Buckets.empty ()) return nullptr; auto it = m_Buckets.begin (); @@ -59,23 +47,47 @@ namespace torrents return node; } + std::list, Distance> > RoutingTable::FindClosestNodes (const Torrent::InfoHash& infoHash, size_t num) const + { + std::list, Distance> > ret; + if (num > 0) + { + auto bucket = FindBucket (infoHash); + if (bucket) + { + for (auto it: bucket->nodes) + { + auto nodeDistance = it->id ^ infoHash; + auto it1 = std::find_if (ret.begin (), ret.end (), + [&nodeDistance](const std::pair, Distance>& alreadyFound) + { + return nodeDistance < alreadyFound.second; + }); + ret.insert (it1, { it, nodeDistance } ); + } + if (ret.size () > num) ret.resize (num); + } + } + return ret; + } + TorrentsDHT::TorrentsDHT (TorrentsTunnel& tunnel, uint16_t port): m_Tunnel (tunnel), m_Port (port) { auto dest = tunnel.GetLocalDestination (); if (dest) { - memcpy (m_NodeID.buf, dest->GetIdentHash (), m_NodeID.len); - m_NodeID.buf[4] ^= (port >> 8); - m_NodeID.buf[5] ^= (port & 0xFF); - memcpy (m_NodeInfo.data (), m_NodeID.buf, m_NodeID.len); - memcpy (m_NodeInfo.data () + m_NodeID.len, dest->GetIdentHash (), i2p::data::IdentHash::len); + memcpy (m_NodeID.data (), dest->GetIdentHash (), m_NodeID.size ()); + m_NodeID[4] ^= (port >> 8); + m_NodeID[5] ^= (port & 0xFF); + memcpy (m_NodeInfo.data (), m_NodeID.data (), m_NodeID.size ()); + memcpy (m_NodeInfo.data () + m_NodeID.size (), dest->GetIdentHash (), i2p::data::IdentHash::len); htobe16buf (m_NodeInfo.data () + m_NodeInfo.size () - 2, port); m_RoutingTable = std::make_unique (m_NodeID); } else { - memset (m_NodeID.buf, 0, m_NodeID.len); + m_NodeID.fill (0); m_NodeInfo.fill (0); } } diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index d06d79cb..8098efc0 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -17,34 +17,29 @@ #include #include #include +#include #include "Identity.h" #include "I2PService.h" #include "util.h" +#include "Torrents.h" namespace i2p { namespace torrents { - struct NodeID + using Distance = Torrent::InfoHash; + struct NodeID: public Torrent::InfoHash { - static constexpr size_t len = SHA_DIGEST_LENGTH; - - union // 4 bytes aligned + static constexpr size_t len = std::tuple_size::value; + constexpr Distance operator^(const Torrent::InfoHash& hash) { - uint8_t buf[len]; - uint32_t l[len/4]; - }; - - auto operator<=>(const NodeID& other) const { return memcmp (buf, other.buf, len) <=> 0; } - bool operator==(const NodeID& other) const { return !memcmp (buf, other.buf, len); } - static constexpr NodeID Zero () { NodeID n; std::fill_n (n.buf, len, 0); return n; } + Distance d; + for (size_t i = 0; i < size (); i++) + d[i] = (*this)[i] ^ hash[i]; + return d; + } }; - struct NodeDistance: public NodeID - { - }; - NodeDistance operator^(const NodeID& node1, const NodeID& node2); - struct Node { NodeID id; @@ -61,7 +56,7 @@ namespace torrents std::list > nodes; NodeID start; - Bucket (): start (NodeID::Zero ()) {} + Bucket (): start{} {} }; class RoutingTable @@ -71,10 +66,11 @@ namespace torrents RoutingTable (const NodeID& ourNode); std::shared_ptr AddNode (const NodeID& id, i2p::data::IdentHash& peer, uint16_t port); + std::list, Distance> > FindClosestNodes (const Torrent::InfoHash& infoHash, size_t num) const; private: - std::shared_ptr FindBucket (const NodeID& id); + std::shared_ptr FindBucket (const Torrent::InfoHash& id) const; private: diff --git a/libi2pd_client/TorrentsTunnel.cpp b/libi2pd_client/TorrentsTunnel.cpp index 112add50..51ca41eb 100644 --- a/libi2pd_client/TorrentsTunnel.cpp +++ b/libi2pd_client/TorrentsTunnel.cpp @@ -29,7 +29,8 @@ namespace torrents i2p::client::I2PService (localDestination), m_Name (name), m_PeerID ("-I2PD-"), m_TorrentsDir (torrentsDir), m_TrackerRequestsCheckTimer (GetService ()), m_KeepAliveCheckTimer (GetService ()), m_ReconnectCheckTimer (GetService ()), - m_TorrentsStatusUpdateTimer (GetService ()), m_DHT (*this, localDestination->GetRng()() % 1000 + 6000) + m_TorrentsStatusUpdateTimer (GetService ()), + m_DHT (*this, TORRENT_PORT + (localDestination ? localDestination->GetRng()() % (65535 - TORRENT_PORT - 1) : 1)) { if (localDestination) m_PeerID += localDestination->GetIdentHash ().ToBase64 ();