move routing table to a different file

This commit is contained in:
Adrien Béraud committed 2016-05-02 15:25:15 -04:00
1 parent f9e6662f7d
commit 0890ed9c4f
5 files changed
+244 -204

No files matched your search

+2
View File
@@ -35,6 +35,7 @@ list (APPEND opendht_SOURCES
src/node.cpp
src/value.cpp
src/dht.cpp
src/routing_table.cpp
src/network_engine.cpp
src/securedht.cpp
src/dhtrunner.cpp
@@ -55,6 +56,7 @@ list (APPEND opendht_HEADERS
include/opendht/node.h
include/opendht/value.h
include/opendht/dht.h
include/opendht/routing_table.h
include/opendht/network_engine.h
include/opendht/scheduler.h
include/opendht/securedht.h
+1 -54
View File
@@ -26,6 +26,7 @@
#include "utils.h"
#include "network_engine.h"
#include "scheduler.h"
#include "routing_table.h"
#include <string>
#include <array>
@@ -368,60 +369,6 @@ private:
std::list<std::weak_ptr<Node>> cache_6;
};
struct Bucket {
Bucket() : cached() {}
Bucket(sa_family_t af, const InfoHash& f = {}, time_point t = time_point::min())
: af(af), first(f), time(t), cached() {}
sa_family_t af {0};
InfoHash first {};
time_point time {time_point::min()}; /* time of last reply in this bucket */
std::list<std::shared_ptr<Node>> nodes {};
sockaddr_storage cached; /* the address of a likely candidate */
socklen_t cachedlen {0};
/** Return a random node in a bucket. */
std::shared_ptr<Node> randomNode();
};
class RoutingTable : public std::list<Bucket> {
public:
using std::list<Bucket>::list;
InfoHash middle(const RoutingTable::const_iterator&) const;
std::vector<std::shared_ptr<Node>> findClosestNodes(const InfoHash id, time_point now, size_t count = TARGET_NODES) const;
RoutingTable::iterator findBucket(const InfoHash& id);
RoutingTable::const_iterator findBucket(const InfoHash& id) const;
/**
* Return true if the id is in the bucket's range.
*/
inline bool contains(const RoutingTable::const_iterator& bucket, const InfoHash& id) const {
return InfoHash::cmp(bucket->first, id) <= 0
&& (std::next(bucket) == end() || InfoHash::cmp(id, std::next(bucket)->first) < 0);
}
/**
* Return true if the table has no bucket ore one empty buket.
*/
inline bool isEmpty() const {
return empty() || (size() == 1 && front().nodes.empty());
}
/**
* Return a random id in the bucket's range.
*/
InfoHash randomId(const RoutingTable::const_iterator& bucket) const;
unsigned depth(const RoutingTable::const_iterator& bucket) const;
/**
* Split a bucket in two equal parts.
*/
bool split(const RoutingTable::iterator& b);
};
struct SearchNode {
SearchNode(std::shared_ptr<Node> node) : node(node) {}
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "node.h"
namespace dht {
struct Bucket {
Bucket() : cached() {}
Bucket(sa_family_t af, const InfoHash& f = {}, time_point t = time_point::min())
: af(af), first(f), time(t), cached() {}
sa_family_t af {0};
InfoHash first {};
time_point time {time_point::min()}; /* time of last reply in this bucket */
std::list<std::shared_ptr<Node>> nodes {};
sockaddr_storage cached; /* the address of a likely candidate */
socklen_t cachedlen {0};
/** Return a random node in a bucket. */
std::shared_ptr<Node> randomNode();
};
class RoutingTable : public std::list<Bucket> {
public:
using std::list<Bucket>::list;
InfoHash middle(const RoutingTable::const_iterator&) const;
std::vector<std::shared_ptr<Node>> findClosestNodes(const InfoHash id, time_point now, size_t count = TARGET_NODES) const;
RoutingTable::iterator findBucket(const InfoHash& id);
RoutingTable::const_iterator findBucket(const InfoHash& id) const;
/**
* Return true if the id is in the bucket's range.
*/
inline bool contains(const RoutingTable::const_iterator& bucket, const InfoHash& id) const {
return InfoHash::cmp(bucket->first, id) <= 0
&& (std::next(bucket) == end() || InfoHash::cmp(id, std::next(bucket)->first) < 0);
}
/**
* Return true if the table has no bucket ore one empty buket.
*/
inline bool isEmpty() const {
return empty() || (size() == 1 && front().nodes.empty());
}
/**
* Return a random id in the bucket's range.
*/
InfoHash randomId(const RoutingTable::const_iterator& bucket) const;
unsigned depth(const RoutingTable::const_iterator& bucket) const;
/**
* Split a bucket in two equal parts.
*/
bool split(const RoutingTable::iterator& b);
};
}
-150
View File
@@ -173,128 +173,6 @@ Dht::isMartian(const sockaddr *sa, socklen_t len)
}
}
std::shared_ptr<Node>
Dht::Bucket::randomNode()
{
if (nodes.empty())
return nullptr;
std::uniform_int_distribution<unsigned> rand_node(0, nodes.size()-1);
unsigned nn = rand_node(rd);
for (auto& n : nodes)
if (not nn--) return n;
return nodes.back();
}
InfoHash
Dht::RoutingTable::randomId(const Dht::RoutingTable::const_iterator& it) const
{
int bit1 = it->first.lowbit();
int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1;
int bit = std::max(bit1, bit2) + 1;
if (bit >= 8*(int)HASH_LEN)
return it->first;
int b = bit/8;
InfoHash id_return;
std::copy_n(it->first.begin(), b, id_return.begin());
id_return[b] = it->first[b] & (0xFF00 >> (bit % 8));
id_return[b] |= rand_byte(rd) >> (bit % 8);
for (unsigned i = b + 1; i < HASH_LEN; i++)
id_return[i] = rand_byte(rd);
return id_return;
}
InfoHash
Dht::RoutingTable::middle(const RoutingTable::const_iterator& it) const
{
unsigned bit = depth(it);
if (bit >= 8*HASH_LEN)
throw std::out_of_range("End of table");
InfoHash id = it->first;
id.setBit(bit, 1);
return id;
}
unsigned
Dht::RoutingTable::depth(const RoutingTable::const_iterator& it) const
{
int bit1 = it->first.lowbit();
int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1;
return std::max(bit1, bit2)+1;
}
std::vector<std::shared_ptr<Node>>
Dht::RoutingTable::findClosestNodes(const InfoHash id, time_point now, size_t count) const
{
std::vector<std::shared_ptr<Node>> nodes {};
auto bucket = findBucket(id);
if (bucket == end()) { return nodes; }
auto sortedBucketInsert = [&](const Bucket &b) {
for (auto n : b.nodes) {
if (not n->isGood(now))
continue;
auto here = std::find_if(nodes.begin(), nodes.end(),
[&id,&n](std::shared_ptr<Node> &node) {
return id.xorCmp(n->id, node->id) < 0;
}
);
nodes.insert(here, n);
}
};
auto itn = bucket;
auto itp = std::prev(bucket);
while (nodes.size() < count && (itn != end() || itp != end())) {
if (itn != end()) {
sortedBucketInsert(*itn);
itn = std::next(itn);
}
if (itp != end()) {
sortedBucketInsert(*itp);
if (itp == begin()) {
itp = end();
continue;
}
itp = std::prev(itp);
}
}
// shrink to the count closest nodes.
if (nodes.size() > count) {
nodes.resize(count);
}
return nodes;
}
Dht::RoutingTable::iterator
Dht::RoutingTable::findBucket(const InfoHash& id)
{
if (empty())
return end();
auto b = begin();
while (true) {
auto next = std::next(b);
if (next == end())
return b;
if (InfoHash::cmp(id, next->first) < 0)
return b;
b = next;
}
}
Dht::RoutingTable::const_iterator
Dht::RoutingTable::findBucket(const InfoHash& id) const
{
/* Avoid code duplication for the const version */
const_iterator it = const_cast<RoutingTable*>(this)->findBucket(id);
return it;
}
/* Every bucket contains an unordered list of nodes. */
std::shared_ptr<Node>
Dht::findNode(const InfoHash& id, sa_family_t af)
@@ -444,34 +322,6 @@ Dht::getPublicAddress(sa_family_t family)
return ret;
}
/* Split a bucket into two equal parts. */
bool
Dht::RoutingTable::split(const RoutingTable::iterator& b)
{
InfoHash new_id;
try {
new_id = middle(b);
} catch (const std::out_of_range& e) {
return false;
}
// Insert new bucket
insert(std::next(b), Bucket {b->af, new_id, b->time});
// Re-assign nodes
std::list<std::shared_ptr<Node>> nodes {};
nodes.splice(nodes.begin(), b->nodes);
while (!nodes.empty()) {
auto n = nodes.begin();
auto b = findBucket((*n)->id);
if (b == end())
nodes.erase(n);
else
b->nodes.splice(b->nodes.begin(), nodes, n);
}
return true;
}
bool
Dht::trySearchInsert(const std::shared_ptr<Node>& node)
{
+161
View File
@@ -0,0 +1,161 @@
#include "routing_table.h"
#include "rng.h"
#include <memory>
namespace dht {
static std::mt19937 rd {dht::crypto::random_device{}()};
static std::uniform_int_distribution<uint8_t> rand_byte;
std::shared_ptr<Node>
Bucket::randomNode()
{
if (nodes.empty())
return nullptr;
std::uniform_int_distribution<unsigned> rand_node(0, nodes.size()-1);
unsigned nn = rand_node(rd);
for (auto& n : nodes)
if (not nn--) return n;
return nodes.back();
}
InfoHash
RoutingTable::randomId(const RoutingTable::const_iterator& it) const
{
int bit1 = it->first.lowbit();
int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1;
int bit = std::max(bit1, bit2) + 1;
if (bit >= 8*(int)HASH_LEN)
return it->first;
int b = bit/8;
InfoHash id_return;
std::copy_n(it->first.begin(), b, id_return.begin());
id_return[b] = it->first[b] & (0xFF00 >> (bit % 8));
id_return[b] |= rand_byte(rd) >> (bit % 8);
for (unsigned i = b + 1; i < HASH_LEN; i++)
id_return[i] = rand_byte(rd);
return id_return;
}
InfoHash
RoutingTable::middle(const RoutingTable::const_iterator& it) const
{
unsigned bit = depth(it);
if (bit >= 8*HASH_LEN)
throw std::out_of_range("End of table");
InfoHash id = it->first;
id.setBit(bit, 1);
return id;
}
unsigned
RoutingTable::depth(const RoutingTable::const_iterator& it) const
{
int bit1 = it->first.lowbit();
int bit2 = std::next(it) != end() ? std::next(it)->first.lowbit() : -1;
return std::max(bit1, bit2)+1;
}
std::vector<std::shared_ptr<Node>>
RoutingTable::findClosestNodes(const InfoHash id, time_point now, size_t count) const
{
std::vector<std::shared_ptr<Node>> nodes {};
auto bucket = findBucket(id);
if (bucket == end()) { return nodes; }
auto sortedBucketInsert = [&](const Bucket &b) {
for (auto n : b.nodes) {
if (not n->isGood(now))
continue;
auto here = std::find_if(nodes.begin(), nodes.end(),
[&id,&n](std::shared_ptr<Node> &node) {
return id.xorCmp(n->id, node->id) < 0;
}
);
nodes.insert(here, n);
}
};
auto itn = bucket;
auto itp = std::prev(bucket);
while (nodes.size() < count && (itn != end() || itp != end())) {
if (itn != end()) {
sortedBucketInsert(*itn);
itn = std::next(itn);
}
if (itp != end()) {
sortedBucketInsert(*itp);
if (itp == begin()) {
itp = end();
continue;
}
itp = std::prev(itp);
}
}
// shrink to the count closest nodes.
if (nodes.size() > count) {
nodes.resize(count);
}
return nodes;
}
RoutingTable::iterator
RoutingTable::findBucket(const InfoHash& id)
{
if (empty())
return end();
auto b = begin();
while (true) {
auto next = std::next(b);
if (next == end())
return b;
if (InfoHash::cmp(id, next->first) < 0)
return b;
b = next;
}
}
RoutingTable::const_iterator
RoutingTable::findBucket(const InfoHash& id) const
{
/* Avoid code duplication for the const version */
const_iterator it = const_cast<RoutingTable*>(this)->findBucket(id);
return it;
}
/* Split a bucket into two equal parts. */
bool
RoutingTable::split(const RoutingTable::iterator& b)
{
InfoHash new_id;
try {
new_id = middle(b);
} catch (const std::out_of_range& e) {
return false;
}
// Insert new bucket
insert(std::next(b), Bucket {b->af, new_id, b->time});
// Re-assign nodes
std::list<std::shared_ptr<Node>> nodes {};
nodes.splice(nodes.begin(), b->nodes);
while (!nodes.empty()) {
auto n = nodes.begin();
auto b = findBucket((*n)->id);
if (b == end())
nodes.erase(n);
else
b->nodes.splice(b->nodes.begin(), nodes, n);
}
return true;
}
}