mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
502776aca3 | ||
|
|
7b4eac558a | ||
|
|
8f8905dfd1 | ||
|
|
64b4d2fa4a | ||
|
|
574d1934c9 | ||
|
|
b3ad031a97 | ||
|
|
a0b9a1986c | ||
|
|
97efe5b791 | ||
|
|
b6c1b6fdd2 | ||
|
|
7e2ae46870 | ||
|
|
ba5d60cebe | ||
|
|
0dc158047a | ||
|
|
1ab615096c | ||
|
|
f8d26e8f9f | ||
|
|
c0b4bf8a46 | ||
|
|
8f26e30021 | ||
|
|
c1e86b48f1 | ||
|
|
b4b39f52dc | ||
|
|
c7a6e11a24 | ||
|
|
d95eeb31e3 |
No files matched your search
+2
-1
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required (VERSION 2.8.6)
|
||||
project (opendht)
|
||||
set (opendht_VERSION_MAJOR 0)
|
||||
set (opendht_VERSION_MINOR 6.1)
|
||||
set (opendht_VERSION_MINOR 6.2)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
|
||||
@@ -131,6 +131,7 @@ endif ()
|
||||
if (OPENDHT_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif ()
|
||||
add_subdirectory(doc)
|
||||
|
||||
if (OPENDHT_PYTHON)
|
||||
add_subdirectory(python)
|
||||
|
||||
@@ -10,9 +10,7 @@ if USE_CYTHON
|
||||
SUBDIRS += python
|
||||
endif
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
SUBDIRS += doc
|
||||
endif
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
AC_INIT(opendht, 0.6.1)
|
||||
AC_INIT(opendht, 0.6.2)
|
||||
AC_CONFIG_AUX_DIR(ac)
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -75,9 +75,9 @@ LT_LANG(C++)
|
||||
AX_CXX_COMPILE_STDCXX(11,[noext],[mandatory])
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
PKG_CHECK_MODULES([nettle], [nettle >= 2.4])
|
||||
PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.1])
|
||||
PKG_CHECK_MODULES([msgpack], [msgpack >= 1.2])
|
||||
PKG_CHECK_MODULES([Nettle], [nettle >= 2.4])
|
||||
PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.1])
|
||||
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
|
||||
CXXFLAGS="${CXXFLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
|
||||
|
||||
AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes)
|
||||
@@ -88,7 +88,7 @@ AM_COND_IF([ENABLE_TOOLS], [
|
||||
])
|
||||
])
|
||||
|
||||
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])])
|
||||
AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])
|
||||
|
||||
dnl Configure setup.py if we build the python module
|
||||
AM_COND_IF([USE_CYTHON], [
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if (OPENDHT_TOOLS)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dhtnode.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1)
|
||||
endif ()
|
||||
@@ -1,3 +1,6 @@
|
||||
dist_man1_MANS = dhtnode.1
|
||||
|
||||
if HAVE_DOXYGEN
|
||||
doxyfile.stamp:
|
||||
$(DOXYGEN) Doxyfile
|
||||
echo stamp > doxyfile.stamp
|
||||
@@ -7,3 +10,4 @@ CLEANFILES = doxyfile.stamp
|
||||
all-local: doxyfile.stamp
|
||||
clean-local:
|
||||
rm -rf $(top_srcdir)/doc/man $(top_srcdir)/doc/html
|
||||
endif
|
||||
@@ -0,0 +1,85 @@
|
||||
.TH DHTNODE 1 2016-06-27
|
||||
|
||||
.SH NAME
|
||||
.B dhtnode
|
||||
- a simple OpenDHT command line node runner.
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B dhtnode [-h]
|
||||
|
||||
.B dhtnode [-v[\fIlogfile\fP]] [-i] [-d] [-n \fInetwork_id\fP] [-p \fIlocal_port\fP] [-b[\fIbootstrap_host\fP[:\fIport\fP]]]
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
This program runs a simple OpenDHT node in an interactive way. If you rather
|
||||
want to run the node in daemon mode, option \fB'-d'\fP is provided. When running
|
||||
in the interactive shell, you benefit from the readline capabilities for writing
|
||||
your commands such as command history. Here are the available commands in the
|
||||
interactive shell:
|
||||
|
||||
.EE
|
||||
h, help Print this help message.
|
||||
q, quit Quit the program.
|
||||
log Start/stop printing DHT logs.
|
||||
|
||||
Node information:
|
||||
ll Print basic information and stats about the current node.
|
||||
ls Print basic information about current searches.
|
||||
ld Print basic information about currenty stored values on this node.
|
||||
lr Print the full current routing table of this node
|
||||
|
||||
Operations on the DHT:
|
||||
b ip:port Ping potential node at given IP address/port.
|
||||
g [key] Get values at [key].
|
||||
l [key] Listen for value changes at [key].
|
||||
p [key] [str] Put string value at [key].
|
||||
s [key] [str] Put string value at [key], signed with our generated
|
||||
private key.
|
||||
e [key] [dest] [str] Put string value at [key], encrypted for [dest] with
|
||||
its public key (if found).
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
\fB-h\fP
|
||||
Prints some help.
|
||||
|
||||
.TP
|
||||
\fB-v\fP[\fIlogfile\fP]
|
||||
Enable the verbose mode. Optionally provide a log file.
|
||||
|
||||
.TP
|
||||
\fB-i\fP
|
||||
Generate cryptographic identity for the node.
|
||||
|
||||
.TP
|
||||
\fB-d\fP
|
||||
Run the program in daemon mode (will fork in the background).
|
||||
|
||||
.TP
|
||||
\fB-n\fP \fInetwork_id\fP
|
||||
Specify the network id. This let you connect to distinct networks and prevents
|
||||
the merge of two different networks (available since OpenDHT v0.6.1).
|
||||
|
||||
.TP
|
||||
\fB-p\fP \fIlocal_port\fP
|
||||
Use port \fIlocal_port\fP for the program to bind to.
|
||||
|
||||
.TP
|
||||
\fB-b\fP[\fIbootstrap_host\fP[:\fIport\fP]]
|
||||
The program needs to be given a node to connect to the network. You use this
|
||||
option to provide the ip address of that node. If no argument is provided, the
|
||||
node runs in \fBbootstrap mode\fP, i.e. it will especially serve as entry point
|
||||
in the network.
|
||||
|
||||
.SH AUTHORS
|
||||
.TP
|
||||
Program written by
|
||||
.IP \(bu
|
||||
.\}
|
||||
Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
.TP
|
||||
Man page written by
|
||||
.IP \(bu
|
||||
.\}
|
||||
Simon Désaulniers <sim.desaulniers@gmail.com>
|
||||
+28
-8
@@ -163,16 +163,35 @@ public:
|
||||
* reannounced on a regular basis.
|
||||
* User can call #cancelPut(InfoHash, Value::Id) to cancel a put operation.
|
||||
*/
|
||||
void put(const InfoHash& key, std::shared_ptr<Value>, DoneCallback cb=nullptr, time_point created=time_point::max());
|
||||
void put(const InfoHash& key, const std::shared_ptr<Value>& v, DoneCallbackSimple cb, time_point created=time_point::max()) {
|
||||
put(key, v, bindDoneCb(cb), created);
|
||||
void put(const InfoHash& key,
|
||||
std::shared_ptr<Value>,
|
||||
DoneCallback cb=nullptr,
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false);
|
||||
void put(const InfoHash& key,
|
||||
const std::shared_ptr<Value>& v,
|
||||
DoneCallbackSimple cb,
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false)
|
||||
{
|
||||
put(key, v, bindDoneCb(cb), created, permanent);
|
||||
}
|
||||
|
||||
void put(const InfoHash& key, Value&& v, DoneCallback cb=nullptr, time_point created=time_point::max()) {
|
||||
put(key, std::make_shared<Value>(std::move(v)), cb, created);
|
||||
void put(const InfoHash& key,
|
||||
Value&& v,
|
||||
DoneCallback cb=nullptr,
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false)
|
||||
{
|
||||
put(key, std::make_shared<Value>(std::move(v)), cb, created, permanent);
|
||||
}
|
||||
void put(const InfoHash& key, Value&& v, DoneCallbackSimple cb, time_point created=time_point::max()) {
|
||||
put(key, std::forward<Value>(v), bindDoneCb(cb), created);
|
||||
void put(const InfoHash& key,
|
||||
Value&& v,
|
||||
DoneCallbackSimple cb,
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false)
|
||||
{
|
||||
put(key, std::forward<Value>(v), bindDoneCb(cb), created, permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +321,7 @@ private:
|
||||
* A single "put" operation data
|
||||
*/
|
||||
struct Announce {
|
||||
bool permanent;
|
||||
std::shared_ptr<Value> value;
|
||||
time_point created;
|
||||
DoneCallback callback;
|
||||
@@ -453,7 +473,7 @@ private:
|
||||
* The values can be filtered by an arbitrary provided filter.
|
||||
*/
|
||||
std::shared_ptr<Search> search(const InfoHash& id, sa_family_t af, GetCallback = nullptr, DoneCallback = nullptr, Value::Filter = Value::AllFilter());
|
||||
void announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value, DoneCallback callback, time_point created=time_point::max());
|
||||
void announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value, DoneCallback callback, time_point created=time_point::max(), bool permanent = false);
|
||||
size_t listenTo(const InfoHash& id, sa_family_t af, GetCallback cb, Value::Filter f = Value::AllFilter());
|
||||
|
||||
void bootstrapSearch(Search& sr);
|
||||
|
||||
@@ -156,16 +156,16 @@ public:
|
||||
void cancelListen(InfoHash h, size_t token);
|
||||
void cancelListen(InfoHash h, std::shared_future<size_t> token);
|
||||
|
||||
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={});
|
||||
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb) {
|
||||
put(hash, value, bindDoneCb(cb));
|
||||
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
|
||||
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
put(hash, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
void put(InfoHash hash, Value&& value, DoneCallback cb={});
|
||||
void put(InfoHash hash, Value&& value, DoneCallbackSimple cb) {
|
||||
put(hash, std::forward<Value>(value), bindDoneCb(cb));
|
||||
void put(InfoHash hash, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
void put(InfoHash hash, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
put(hash, std::forward<Value>(value), bindDoneCb(cb), permanent);
|
||||
}
|
||||
void put(const std::string& key, Value&& value, DoneCallbackSimple cb={});
|
||||
void put(const std::string& key, Value&& value, DoneCallbackSimple cb={}, bool permanent = false);
|
||||
|
||||
void cancelPut(const InfoHash& h, const Value::Id& id);
|
||||
|
||||
|
||||
@@ -101,9 +101,9 @@ public:
|
||||
/**
|
||||
* Will take ownership of the value, sign it using our private key and put it in the DHT.
|
||||
*/
|
||||
void putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallback callback);
|
||||
void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback) {
|
||||
putSigned(hash, std::make_shared<Value>(std::move(v)), callback);
|
||||
void putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallback callback, bool permanent = false);
|
||||
void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putSigned(hash, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,9 +111,9 @@ public:
|
||||
* and put it in the DHT.
|
||||
* The operation will be immediate if the recipient' public key is known (otherwise it will be retrived first).
|
||||
*/
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, std::shared_ptr<Value> val, DoneCallback callback);
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback);
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, std::shared_ptr<Value> val, DoneCallback callback, bool permanent = false);
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,4 +8,4 @@ add_custom_target(python ALL
|
||||
COMMAND python3 setup.py build
|
||||
DEPENDS opendht opendht_cpp.pxd opendht.pyx)
|
||||
|
||||
install(CODE "execute_process(COMMAND python3 setup.py install WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
|
||||
install(CODE "execute_process(COMMAND python3 setup.py install --root=\$ENV{DESTDIR}/ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
|
||||
+1
-1
@@ -13,7 +13,7 @@ clean-local:
|
||||
rm -rf $(builddir)/build $(builddir)/*.so $(PYTHON_INSTALL_RECORD)
|
||||
|
||||
install-exec-local:
|
||||
$(PYTHON) setup.py install --record $(PYTHON_INSTALL_RECORD)
|
||||
$(PYTHON) setup.py install --root=$(DESTDIR)/ --record $(PYTHON_INSTALL_RECORD)
|
||||
rm -rf $(builddir)/build
|
||||
|
||||
if HAVE_PIP
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2015-2016 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2015-2016 Savoir-faire Linux Inc.
|
||||
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
|
||||
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
#
|
||||
|
||||
+2
-3
@@ -3,8 +3,7 @@ SUBDIRS = argon2
|
||||
lib_LTLIBRARIES = libopendht.la
|
||||
|
||||
AM_CPPFLAGS = -I../include/opendht
|
||||
libopendht_la_CXXFLAGS = @CXXFLAGS@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ @GNUTLS_LIBS@ @nettle_LIBS@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ @GnuTLS_LIBS@ @Nettle_LIBS@
|
||||
libopendht_la_LIBADD = ./argon2/libargon2.la
|
||||
|
||||
libopendht_la_SOURCES = \
|
||||
@@ -31,7 +30,7 @@ nobase_include_HEADERS = \
|
||||
../include/opendht/dht.h \
|
||||
../include/opendht/callbacks.h \
|
||||
../include/opendht/node_cache.h \
|
||||
../include/opendht/routing_table.h \
|
||||
../include/opendht/routing_table.h \
|
||||
../include/opendht/network_engine.h \
|
||||
../include/opendht/scheduler.h \
|
||||
../include/opendht/utils.h \
|
||||
|
||||
+80
-59
@@ -163,6 +163,7 @@ private:
|
||||
|
||||
|
||||
struct Dht::SearchNode {
|
||||
SearchNode() : node() {}
|
||||
SearchNode(std::shared_ptr<Node> node) : node(node) {}
|
||||
|
||||
using AnnounceStatusMap = std::map<Value::Id, std::shared_ptr<Request>>;
|
||||
@@ -322,7 +323,7 @@ struct Dht::Search {
|
||||
callbacks.clear();
|
||||
listeners.clear();
|
||||
nodes.clear();
|
||||
nextSearchStep = {};
|
||||
nextSearchStep.reset();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -430,10 +431,10 @@ Dht::trySearchInsert(const std::shared_ptr<Node>& node)
|
||||
auto family = node->getFamily();
|
||||
auto& srs = family == AF_INET ? searches4 : searches6;
|
||||
for (auto& srp : srs) {
|
||||
auto& s = srp.second;
|
||||
if (s->insertNode(node, now)) {
|
||||
auto& s = *srp.second;
|
||||
if (s.insertNode(node, now)) {
|
||||
inserted = true;
|
||||
scheduler.edit(s->nextSearchStep, s->getNextStepTime(types, now));
|
||||
scheduler.edit(s.nextSearchStep, s.getNextStepTime(types, now));
|
||||
}
|
||||
}
|
||||
return inserted;
|
||||
@@ -570,37 +571,53 @@ Dht::Search::removeExpiredNode(time_point now)
|
||||
bool
|
||||
Dht::Search::insertNode(const std::shared_ptr<Node>& snode, time_point now, const Blob& token)
|
||||
{
|
||||
if (expired and nodes.empty())
|
||||
return false;
|
||||
|
||||
auto& node = *snode;
|
||||
const auto& nid = node.id;
|
||||
|
||||
if (node.getFamily() != af) {
|
||||
//DHT_LOG.DEBUG("Attempted to insert node in the wrong family.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fast track for the case where the node is not relevant for this search
|
||||
if (node.isExpired() && nodes.size() >= SEARCH_NODES && id.xorCmp(nid, nodes.back().node->id) > 0)
|
||||
if (node.getFamily() != af)
|
||||
return false;
|
||||
|
||||
bool found = false;
|
||||
auto n = std::find_if(nodes.begin(), nodes.end(), [&](const SearchNode& sn) {
|
||||
if (sn.node == snode) {
|
||||
auto n = nodes.end();
|
||||
while (n != nodes.begin()) {
|
||||
--n;
|
||||
if (n->node == snode) {
|
||||
found = true;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return id.xorCmp(nid, sn.node->id) < 0;
|
||||
});
|
||||
if (id.xorCmp(nid, n->node->id) > 0) {
|
||||
++n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool new_search_node = false;
|
||||
if (!found) {
|
||||
// Be more restricitve if there are too many
|
||||
// good or unknown nodes in this search,
|
||||
unsigned num_bad_nodes = getNumberOfBadNodes();
|
||||
if (nodes.size() - num_bad_nodes >= SEARCH_NODES) {
|
||||
if (node.isExpired() or n == nodes.end())
|
||||
// find if and where to trim excessive nodes
|
||||
auto t = nodes.cend();
|
||||
size_t bad = 0; // number of bad nodes (if search is not expired)
|
||||
bool full {false}; // is the search full (has the maximum nodes)
|
||||
if (expired) {
|
||||
// if the search is expired, trim to SEARCH_NODES nodes
|
||||
if (nodes.size() >= SEARCH_NODES) {
|
||||
full = true;
|
||||
t = nodes.begin() + SEARCH_NODES;
|
||||
}
|
||||
} else {
|
||||
// otherwise, trim to SEARCH_NODES nodes, not counting bad nodes
|
||||
bad = getNumberOfBadNodes();
|
||||
full = nodes.size() - bad >= SEARCH_NODES;
|
||||
while (std::distance(nodes.cbegin(), t) - bad > SEARCH_NODES) {
|
||||
--t;
|
||||
if (t->isBad())
|
||||
bad--;
|
||||
}
|
||||
}
|
||||
|
||||
if (full) {
|
||||
if (t != nodes.cend())
|
||||
nodes.resize(std::distance(nodes.cbegin(), t));
|
||||
if (n >= t)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -608,24 +625,22 @@ Dht::Search::insertNode(const std::shared_ptr<Node>& snode, time_point now, cons
|
||||
if (nodes.empty()) {
|
||||
step_time = TIME_INVALID;
|
||||
}
|
||||
|
||||
n = nodes.insert(n, SearchNode(snode));
|
||||
node.time = now;
|
||||
new_search_node = true;
|
||||
if (node.isExpired()) {
|
||||
if (not expired)
|
||||
bad++;
|
||||
} else if (expired) {
|
||||
bad = nodes.size() - 1;
|
||||
expired = false;
|
||||
}
|
||||
|
||||
// trim good nodes
|
||||
while (nodes.size() - num_bad_nodes > SEARCH_NODES) {
|
||||
if (removeExpiredNode(now))
|
||||
num_bad_nodes--;
|
||||
|
||||
auto to_remove = std::find_if(nodes.rbegin(), nodes.rend(),
|
||||
[](const SearchNode& n) { return not n.isBad(); }
|
||||
);
|
||||
if (to_remove != nodes.rend()) {
|
||||
nodes.erase(std::prev(to_remove.base()));
|
||||
} // else, all nodes are expired.
|
||||
while (nodes.size() - bad > SEARCH_NODES) {
|
||||
if (not expired and nodes.back().isBad())
|
||||
bad--;
|
||||
nodes.pop_back();
|
||||
}
|
||||
expired = false;
|
||||
}
|
||||
if (not token.empty()) {
|
||||
n->candidate = false;
|
||||
@@ -634,6 +649,9 @@ Dht::Search::insertNode(const std::shared_ptr<Node>& snode, time_point now, cons
|
||||
n->token = token;
|
||||
expired = false;
|
||||
}
|
||||
if (new_search_node) {
|
||||
removeExpiredNode(now);
|
||||
}
|
||||
return new_search_node;
|
||||
}
|
||||
|
||||
@@ -652,10 +670,11 @@ Dht::expireSearches()
|
||||
{
|
||||
auto t = scheduler.time() - SEARCH_EXPIRE_TIME;
|
||||
auto expired = [&](std::pair<const InfoHash, std::shared_ptr<Search>>& srp) {
|
||||
auto& sr = srp.second;
|
||||
auto b = sr->callbacks.empty() && sr->announce.empty() && sr->listeners.empty() && sr->step_time < t;
|
||||
auto& sr = *srp.second;
|
||||
auto b = sr.callbacks.empty() && sr.announce.empty() && sr.listeners.empty() && sr.step_time < t;
|
||||
if (b) {
|
||||
DHT_LOG.DEBUG("Removing search %s ", srp.first.toString().c_str());
|
||||
DHT_LOG.DEBUG("Removing search %s", srp.first.toString().c_str());
|
||||
sr.clear();
|
||||
return b;
|
||||
} else { return false; }
|
||||
};
|
||||
@@ -722,17 +741,11 @@ void
|
||||
Dht::searchStep(std::shared_ptr<Search> sr)
|
||||
{
|
||||
if (not sr or sr->expired or sr->done) return;
|
||||
if (sr->nodes.empty() and (sr->af == AF_INET ? buckets : buckets6).isEmpty())
|
||||
return; // wait for connection
|
||||
|
||||
const auto& now = scheduler.time();
|
||||
DHT_LOG.DEBUG("[search %s IPv%c] step (%d requests)", sr->id.toString().c_str(), sr->af == AF_INET ? '4' : '6', sr->currentGetRequests());
|
||||
sr->step_time = now;
|
||||
|
||||
/*
|
||||
* The accurate delay between two refills has not been strongly determined.
|
||||
* TODO: Emprical analysis over refill timeout.
|
||||
*/
|
||||
if (sr->refill_time + Node::NODE_EXPIRE_TIME < now and sr->nodes.size()-sr->getNumberOfBadNodes() < SEARCH_NODES) {
|
||||
if (auto added = sr->refill(sr->af == AF_INET ? buckets : buckets6, now)) {
|
||||
sr->refill_time = now;
|
||||
@@ -815,8 +828,10 @@ Dht::searchStep(std::shared_ptr<Search> sr)
|
||||
a.callback(true, sr->getNodes());
|
||||
a.callback = nullptr;
|
||||
}
|
||||
ait = sr->announce.erase(ait);
|
||||
continue;
|
||||
if (not a.permanent) {
|
||||
ait = sr->announce.erase(ait);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (in) storageStore(sr->id, a.value, a.created);
|
||||
unsigned i = 0;
|
||||
@@ -883,13 +898,17 @@ Dht::searchStep(std::shared_ptr<Search> sr)
|
||||
g.done_cb(false, {});
|
||||
}
|
||||
}
|
||||
if (not sr->nodes.empty()) {
|
||||
{
|
||||
std::vector<DoneCallback> a_cbs;
|
||||
a_cbs.reserve(sr->announce.size());
|
||||
for (const auto& a : sr->announce)
|
||||
if (a.callback)
|
||||
a_cbs.emplace_back(std::move(a.callback));
|
||||
sr->announce.clear();
|
||||
for (auto ait = sr->announce.begin() ; ait != sr->announce.end(); ) {
|
||||
if (ait->callback)
|
||||
a_cbs.emplace_back(std::move(ait->callback));
|
||||
if (not ait->permanent)
|
||||
ait = sr->announce.erase(ait);
|
||||
else
|
||||
ait++;
|
||||
}
|
||||
for (const auto& a : a_cbs)
|
||||
a(false, {});
|
||||
}
|
||||
@@ -1207,7 +1226,8 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback callback, DoneCallba
|
||||
}
|
||||
|
||||
void
|
||||
Dht::announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value, DoneCallback callback, time_point created)
|
||||
Dht::announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value, DoneCallback callback,
|
||||
time_point created, bool permanent)
|
||||
{
|
||||
const auto& now = scheduler.time();
|
||||
if (!value) {
|
||||
@@ -1229,7 +1249,7 @@ Dht::announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value,
|
||||
return a.value->id == value->id;
|
||||
});
|
||||
if (a_sr == sr->announce.end()) {
|
||||
sr->announce.emplace_back(Announce {value, std::min(now, created), callback});
|
||||
sr->announce.emplace_back(Announce {permanent, value, std::min(now, created), callback});
|
||||
for (auto& n : sr->nodes)
|
||||
n.acked[value->id] = {};
|
||||
}
|
||||
@@ -1384,7 +1404,7 @@ Dht::cancelListen(const InfoHash& id, size_t token)
|
||||
}
|
||||
|
||||
void
|
||||
Dht::put(const InfoHash& id, std::shared_ptr<Value> val, DoneCallback callback, time_point created)
|
||||
Dht::put(const InfoHash& id, std::shared_ptr<Value> val, DoneCallback callback, time_point created, bool permanent)
|
||||
{
|
||||
scheduler.syncTime();
|
||||
|
||||
@@ -1412,13 +1432,13 @@ Dht::put(const InfoHash& id, std::shared_ptr<Value> val, DoneCallback callback,
|
||||
*done4 = true;
|
||||
*ok |= ok4;
|
||||
donecb(nodes);
|
||||
}, created);
|
||||
}, created, permanent);
|
||||
announce(id, AF_INET6, val, [=](bool ok6, const std::vector<std::shared_ptr<Node>>& nodes) {
|
||||
DHT_LOG.DEBUG("Announce done IPv6 %d", ok6);
|
||||
*done6 = true;
|
||||
*ok |= ok6;
|
||||
donecb(nodes);
|
||||
}, created);
|
||||
}, created, permanent);
|
||||
}
|
||||
|
||||
struct OpStatus {
|
||||
@@ -2688,7 +2708,8 @@ Dht::onAnnounceDone(const Request&, NetworkEngine::RequestAnswer& answer,
|
||||
a.callback(true, sr->getNodes());
|
||||
a.callback = nullptr;
|
||||
}
|
||||
return true;
|
||||
if (not a.permanent)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}), sr->announce.end());
|
||||
|
||||
+6
-6
@@ -480,30 +480,30 @@ DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> token)
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb)
|
||||
DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
auto sv = std::make_shared<Value>(std::move(value));
|
||||
pending_ops.emplace([=](SecureDht& dht) {
|
||||
dht.put(hash, sv, cb);
|
||||
dht.put(hash, sv, cb, {}, permanent);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb)
|
||||
DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops.emplace([=](SecureDht& dht) {
|
||||
dht.put(hash, value, cb);
|
||||
dht.put(hash, value, cb, {}, permanent);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::put(const std::string& key, Value&& value, DoneCallbackSimple cb)
|
||||
DhtRunner::put(const std::string& key, Value&& value, DoneCallbackSimple cb, bool permanent)
|
||||
{
|
||||
put(InfoHash::get(key), std::forward<Value>(value), cb);
|
||||
put(InfoHash::get(key), std::forward<Value>(value), cb, permanent);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+6
-6
@@ -78,7 +78,7 @@ SecureDht::SecureDht(int s, int s6, SecureDht::Config conf)
|
||||
DHT_LOG.DEBUG("SecureDht: public key announced successfully");
|
||||
else
|
||||
DHT_LOG.ERR("SecureDht: error while announcing public key!");
|
||||
});
|
||||
}, {}, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ SecureDht::listen(const InfoHash& id, GetCallback cb, Value::Filter&& f)
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallback callback)
|
||||
SecureDht::putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
if (val->id == Value::INVALID_ID) {
|
||||
crypto::random_device rdev;
|
||||
@@ -331,16 +331,16 @@ SecureDht::putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallb
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[hash,val,this,callback] (bool /* ok */) {
|
||||
[hash,val,this,callback,permanent] (bool /* ok */) {
|
||||
sign(*val);
|
||||
put(hash, val, callback);
|
||||
put(hash, val, callback, {}, permanent);
|
||||
},
|
||||
Value::IdFilter(val->id)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, std::shared_ptr<Value> val, DoneCallback callback)
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, std::shared_ptr<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
findPublicKey(to, [=](const std::shared_ptr<crypto::PublicKey> pk) {
|
||||
if(!pk || !*pk) {
|
||||
@@ -350,7 +350,7 @@ SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, std::shared_pt
|
||||
}
|
||||
DHT_LOG.WARN("Encrypting data for PK: %s", pk->getId().toString().c_str());
|
||||
try {
|
||||
put(hash, encrypt(*val, *pk), callback);
|
||||
put(hash, encrypt(*val, *pk), callback, {}, permanent);
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.ERR("Error putting encrypted data: %s", e.what());
|
||||
if (callback)
|
||||
|
||||
+3
-3
@@ -3,10 +3,10 @@ bin_PROGRAMS = dhtnode dhtchat dhtscanner
|
||||
AM_CPPFLAGS = -I../include
|
||||
|
||||
dhtnode_SOURCES = dhtnode.cpp
|
||||
dhtnode_LDFLAGS = -lopendht -lreadline -L../src/.libs @GNUTLS_LIBS@
|
||||
dhtnode_LDFLAGS = -lopendht -lreadline -L../src/.libs @GnuTLS_LIBS@
|
||||
|
||||
dhtchat_SOURCES = dhtchat.cpp
|
||||
dhtchat_LDFLAGS = -lopendht -lreadline -L../src/.libs @GNUTLS_LIBS@
|
||||
dhtchat_LDFLAGS = -lopendht -lreadline -L../src/.libs @GnuTLS_LIBS@
|
||||
|
||||
dhtscanner_SOURCES = dhtscanner.cpp
|
||||
dhtscanner_LDFLAGS = -lopendht -lreadline -L../src/.libs @GNUTLS_LIBS@
|
||||
dhtscanner_LDFLAGS = -lopendht -lreadline -L../src/.libs @GnuTLS_LIBS@
|
||||
+1
-1
@@ -29,7 +29,7 @@ extern "C" {
|
||||
using namespace dht;
|
||||
|
||||
void print_usage() {
|
||||
std::cout << "Usage: dhtnode [-p local_port] [-b bootstrap_host:port]" << std::endl << std::endl;
|
||||
std::cout << "Usage: dhtnode [-v[logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b[bootstrap_host[:port]]]" << std::endl << std::endl;
|
||||
std::cout << "dhtnode, a simple OpenDHT command line node runner." << std::endl;
|
||||
std::cout << "Report bugs to: http://opendht.net" << std::endl;
|
||||
}
|
||||
|
||||
+7
-18
@@ -153,7 +153,7 @@ static const constexpr struct option long_options[] = {
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"bootstrap", optional_argument, nullptr, 'b'},
|
||||
{"identity", no_argument , nullptr, 'i'},
|
||||
{"verbose", no_argument , nullptr, 'v'},
|
||||
{"verbose", optional_argument, nullptr, 'v'},
|
||||
{"daemonize", no_argument , nullptr, 'd'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
@@ -162,14 +162,14 @@ dht_params
|
||||
parseArgs(int argc, char **argv) {
|
||||
dht_params params;
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, ":hidv:p:b:", long_options, nullptr)) != -1) {
|
||||
while ((opt = getopt_long(argc, argv, "hidv::p:n:b::", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case 'p': {
|
||||
int port_arg = atoi(optarg);
|
||||
if (port_arg >= 0 && port_arg < 0x10000)
|
||||
params.port = port_arg;
|
||||
else
|
||||
std::cout << "Invalid port: " << port_arg << std::endl;
|
||||
std::cerr << "Invalid port: " << port_arg << std::endl;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
@@ -180,8 +180,7 @@ parseArgs(int argc, char **argv) {
|
||||
ss << DHT_DEFAULT_PORT;
|
||||
params.bootstrap.second = ss.str();
|
||||
}
|
||||
}
|
||||
else
|
||||
} else
|
||||
params.is_bootstrap_node = true;
|
||||
break;
|
||||
case 'h':
|
||||
@@ -198,19 +197,9 @@ parseArgs(int argc, char **argv) {
|
||||
case 'd':
|
||||
params.daemonize = true;
|
||||
break;
|
||||
case ':':
|
||||
switch (optopt) {
|
||||
case 'b':
|
||||
params.is_bootstrap_node = true;
|
||||
break;
|
||||
case 'v':
|
||||
params.log = true;
|
||||
break;
|
||||
default:
|
||||
std::cout << "option requires an argument -- '" << optopt << '\'' << std::endl;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
std::cerr << "unrecognized option -- '" << static_cast<char>(optopt) << '\'' << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user