mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2024-11-10 01:10:32 +00:00
store RouterInfo in DHT
This commit is contained in:
parent
ebee6c5f13
commit
abf687ff09
@ -14,7 +14,7 @@ namespace i2p
|
|||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
DHTNode::DHTNode ():
|
DHTNode::DHTNode ():
|
||||||
zero (nullptr), one (nullptr), hash (nullptr)
|
zero (nullptr), one (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,17 +22,16 @@ namespace data
|
|||||||
{
|
{
|
||||||
if (zero) delete zero;
|
if (zero) delete zero;
|
||||||
if (one) delete one;
|
if (one) delete one;
|
||||||
if (hash) delete hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DHTNode::MoveHashUp (bool fromOne)
|
void DHTNode::MoveRouterUp (bool fromOne)
|
||||||
{
|
{
|
||||||
DHTNode *& side = fromOne ? one : zero;
|
DHTNode *& side = fromOne ? one : zero;
|
||||||
if (side)
|
if (side)
|
||||||
{
|
{
|
||||||
if (hash) delete hash; // shouldn't happen
|
if (router) router = nullptr; // shouldn't happen
|
||||||
hash = side->hash;
|
router = side->router;
|
||||||
side->hash = nullptr;
|
side->router = nullptr;
|
||||||
delete side;
|
delete side;
|
||||||
side = nullptr;
|
side = nullptr;
|
||||||
}
|
}
|
||||||
@ -49,38 +48,46 @@ namespace data
|
|||||||
delete m_Root;
|
delete m_Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
DHTNode * DHTTable::Insert (const IdentHash& h)
|
void DHTTable::Clear ()
|
||||||
{
|
{
|
||||||
return Insert (new IdentHash (h), m_Root, 0);
|
m_Size = 0;
|
||||||
|
delete m_Root;
|
||||||
|
m_Root = new DHTNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
DHTNode * DHTTable::Insert (IdentHash * h, DHTNode * root, int level)
|
void DHTTable::Insert (const std::shared_ptr<RouterInfo>& r)
|
||||||
{
|
{
|
||||||
if (root->hash)
|
if (!r) return;
|
||||||
{
|
return Insert (r, m_Root, 0);
|
||||||
if (*(root->hash) == *h)
|
|
||||||
{
|
|
||||||
delete h;
|
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
auto h2 = root->hash;
|
|
||||||
root->hash = nullptr; m_Size--;
|
void DHTTable::Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level)
|
||||||
|
{
|
||||||
|
if (root->router)
|
||||||
|
{
|
||||||
|
if (root->router->GetIdentHash () == r->GetIdentHash ())
|
||||||
|
{
|
||||||
|
root->router = r; // replace
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto r2 = root->router;
|
||||||
|
root->router = nullptr; m_Size--;
|
||||||
int bit1, bit2;
|
int bit1, bit2;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
bit1 = h->GetBit (level);
|
bit1 = r->GetIdentHash ().GetBit (level);
|
||||||
bit2 = h2->GetBit (level);
|
bit2 = r2->GetIdentHash ().GetBit (level);
|
||||||
if (bit1 == bit2)
|
if (bit1 == bit2)
|
||||||
{
|
{
|
||||||
if (bit1)
|
if (bit1)
|
||||||
{
|
{
|
||||||
if (root->one) return nullptr; // someting wrong
|
if (root->one) return; // someting wrong
|
||||||
root->one = new DHTNode;
|
root->one = new DHTNode;
|
||||||
root = root->one;
|
root = root->one;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (root->zero) return nullptr; // someting wrong
|
if (root->zero) return; // someting wrong
|
||||||
root->zero = new DHTNode;
|
root->zero = new DHTNode;
|
||||||
root = root->zero;
|
root = root->zero;
|
||||||
}
|
}
|
||||||
@ -95,37 +102,36 @@ namespace data
|
|||||||
root->one = new DHTNode;
|
root->one = new DHTNode;
|
||||||
if (bit1)
|
if (bit1)
|
||||||
{
|
{
|
||||||
Insert (h2, root->zero, level + 1);
|
Insert (r2, root->zero, level + 1);
|
||||||
return Insert (h, root->one, level + 1);
|
Insert (r, root->one, level + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Insert (h2, root->one, level + 1);
|
Insert (r2, root->one, level + 1);
|
||||||
return Insert (h, root->zero, level + 1);
|
Insert (r, root->zero, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!root->zero && !root->one)
|
if (!root->zero && !root->one)
|
||||||
{
|
{
|
||||||
root->hash = h; m_Size++;
|
root->router = r; m_Size++;
|
||||||
return root;
|
return;
|
||||||
}
|
}
|
||||||
int bit = h->GetBit (level);
|
int bit = r->GetIdentHash ().GetBit (level);
|
||||||
if (bit)
|
if (bit)
|
||||||
{
|
{
|
||||||
if (!root->one)
|
if (!root->one)
|
||||||
root->one = new DHTNode;
|
root->one = new DHTNode;
|
||||||
return Insert (h, root->one, level + 1);
|
Insert (r, root->one, level + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!root->zero)
|
if (!root->zero)
|
||||||
root->zero = new DHTNode;
|
root->zero = new DHTNode;
|
||||||
return Insert (h, root->zero, level + 1);
|
Insert (r, root->zero, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DHTTable::Remove (const IdentHash& h)
|
bool DHTTable::Remove (const IdentHash& h)
|
||||||
@ -137,9 +143,9 @@ namespace data
|
|||||||
{
|
{
|
||||||
if (root)
|
if (root)
|
||||||
{
|
{
|
||||||
if (root->hash && *(root->hash) == h)
|
if (root->router && root->router->GetIdentHash () == h)
|
||||||
{
|
{
|
||||||
delete root->hash; root->hash = nullptr;
|
root->router = nullptr;
|
||||||
m_Size--;
|
m_Size--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -152,11 +158,11 @@ namespace data
|
|||||||
{
|
{
|
||||||
delete root->one;
|
delete root->one;
|
||||||
root->one = nullptr;
|
root->one = nullptr;
|
||||||
if (root->zero && root->zero->hash)
|
if (root->zero && root->zero->router)
|
||||||
root->MoveHashUp (false);
|
root->MoveRouterUp (false);
|
||||||
}
|
}
|
||||||
else if (root->one->hash && !root->zero)
|
else if (root->one->router && !root->zero)
|
||||||
root->MoveHashUp (true);
|
root->MoveRouterUp (true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,11 +174,11 @@ namespace data
|
|||||||
{
|
{
|
||||||
delete root->zero;
|
delete root->zero;
|
||||||
root->zero = nullptr;
|
root->zero = nullptr;
|
||||||
if (root->one && root->one->hash)
|
if (root->one && root->one->router)
|
||||||
root->MoveHashUp (true);
|
root->MoveRouterUp (true);
|
||||||
}
|
}
|
||||||
else if (root->zero->hash && !root->one)
|
else if (root->zero->router && !root->one)
|
||||||
root->MoveHashUp (false);
|
root->MoveRouterUp (false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,48 +186,95 @@ namespace data
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentHash * DHTTable::FindClosest (const IdentHash& h)
|
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, const Filter& filter)
|
||||||
{
|
{
|
||||||
return FindClosest (h, m_Root, 0);
|
if (filter) m_Filter = filter;
|
||||||
|
auto r = FindClosest (h, m_Root, 0);
|
||||||
|
m_Filter = nullptr;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentHash * DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level)
|
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level)
|
||||||
{
|
{
|
||||||
if (root->hash) return root->hash;
|
bool split = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (root->router)
|
||||||
|
return (!m_Filter || m_Filter (root->router)) ? root->router : nullptr;
|
||||||
|
split = root->zero && root->one;
|
||||||
|
if (!split)
|
||||||
|
{
|
||||||
|
if (root->zero) root = root->zero;
|
||||||
|
else if (root->one) root = root->one;
|
||||||
|
else return nullptr;
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!split);
|
||||||
int bit = h.GetBit (level);
|
int bit = h.GetBit (level);
|
||||||
if (bit)
|
if (bit)
|
||||||
{
|
{
|
||||||
if (root->one)
|
if (root->one)
|
||||||
return FindClosest (h, root->one, level + 1);
|
{
|
||||||
|
auto r = FindClosest (h, root->one, level + 1);
|
||||||
|
if (r) return r;
|
||||||
|
}
|
||||||
if (root->zero)
|
if (root->zero)
|
||||||
return FindClosest (h, root->zero, level + 1);
|
{
|
||||||
|
auto r = FindClosest (h, root->zero, level + 1);
|
||||||
|
if (r) return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (root->zero)
|
if (root->zero)
|
||||||
return FindClosest (h, root->zero, level + 1);
|
{
|
||||||
|
auto r = FindClosest (h, root->zero, level + 1);
|
||||||
|
if (r) return r;
|
||||||
|
}
|
||||||
if (root->one)
|
if (root->one)
|
||||||
return FindClosest (h, root->one, level + 1);
|
{
|
||||||
|
auto r = FindClosest (h, root->one, level + 1);
|
||||||
|
if (r) return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IdentHash *> DHTTable::FindClosest (const IdentHash& h, size_t num)
|
std::vector<std::shared_ptr<RouterInfo> > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter)
|
||||||
{
|
{
|
||||||
std::vector<IdentHash *> vec;
|
std::vector<std::shared_ptr<RouterInfo> > vec;
|
||||||
if (num > 0)
|
if (num > 0)
|
||||||
|
{
|
||||||
|
if (filter) m_Filter = filter;
|
||||||
FindClosest (h, num, m_Root, 0, vec);
|
FindClosest (h, num, m_Root, 0, vec);
|
||||||
|
m_Filter = nullptr;
|
||||||
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<IdentHash *>& hashes)
|
void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes)
|
||||||
{
|
{
|
||||||
if (hashes.size () >= num) return;
|
if (hashes.size () >= num) return;
|
||||||
if (root->hash)
|
bool split = false;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
hashes.push_back (root->hash);
|
if (root->router)
|
||||||
|
{
|
||||||
|
if (!m_Filter || m_Filter (root->router))
|
||||||
|
hashes.push_back (root->router);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
split = root->zero && root->one;
|
||||||
|
if (!split)
|
||||||
|
{
|
||||||
|
if (root->zero) root = root->zero;
|
||||||
|
else if (root->one) root = root->one;
|
||||||
|
else return;
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!split);
|
||||||
int bit = h.GetBit (level);
|
int bit = h.GetBit (level);
|
||||||
if (bit)
|
if (bit)
|
||||||
{
|
{
|
||||||
@ -239,6 +292,54 @@ namespace data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DHTTable::Cleanup (Filter filter)
|
||||||
|
{
|
||||||
|
if (filter)
|
||||||
|
{
|
||||||
|
m_Filter = filter;
|
||||||
|
Cleanup (m_Root);
|
||||||
|
m_Filter = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DHTTable::Cleanup (DHTNode * root)
|
||||||
|
{
|
||||||
|
if (!root) return;
|
||||||
|
if (root->router)
|
||||||
|
{
|
||||||
|
if (!m_Filter || !m_Filter (root->router))
|
||||||
|
{
|
||||||
|
m_Size--;
|
||||||
|
root->router = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (root->zero)
|
||||||
|
{
|
||||||
|
Cleanup (root->zero);
|
||||||
|
if (root->zero->IsEmpty ())
|
||||||
|
{
|
||||||
|
delete root->zero;
|
||||||
|
root->zero = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (root->one)
|
||||||
|
{
|
||||||
|
Cleanup (root->one);
|
||||||
|
if (root->one->IsEmpty ())
|
||||||
|
{
|
||||||
|
delete root->one;
|
||||||
|
root->one = nullptr;
|
||||||
|
if (root->zero && root->zero->router)
|
||||||
|
root->MoveRouterUp (false);
|
||||||
|
}
|
||||||
|
else if (root->one->router && !root->zero)
|
||||||
|
root->MoveRouterUp (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DHTTable::Print (std::stringstream& s)
|
void DHTTable::Print (std::stringstream& s)
|
||||||
{
|
{
|
||||||
Print (s, m_Root, 0);
|
Print (s, m_Root, 0);
|
||||||
@ -248,10 +349,10 @@ namespace data
|
|||||||
{
|
{
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
s << std::string (level, '-');
|
s << std::string (level, '-');
|
||||||
if (root->hash)
|
if (root->router)
|
||||||
{
|
{
|
||||||
if (!root->zero && !root->one)
|
if (!root->zero && !root->one)
|
||||||
s << '>' << GetIdentHashAbbreviation (*(root->hash));
|
s << '>' << GetIdentHashAbbreviation (root->router->GetIdentHash ());
|
||||||
else
|
else
|
||||||
s << "error";
|
s << "error";
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "Identity.h"
|
#include <functional>
|
||||||
|
#include "RouterInfo.h"
|
||||||
|
|
||||||
// Kademlia DHT (XOR distance)
|
// Kademlia DHT (XOR distance)
|
||||||
|
|
||||||
@ -24,42 +25,48 @@ namespace data
|
|||||||
struct DHTNode
|
struct DHTNode
|
||||||
{
|
{
|
||||||
DHTNode * zero, * one;
|
DHTNode * zero, * one;
|
||||||
IdentHash * hash;
|
std::shared_ptr<RouterInfo> router;
|
||||||
|
|
||||||
DHTNode ();
|
DHTNode ();
|
||||||
~DHTNode ();
|
~DHTNode ();
|
||||||
|
|
||||||
bool IsEmpty () const { return !zero && !one && !hash; };
|
bool IsEmpty () const { return !zero && !one && !router; };
|
||||||
void MoveHashUp (bool fromOne);
|
void MoveRouterUp (bool fromOne);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DHTTable
|
class DHTTable
|
||||||
{
|
{
|
||||||
|
typedef std::function<bool (const std::shared_ptr<RouterInfo>&)> Filter;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DHTTable ();
|
DHTTable ();
|
||||||
~DHTTable ();
|
~DHTTable ();
|
||||||
|
|
||||||
DHTNode * Insert (const IdentHash& h);
|
void Insert (const std::shared_ptr<RouterInfo>& r);
|
||||||
bool Remove (const IdentHash& h);
|
bool Remove (const IdentHash& h);
|
||||||
IdentHash * FindClosest (const IdentHash& h);
|
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, const Filter& filter = nullptr);
|
||||||
std::vector<IdentHash *> FindClosest (const IdentHash& h, size_t num);
|
std::vector<std::shared_ptr<RouterInfo> > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr);
|
||||||
|
|
||||||
void Print (std::stringstream& s);
|
void Print (std::stringstream& s);
|
||||||
size_t GetSize () const { return m_Size; };
|
size_t GetSize () const { return m_Size; };
|
||||||
|
void Clear ();
|
||||||
|
void Cleanup (Filter filter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DHTNode * Insert (IdentHash * h, DHTNode * root, int level); // recursive
|
void Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level); // recursive
|
||||||
bool Remove (const IdentHash& h, DHTNode * root, int level);
|
bool Remove (const IdentHash& h, DHTNode * root, int level);
|
||||||
IdentHash * FindClosest (const IdentHash& h, DHTNode * root, int level);
|
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, DHTNode * root, int level);
|
||||||
void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<IdentHash *>& hashes);
|
void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes);
|
||||||
|
void Cleanup (DHTNode * root);
|
||||||
void Print (std::stringstream& s, DHTNode * root, int level);
|
void Print (std::stringstream& s, DHTNode * root, int level);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DHTNode * m_Root;
|
DHTNode * m_Root;
|
||||||
size_t m_Size;
|
size_t m_Size;
|
||||||
|
// transient
|
||||||
|
Filter m_Filter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1355,14 +1355,11 @@ namespace data
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
std::shared_ptr<const RouterInfo> NetDb::GetClosestFloodfill (const IdentHash& destination,
|
||||||
const std::set<IdentHash>& excluded, bool closeThanUsOnly) const
|
const std::set<IdentHash>& excluded) const
|
||||||
{
|
{
|
||||||
std::shared_ptr<const RouterInfo> r;
|
std::shared_ptr<const RouterInfo> r;
|
||||||
XORMetric minMetric;
|
XORMetric minMetric;
|
||||||
IdentHash destKey = CreateRoutingKey (destination);
|
IdentHash destKey = CreateRoutingKey (destination);
|
||||||
if (closeThanUsOnly)
|
|
||||||
minMetric = destKey ^ i2p::context.GetIdentHash ();
|
|
||||||
else
|
|
||||||
minMetric.SetMax ();
|
minMetric.SetMax ();
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (const auto& it: m_Floodfills)
|
for (const auto& it: m_Floodfills)
|
||||||
|
@ -93,7 +93,7 @@ namespace data
|
|||||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user