diff --git a/libi2pd_client/TorrentsDHT.cpp b/libi2pd_client/TorrentsDHT.cpp index 861241a9..93bde6a5 100644 --- a/libi2pd_client/TorrentsDHT.cpp +++ b/libi2pd_client/TorrentsDHT.cpp @@ -30,6 +30,35 @@ namespace torrents return d; } + RoutingTable::RoutingTable (const NodeID& ourNode): + m_OurNode (ourNode) + { + m_Buckets.push_back (std::make_shared ()); + } + + std::shared_ptr RoutingTable::FindBucket (const NodeID& id) + { + if (m_Buckets.empty ()) return nullptr; + auto it = m_Buckets.begin (); + while (std::next (it) != m_Buckets.end ()) + { + if (id < (*std::next (it))->start) + return *it; + it++; + } + return *it; + } + + std::shared_ptr RoutingTable::AddNode (const NodeID& id, i2p::data::IdentHash& peer, uint16_t port) + { + if (id == m_OurNode) return nullptr; + auto bucket = FindBucket (id); + if (!bucket) return nullptr; + auto node = std::make_shared(id, peer, port); + bucket->nodes.emplace_back (node); + return node; + } + TorrentsDHT::TorrentsDHT (TorrentsTunnel& tunnel, uint16_t port): m_Tunnel (tunnel), m_Port (port) { @@ -42,6 +71,7 @@ namespace torrents memcpy (m_NodeInfo.data (), m_NodeID.buf, m_NodeID.len); memcpy (m_NodeInfo.data () + m_NodeID.len, dest->GetIdentHash (), i2p::data::IdentHash::len); htobe16buf (m_NodeInfo.data () + m_NodeInfo.size () - 2, port); + m_RoutingTable = std::make_unique (m_NodeID); } else { diff --git a/libi2pd_client/TorrentsDHT.h b/libi2pd_client/TorrentsDHT.h index 04f7dcee..d06d79cb 100644 --- a/libi2pd_client/TorrentsDHT.h +++ b/libi2pd_client/TorrentsDHT.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "Identity.h" #include "I2PService.h" #include "util.h" @@ -33,18 +34,25 @@ namespace torrents 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; } }; struct NodeDistance: public NodeID { - auto operator<=>(const NodeDistance& other) const { return memcmp (buf, other.buf, len) <=> 0; } }; NodeDistance operator^(const NodeID& node1, const NodeID& node2); struct Node { NodeID id; - i2p::data::IdentHash peerInfo; + i2p::data::IdentHash peer; + uint16_t port; + + Node (const NodeID& id1, const i2p::data::IdentHash& peer1, uint16_t port1): + id (id1), peer (peer1), port (port1) {} }; constexpr size_t MAX_BUCKET_CAPACITY = 8; @@ -52,17 +60,26 @@ namespace torrents { std::list > nodes; NodeID start; + + Bucket (): start (NodeID::Zero ()) {} }; class RoutingTable { public: - RoutingTable () = default; + RoutingTable (const NodeID& ourNode); + + std::shared_ptr AddNode (const NodeID& id, i2p::data::IdentHash& peer, uint16_t port); + + private: + + std::shared_ptr FindBucket (const NodeID& id); private: std::list > m_Buckets; + NodeID m_OurNode; }; using NodeInfo = std::array; @@ -91,7 +108,7 @@ namespace torrents uint16_t m_Port; NodeID m_NodeID; NodeInfo m_NodeInfo; // 20 byte Node ID + 32 byte IdentHash + 2 byte port - RoutingTable m_RoutingTable; + std::unique_ptr m_RoutingTable; }; } }