lokinet/llarp/dht/bucket.hpp

158 lines
3.6 KiB
C++
Raw Normal View History

#ifndef LLARP_DHT_BUCKET_HPP
#define LLARP_DHT_BUCKET_HPP
2018-12-15 16:21:52 +00:00
#include <crypto.hpp>
2018-12-12 00:48:54 +00:00
#include <dht/kademlia.hpp>
#include <dht/key.hpp>
#include <map>
#include <set>
2018-08-04 02:59:32 +00:00
#include <vector>
namespace llarp
{
namespace dht
{
template < typename Val_t >
struct Bucket
{
using BucketStorage_t = std::map< Key_t, Val_t, XorMetric >;
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
size_t
Size() const
{
return nodes.size();
}
2018-08-04 02:59:32 +00:00
bool
2018-08-29 20:40:26 +00:00
GetRandomNodeExcluding(Key_t& result,
const std::set< Key_t >& exclude) const
2018-08-04 02:59:32 +00:00
{
std::vector< Key_t > candidates;
for(const auto& item : nodes)
{
if(exclude.find(item.first) == exclude.end())
candidates.push_back(item.first);
}
if(candidates.size() == 0)
return false;
result = candidates[llarp::randint() % candidates.size()];
2018-08-04 02:59:32 +00:00
return true;
}
bool
FindClosest(const Key_t& target, Key_t& result) const
{
Key_t mindist;
mindist.Fill(0xff);
for(const auto& item : nodes)
{
auto curDist = item.first ^ target;
if(curDist < mindist)
{
mindist = curDist;
result = item.first;
}
}
return nodes.size() > 0;
}
2018-08-29 20:40:26 +00:00
bool
GetManyRandom(std::set< Key_t >& result, size_t N) const
{
if(nodes.size() < N)
2018-11-20 16:58:18 +00:00
{
llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ",
N);
2018-08-29 20:40:26 +00:00
return false;
2018-11-20 16:58:18 +00:00
}
2018-08-29 20:40:26 +00:00
if(nodes.size() == N)
{
for(const auto& node : nodes)
{
result.insert(node.first);
}
return true;
}
size_t expecting = N;
size_t sz = nodes.size();
while(N)
{
auto itr = nodes.begin();
std::advance(itr, llarp::randint() % sz);
2018-08-29 20:40:26 +00:00
if(result.insert(itr->first).second)
--N;
}
return result.size() == expecting;
}
bool
GetManyNearExcluding(const Key_t& target, std::set< Key_t >& result,
size_t N, const std::set< Key_t >& exclude) const
{
std::set< Key_t > s;
for(const auto& k : exclude)
s.insert(k);
Key_t peer;
while(N--)
{
if(!FindCloseExcluding(target, peer, s))
return false;
s.insert(peer);
result.insert(peer);
}
return true;
}
bool
FindCloseExcluding(const Key_t& target, Key_t& result,
2018-08-29 20:40:26 +00:00
const std::set< Key_t >& exclude) const
{
Key_t maxdist;
maxdist.Fill(0xff);
Key_t mindist;
mindist.Fill(0xff);
for(const auto& item : nodes)
{
2018-08-10 21:34:11 +00:00
if(exclude.count(item.first))
continue;
2018-08-10 21:34:11 +00:00
auto curDist = item.first ^ target;
if(curDist < mindist)
{
mindist = curDist;
result = item.first;
}
}
return mindist < maxdist;
}
void
PutNode(const Val_t& val)
{
auto itr = nodes.find(val.ID);
if(itr == nodes.end() || itr->second < val)
nodes[val.ID] = val;
}
void
DelNode(const Key_t& key)
{
auto itr = nodes.find(key);
if(itr != nodes.end())
nodes.erase(itr);
}
2018-12-19 17:48:29 +00:00
bool
HasNode(const Key_t& key) const
{
return nodes.find(key) != nodes.end();
}
BucketStorage_t nodes;
};
2018-07-17 04:37:50 +00:00
} // namespace dht
} // namespace llarp
#endif