Compare commits

..
34 Commits
Author SHA1 Message Date
Simon Désaulniers beca53a669 version 0.6.3 2016-07-29 12:30:02 -04:00
Simon Désaulniers e4c7b36a6d autotools: versionning consistent with CMake 2016-07-25 17:56:43 -04:00
Adrien Béraud 8f9cf1b502 cmake: build versioned shared library 2016-07-25 17:56:43 -04:00
Adrien Béraud dc17820076 Clarify GPLv3 "or any later version" licence 2016-07-25 17:56:43 -04:00
Simon Désaulniers f29c5dd786 add readme help text for benchmark 2016-07-25 17:56:42 -04:00
Adrien Béraud 61ef2eda2f pkgconfig: add private dependencies 2016-07-25 17:56:42 -04:00
Adrien Béraud 00676c163b dht: add code documentation 2016-07-25 17:56:42 -04:00
Adrien Béraud fba2f0a358 autotools: disable doxygen by default 2016-07-25 17:56:42 -04:00
Adrien Béraud 6cd7fdb830 add network id to distinguish different networks 2016-07-25 17:56:40 -04:00
Adrien Béraud 426c6b6e6d value: add common crypto ops 2016-07-25 17:55:16 -04:00
Adrien Béraud 7b1c5c9525 infohash: merge Windows includes 2016-07-25 17:29:48 -04:00
Andreas Traczyk c8fd11d0d0 Update README.md 2016-07-25 17:29:45 -04:00
Andreas Traczyk 5e90cf3dc7 microsoft compiler support 2016-07-25 17:15:28 -04:00
Simon Désaulniers 01fbe0fd31 dht: make main store a vector<unique_ptr<Storage>>
Since the elements inside are going to be moved constantly during the life of
the node, this design is better. Also, it works around a crash when the store is
resized (elements inside moved) at some point (always happenned the 3rd time)
for some reason. This bug was known when compiled with LLVM >7.3.0 (>clang-703.0.31).
2016-07-22 16:27:10 -04:00
Simon Désaulniers 502776aca3 version 0.6.2 2016-07-19 13:54:16 -04:00
Simon Désaulniers 7b4eac558a doc: clarify dhtnode usage 2016-07-19 13:47:01 -04:00
zorun 8f8905dfd1 doc: Fix install path of man page (#90)
Man pages go in /usr/share/man

  http://www.pathname.com/fhs/pub/fhs-2.3.html#USRSHAREMANMANUALPAGES
2016-07-18 18:13:45 -04:00
Simon Désaulniers 64b4d2fa4a doc: add missing CMakeLists.txt 2016-07-18 18:13:45 -04:00
Simon Désaulniers 574d1934c9 tools: specify optional arg syntax -o[ARG] 2016-07-18 18:13:45 -04:00
Simon Désaulniers b3ad031a97 build-tools: distribute dhtnode.1 manpage 2016-07-18 18:13:43 -04:00
Simon Désaulniers a0b9a1986c doc: fix typos in dhtnode manpage 2016-07-18 18:12:52 -04:00
Simon Désaulniers 97efe5b791 dhtnode: manpage and add all options in help text 2016-07-18 18:12:52 -04:00
Simon Désaulniers b6c1b6fdd2 dhtnode: fix getopt optional arg parsing 2016-07-18 18:12:49 -04:00
Adrien Béraud 7e2ae46870 dht: clear search before expiring it 2016-07-18 18:11:24 -04:00
Adrien Béraud ba5d60cebe autotools: handle case where DESTDIR is empty 2016-07-18 18:11:24 -04:00
Adrien Béraud 0dc158047a autotools: cleanup 2016-07-18 18:11:24 -04:00
Simon Désaulniers 1ab615096c dht: handle search expired before permanent put 2016-07-18 18:11:24 -04:00
Simon Désaulniers f8d26e8f9f securedht: permanent put of a certificate. 2016-07-18 18:11:24 -04:00
Simon Désaulniers c0b4bf8a46 dht,api: enable optional permanent put on dht
A permanent put is going to be executed once and every time the data expires on
each SearchNode.
2016-07-18 18:11:24 -04:00
Simon Désaulniers 8f26e30021 revert attempt to avoid securedht cert put fail 2016-07-18 18:11:23 -04:00
Simon Désaulniers c1e86b48f1 Revert "dht: wait for connection before running searches"
This reverts commit bd08506146.
2016-07-18 18:11:23 -04:00
Adrien Béraud b4b39f52dc dht: new insertNode algorithm 2016-07-18 18:11:23 -04:00
Simon Désaulniers c7a6e11a24 enable python make DESTDIR=$DIR install support 2016-07-18 18:11:23 -04:00
Simon Désaulniers d95eeb31e3 cmake: pass $DESTDIR environnement var to setup.py 2016-07-18 18:11:18 -04:00
26 changed files with 323 additions and 122 deletions

No files matched your search

+2 -1
View File
@@ -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.3)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -132,6 +132,7 @@ endif ()
if (OPENDHT_TOOLS)
add_subdirectory(tools)
endif ()
add_subdirectory(doc)
if (OPENDHT_PYTHON)
add_subdirectory(python)
-2
View File
@@ -10,9 +10,7 @@ if USE_CYTHON
SUBDIRS += python
endif
if HAVE_DOXYGEN
SUBDIRS += doc
endif
ACLOCAL_AMFLAGS = -I m4
+5 -1
View File
@@ -97,7 +97,11 @@ Licence
-
Copyright (C) 2014-2016 Savoir-faire Linux Inc.
Licenced under the GNU General Public License version 3 (see COPYING for the full licence).
OpenDHT 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.
See COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html for the full GPLv3 licence.
This project is independent from another project called OpenDHT (Sean Rhea. Ph.D. Thesis, 2005), now extinct.
+13 -2
View File
@@ -1,10 +1,21 @@
AC_INIT(opendht, 0.6.1)
dnl define macros
m4_define([opendht_major_version], 0)
m4_define([opendht_minor_version], 6)
m4_define([opendht_patch_version], 3)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
AC_INIT(opendht, [opendht_version])
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AC_SUBST(OPENDHT_MAJOR_VERSION, opendht_major_version)
AC_SUBST(OPENDHT_MINOR_VERSION, opendht_minor_version)
AC_SUBST(OPENDHT_PATCH_VERSION, opendht_patch_version)
AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Build in debug mode, adds stricter warnings, disables optimization]))
AS_IF([test "x$enable_debug" = "xyes"],
[CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -O0"],
@@ -88,7 +99,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], [
+3
View File
@@ -0,0 +1,3 @@
if (OPENDHT_TOOLS)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dhtnode.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1)
endif ()
+4
View File
@@ -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
+85
View File
@@ -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>
+21 -2
View File
@@ -30,23 +30,44 @@ namespace dht {
struct Node;
/**
* Current status of a DHT node.
*/
enum class NodeStatus {
Disconnected, // 0 nodes
Connecting, // 1+ nodes
Connected // 1+ good nodes
};
/**
* Dht configuration.
*/
struct Config {
/** DHT node ID */
InfoHash node_id;
/**
* DHT network ID. A node will only talk with other nodes having
* the same network ID.
* Network ID 0 (default) represents the main public network.
*/
NetId network;
/** For testing purposes only, enables bootstrap mode */
bool is_bootstrap;
};
/**
* SecureDht configuration.
*/
struct SecureDhtConfig
{
Config node_config;
crypto::Identity id;
};
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
using ValuesExport = std::pair<InfoHash, Blob>;
using GetCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>& values)>;
@@ -57,8 +78,6 @@ using CertificateStoreQuery = std::function<std::vector<std::shared_ptr<crypto::
typedef bool (*GetCallbackRaw)(std::shared_ptr<Value>, void *user_data);
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
GetCallbackSimple bindGetCb(GetCallbackRaw raw_cb, void* user_data);
GetCallback bindGetCb(GetCallbackSimple cb);
+1 -1
View File
@@ -392,7 +392,7 @@ private:
RoutingTable buckets {};
RoutingTable buckets6 {};
std::vector<Storage> store;
std::vector<std::unique_ptr<Storage>> store;
size_t total_values {0};
size_t total_store_size {0};
size_t max_store_size {DEFAULT_STORAGE_LIMIT};
+3 -2
View File
@@ -268,12 +268,13 @@ public:
* @param threaded: If false, ::loop() must be called periodically. Otherwise a thread is launched.
* @param cb: Optional callback to receive general state information.
*/
void run(in_port_t port, const crypto::Identity identity, bool threaded = false, bool is_bootstrap = false) {
void run(in_port_t port, const crypto::Identity identity, bool threaded = false, NetId network = 0) {
run(port, {
/*.dht_config = */{
/*.node_config = */{
/*.node_id = */{},
/*.is_bootstrap = */is_bootstrap
/*.network = */network,
/*.is_bootstrap = */false
},
/*.id = */identity
},
+3 -2
View File
@@ -256,7 +256,7 @@ public:
using RequestExpiredCb = std::function<void(const Request&, bool)>;
NetworkEngine(Logger& log, Scheduler& scheduler) : myid(zeroes), DHT_LOG(log), scheduler(scheduler) {}
NetworkEngine(InfoHash& myid, int s, int s6, Logger& log, Scheduler& scheduler,
NetworkEngine(InfoHash& myid, NetId net, int s, int s6, Logger& log, Scheduler& scheduler,
decltype(NetworkEngine::onError) onError,
decltype(NetworkEngine::onNewNode) onNewNode,
decltype(NetworkEngine::onReportedAddr) onReportedAddr,
@@ -266,7 +266,7 @@ public:
decltype(NetworkEngine::onListen) onListen,
decltype(NetworkEngine::onAnnounce) onAnnounce) :
onError(onError), onNewNode(onNewNode), onReportedAddr(onReportedAddr), onPing(onPing), onFindNode(onFindNode),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), myid(myid),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), myid(myid), network(net),
dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{
transaction_id = std::uniform_int_distribution<decltype(transaction_id)>{1}(rd_device);
@@ -376,6 +376,7 @@ private:
/* DHT info */
const InfoHash& myid;
const NetId network {0};
const int dht_socket {-1};
const int dht_socket6 {-1};
const Logger& DHT_LOG;
+2
View File
@@ -23,6 +23,8 @@
namespace dht {
static constexpr unsigned TARGET_NODES {8};
struct Bucket {
Bucket() : cached() {}
Bucket(sa_family_t af, const InfoHash& f = {}, time_point t = time_point::min())
+3 -6
View File
@@ -126,16 +126,13 @@ public:
Value decrypt(const Value& v);
void findCertificate(const InfoHash& node, std::function<void(const std::shared_ptr<crypto::Certificate>)> cb);
void findPublicKey(const InfoHash& node, std::function<void(const std::shared_ptr<crypto::PublicKey>)> cb);
void findPublicKey(const InfoHash& node, std::function<void(const std::shared_ptr<const crypto::PublicKey>)> cb);
const std::shared_ptr<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
void registerCertificate(std::shared_ptr<crypto::Certificate>& cert);
const std::shared_ptr<crypto::Certificate> getCertificate(const InfoHash& node) const;
const std::shared_ptr<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
const std::shared_ptr<const crypto::PublicKey> getPublicKey(const InfoHash& node) const;
/**
* Allows to set a custom callback called by the library to find a locally-stored certificate.
@@ -161,7 +158,7 @@ private:
// our certificate cache
std::map<InfoHash, std::shared_ptr<crypto::Certificate>> nodesCertificates_ {};
std::map<InfoHash, std::shared_ptr<crypto::PublicKey>> nodesPubKeys_ {};
std::map<InfoHash, std::shared_ptr<const crypto::PublicKey>> nodesPubKeys_ {};
std::uniform_int_distribution<Value::Id> rand_id {};
};
+1 -2
View File
@@ -40,9 +40,8 @@
namespace dht {
static constexpr unsigned TARGET_NODES {8};
using Address = std::pair<sockaddr_storage, socklen_t>;
using NetId = uint32_t;
using want_t = int_fast8_t;
std::string print_addr(const sockaddr* sa, socklen_t slen);
+3 -3
View File
@@ -256,7 +256,7 @@ struct Value
void sign(const crypto::PrivateKey& key) {
if (isEncrypted())
throw DhtException("Can't sign encrypted data.");
owner = std::make_shared<crypto::PublicKey>(key.getPublicKey());
owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
signature = key.sign(getToSign());
}
@@ -273,7 +273,7 @@ struct Value
}
/**
*
* Sign the value with from and returns the encrypted version for to.
*/
Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to) {
if (isEncrypted())
@@ -429,7 +429,7 @@ struct Value
/**
* Public key of the signer.
*/
std::shared_ptr<crypto::PublicKey> owner {};
std::shared_ptr<const crypto::PublicKey> owner {};
/**
* Hash of the recipient (optional).
+45
View File
@@ -0,0 +1,45 @@
# Benchmark
The `benchmark.py` script is used for testing OpenDHT in various cases. If you
run `benchmark.py --help`, you should find the following text:
optional arguments:
-h, --help show this help message and exit
--performance Launches performance benchmark test. Available args
for "-t" are: gets.
--data-persistence Launches data persistence benchmark test. Available
args for "-t" are: delete, replace, mult_time.
Available args for "-o" are : dump_str_log,
keep_alive, trigger, traffic_plot, op_plot. Use "-m"
to specify the number of producers on the DHT.Use "-e"
to specify the number of values to put on the DHT.
These options specify the feature to be tested. Each feature has its own tests.
You specify the test by using `-t` flag (see `benchmark.py --help` for full
help).
## Python dependencies
- pyroute2 >=0.3.14
- matplotlib
- GeoIP (used by `scanner.py` for drawing map of the world)
- ipaddress
- netifaces
- networkx
- numpy
## Usage
Before running the script, you have to build and install OpenDHT and its cython
wrapper (`cython3` has to be installed) on the system so that it can be found by
the benchmark script.
$ cd $OPENDHT_SRC_DIR
$ ./autogen.sh
$ ./configure
$ make && sudo make install
Then, you can use the script like so:
$ cd $OPENDHT_SRC_DIR/python/tools/
$ python3 benchmark.py --performance -t gets -n 2048
+10 -13
View File
@@ -208,23 +208,23 @@ class DhtFeatureTest(FeatureTest):
FeatureTest.lock.notify()
def _dhtPut(self, producer, _hash, *values):
with FeatureTest.lock:
for val in values:
vstr = val.__str__()[:100]
DhtNetwork.log('[PUT]:', _hash.toString(), '->', vstr + ("..." if len(vstr) > 100 else ""))
FeatureTest.done += 1
for val in values:
with FeatureTest.lock:
vstr = val.__str__()[:100]
DhtNetwork.log('[PUT]:', _hash.toString(), '->', vstr + ("..." if len(vstr) > 100 else ""))
FeatureTest.done += 1
while FeatureTest.done > 0:
producer.put(_hash, val, DhtFeatureTest.putDoneCb)
while FeatureTest.done > 0:
FeatureTest.lock.wait()
FeatureTest.lock.wait()
def _dhtGet(self, consumer, _hash):
DhtFeatureTest.foreignValues = []
DhtFeatureTest.foreignNodes = []
with FeatureTest.lock:
FeatureTest.done += 1
DhtNetwork.log('[GET]:', _hash.toString())
consumer.get(_hash, DhtFeatureTest.getcb, DhtFeatureTest.getDoneCb)
while FeatureTest.done > 0:
DhtNetwork.log('[GET]:', _hash.toString())
consumer.get(_hash, DhtFeatureTest.getcb, DhtFeatureTest.getDoneCb)
FeatureTest.lock.wait()
def _gottaGetThemAllPokeNodes(self, consumer, hashes, nodes=None):
@@ -356,7 +356,7 @@ class PersistenceTest(DhtFeatureTest):
bootstrap = self.bootstrap
# Value representing an ICE packet. Each ICE packet is around 1KB.
VALUE_SIZE = 1024
NUM_VALUES = self._num_values/wb.node_num if self._num_values else 5
NUM_VALUES = self._num_values/wb.node_num if self._num_values else 50
nr_values = NUM_VALUES * wb.node_num
nr_nodes = wb.node_num
nr_nodes_cv = threading.Condition()
@@ -365,11 +365,8 @@ class PersistenceTest(DhtFeatureTest):
hashes = [random_hash() for _ in range(wb.node_num)]
# initial set of values
i = 0
for h in hashes:
self._dhtPut(bootstrap.front(), h, *[Value(v) for v in values])
print("at: ", i)
i += 1
def normalBehavior(do, t, log=None):
nonlocal nr_values
+1 -1
View File
@@ -3,7 +3,7 @@ SUBDIRS = argon2
lib_LTLIBRARIES = libopendht.la
AM_CPPFLAGS = -I../include/opendht
libopendht_la_LDFLAGS = @LDFLAGS@ @GnuTLS_LIBS@ @Nettle_LIBS@
libopendht_la_LDFLAGS = @LDFLAGS@ @GnuTLS_LIBS@ @Nettle_LIBS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
libopendht_la_LIBADD = ./argon2/libargon2.la
libopendht_la_SOURCES = \
+43 -43
View File
@@ -396,7 +396,7 @@ Dht::shutdown(ShutdownCallback cb) {
};
for (const auto& str : store) {
*remaining += maintainStorage(str.id, true, str_donecb);
*remaining += maintainStorage(str->id, true, str_donecb);
}
DHT_LOG.WARN("Shuting down node: %u ops remaining.", *remaining);
if (!*remaining && cb) { cb(); }
@@ -1370,12 +1370,12 @@ Dht::listen(const InfoHash& id, GetCallback cb, Value::Filter&& f)
auto st = findStorage(id);
size_t tokenlocal = 0;
if (st == store.end() && store.size() < MAX_HASHES) {
store.emplace_back(id, scheduler.time());
store.emplace_back(new Storage(id, scheduler.time()));
st = std::prev(store.end());
}
if (st != store.end()) {
if (not st->empty()) {
std::vector<std::shared_ptr<Value>> newvals = st->get(f);
if (not (*st)->empty()) {
std::vector<std::shared_ptr<Value>> newvals = (*st)->get(f);
if (not newvals.empty()) {
if (!cb(newvals))
return 0;
@@ -1386,8 +1386,8 @@ Dht::listen(const InfoHash& id, GetCallback cb, Value::Filter&& f)
}
}
}
tokenlocal = ++st->listener_token;
st->local_listeners.emplace(tokenlocal, LocalListener{f, gcb});
tokenlocal = ++(*st)->listener_token;
(*st)->local_listeners.emplace(tokenlocal, LocalListener{f, gcb});
}
auto token4 = Dht::listenTo(id, AF_INET, gcb, f);
@@ -1412,7 +1412,7 @@ Dht::cancelListen(const InfoHash& id, size_t token)
auto st = findStorage(id);
auto tokenlocal = std::get<0>(it->second);
if (st != store.end() && tokenlocal)
st->local_listeners.erase(tokenlocal);
(*st)->local_listeners.erase(tokenlocal);
auto searches_cancel_listen = [&](std::map<InfoHash, std::shared_ptr<Search>> srs) {
for (auto& sp : srs) {
@@ -1545,7 +1545,7 @@ Dht::getLocal(const InfoHash& id, Value::Filter f) const
{
auto s = findStorage(id);
if (s == store.end()) return {};
return s->get(f);
return (*s)->get(f);
}
std::shared_ptr<Value>
@@ -1553,7 +1553,7 @@ Dht::getLocalById(const InfoHash& id, Value::Id vid) const
{
auto s = findStorage(id);
if (s != store.end())
return s->getById(vid);
return (*s)->getById(vid);
return {};
}
@@ -1626,15 +1626,15 @@ Dht::cancelPut(const InfoHash& id, const Value::Id& vid)
decltype(Dht::store)::iterator
Dht::findStorage(const InfoHash& id)
{
return std::find_if(store.begin(), store.end(), [&](const Storage& st) {
return st.id == id;
return std::find_if(store.begin(), store.end(), [&](const std::unique_ptr<Storage>& st) {
return st->id == id;
});
}
decltype(Dht::store)::const_iterator
Dht::findStorage(const InfoHash& id) const
{
return std::find_if(store.cbegin(), store.cend(), [&](const Storage& st) {
return st.id == id;
return std::find_if(store.cbegin(), store.cend(), [&](const std::unique_ptr<Storage>& st) {
return st->id == id;
});
}
@@ -1674,15 +1674,15 @@ Dht::storageStore(const InfoHash& id, const std::shared_ptr<Value>& value, time_
if (st == store.end()) {
if (store.size() >= MAX_HASHES)
return false;
store.emplace_back(id, now);
store.emplace_back(new Storage(id, now));
st = std::prev(store.end());
}
auto store = st->store(value, created, max_store_size - total_store_size);
auto store = (*st)->store(value, created, max_store_size - total_store_size);
if (std::get<0>(store)) {
total_store_size += std::get<1>(store);
total_values += std::get<2>(store);
storageChanged(*st, *std::get<0>(store));
storageChanged(*(*st), *std::get<0>(store));
}
return std::get<0>(store);
}
@@ -1731,12 +1731,12 @@ Dht::storageAddListener(const InfoHash& id, const std::shared_ptr<Node>& node, s
if (st == store.end()) {
if (store.size() >= MAX_HASHES)
return;
store.emplace_back(id, now);
store.emplace_back(new Storage(id, now));
st = std::prev(store.end());
}
auto l = st->listeners.find(node);
if (l == st->listeners.end()) {
const auto& stvalues = st->getValues();
auto l = (*st)->listeners.find(node);
if (l == (*st)->listeners.end()) {
const auto& stvalues = (*st)->getValues();
if (not stvalues.empty()) {
std::vector<std::shared_ptr<Value>> values(stvalues.size());
std::transform(stvalues.begin(), stvalues.end(), values.begin(), [=](const ValueStorage& vs) { return vs.data; });
@@ -1745,7 +1745,7 @@ Dht::storageAddListener(const InfoHash& id, const std::shared_ptr<Node>& node, s
buckets.findClosestNodes(id, now, TARGET_NODES), buckets6.findClosestNodes(id, now, TARGET_NODES),
values);
}
st->listeners.emplace(node, Listener {rid, now});
(*st)->listeners.emplace(node, Listener {rid, now});
}
else
l->second.refresh(rid, now);
@@ -1757,21 +1757,21 @@ Dht::expireStorage()
const auto& now = scheduler.time();
auto i = store.begin();
while (i != store.end()) {
for (auto l = i->listeners.cbegin(); l != i->listeners.cend();){
for (auto l = (*i)->listeners.cbegin(); l != (*i)->listeners.cend();){
bool expired = l->second.time + Node::NODE_EXPIRE_TIME < now;
if (expired) {
DHT_LOG.DEBUG("Discarding expired listener %s", l->first->id.toString().c_str());
i->listeners.erase(l++);
(*i)->listeners.erase(l++);
} else
++l;
}
auto stats = i->expire(types, now);
auto stats = (*i)->expire(types, now);
total_store_size += stats.first;
total_values += stats.second;
if (i->empty() && i->listeners.empty() && i->local_listeners.empty()) {
DHT_LOG.DEBUG("Discarding expired value %s", i->id.toString().c_str());
if ((*i)->empty() && (*i)->listeners.empty() && (*i)->local_listeners.empty()) {
DHT_LOG.DEBUG("Discarding expired value %s", (*i)->id.toString().c_str());
i = store.erase(i);
}
else
@@ -2052,10 +2052,10 @@ Dht::getStorageLog() const
using namespace std::chrono;
std::stringstream out;
for (const auto& st : store) {
out << "Storage " << st.id << " " << st.listeners.size() << " list., " << st.valueCount() << " values (" << st.totalSize() << " bytes)" << std::endl;
if (not st.local_listeners.empty())
out << " " << st.local_listeners.size() << " local listeners" << std::endl;
for (const auto& l : st.listeners) {
out << "Storage " << (*st).id << " " << (*st).listeners.size() << " list., " << (*st).valueCount() << " values (" << (*st).totalSize() << " bytes)" << std::endl;
if (not (*st).local_listeners.empty())
out << " " << (*st).local_listeners.size() << " local listeners" << std::endl;
for (const auto& l : (*st).listeners) {
out << " " << "Listener " << l.first->toString();
auto since = duration_cast<seconds>(now - l.second.time);
auto expires = duration_cast<seconds>(l.second.time + Node::NODE_EXPIRE_TIME - now);
@@ -2102,7 +2102,7 @@ Dht::Dht() : store(), network_engine(DHT_LOG, scheduler) {}
Dht::Dht(int s, int s6, Config config)
: myid(config.node_id), is_bootstrap(config.is_bootstrap), store(),
network_engine(myid, s, s6, DHT_LOG, scheduler,
network_engine(myid, config.network, s, s6, DHT_LOG, scheduler,
std::bind(&Dht::onError, this, _1, _2),
std::bind(&Dht::onNewNode, this, _1, _2),
std::bind(&Dht::onReportedAddr, this, _1, _2, _3),
@@ -2238,11 +2238,11 @@ Dht::dataPersistence() {
const auto& now = scheduler.time();
auto storage_maintenance_time = time_point::max();
for (auto &str : store) {
if (now > str.maintenance_time) {
maintainStorage(str.id);
str.maintenance_time = now + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME;
if (now > str->maintenance_time) {
maintainStorage(str->id);
str->maintenance_time = now + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME;
}
storage_maintenance_time = std::min(storage_maintenance_time, str.maintenance_time);
storage_maintenance_time = std::min(storage_maintenance_time, str->maintenance_time);
}
scheduler.add(storage_maintenance_time, std::bind(&Dht::dataPersistence, this));
}
@@ -2259,7 +2259,7 @@ Dht::maintainStorage(InfoHash id, bool force, DoneCallback donecb) {
auto nodes = buckets.findClosestNodes(id, now);
if (!nodes.empty()) {
if (force || id.xorCmp(nodes.back()->id, myid) < 0) {
for (auto &value : local_storage->getValues()) {
for (auto &value : (*local_storage)->getValues()) {
const auto& vt = getType(value.data->type);
if (force || value.time + vt.expiration > now + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME) {
// gotta put that value there
@@ -2275,7 +2275,7 @@ Dht::maintainStorage(InfoHash id, bool force, DoneCallback donecb) {
auto nodes6 = buckets6.findClosestNodes(id, now);
if (!nodes6.empty()) {
if (force || id.xorCmp(nodes6.back()->id, myid) < 0) {
for (auto &value : local_storage->getValues()) {
for (auto &value : (*local_storage)->getValues()) {
const auto& vt = getType(value.data->type);
if (force || value.time + vt.expiration > now + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME) {
// gotta put that value there
@@ -2290,7 +2290,7 @@ Dht::maintainStorage(InfoHash id, bool force, DoneCallback donecb) {
if (not want4 and not want6) {
DHT_LOG.DEBUG("Discarding storage values %s", id.toString().c_str());
local_storage->clear();
(*local_storage)->clear();
}
return announce_per_af;
@@ -2383,12 +2383,12 @@ Dht::exportValues() const
e.reserve(store.size());
for (const auto& h : store) {
ValuesExport ve;
ve.first = h.id;
ve.first = h->id;
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_array(h.getValues().size());
for (const auto& v : h.getValues()) {
pk.pack_array(h->getValues().size());
for (const auto& v : h->getValues()) {
pk.pack_array(2);
pk.pack(v.time.time_since_epoch().count());
v.data->msgpack_pack(pk);
@@ -2551,8 +2551,8 @@ Dht::onGetValues(std::shared_ptr<Node> node, InfoHash& hash, want_t)
answer.ntoken = makeToken((sockaddr*)&node->ss, false);
answer.nodes4 = buckets.findClosestNodes(hash, now, TARGET_NODES);
answer.nodes6 = buckets6.findClosestNodes(hash, now, TARGET_NODES);
if (st != store.end() && not st->empty()) {
auto values = st->getValues();
if (st != store.end() && not (*st)->empty()) {
auto values = (*st)->getValues();
answer.values.resize(values.size());
std::transform(values.begin(), values.end(), answer.values.begin(), [](const ValueStorage& vs) {
return vs.data;
+53 -14
View File
@@ -49,6 +49,7 @@ static const uint8_t v4prefix[16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0
};
constexpr unsigned SEND_NODES {8};
enum class MessageType {
Error = 0,
@@ -63,6 +64,7 @@ enum class MessageType {
struct ParsedMessage {
MessageType type;
InfoHash id; /* the id of the sender */
NetId network {0}; /* network id */
InfoHash info_hash; /* hash for which values are requested */
InfoHash target; /* target id around which to find nodes */
NetworkEngine::TransId tid; /* transaction id */
@@ -293,6 +295,11 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, const sockaddr*
return;
}
if (msg.network != network) {
DHT_LOG.DEBUG("Received message from other network %u.", msg.network);
return;
}
if (msg.id == myid || msg.id == zeroes) {
DHT_LOG.DEBUG("Received message from self.");
return;
@@ -451,9 +458,10 @@ packToken(msgpack::packer<msgpack::sbuffer>& pk, Blob token)
}
void
insertAddr(msgpack::packer<msgpack::sbuffer>& pk, const sockaddr *sa, socklen_t)
insertAddr(msgpack::packer<msgpack::sbuffer>& pk, const sockaddr *sa, socklen_t sa_len)
{
size_t addr_len = (sa->sa_family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr);
size_t addr_len = std::min<size_t>(sa_len,
(sa->sa_family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr));
void* addr_ptr = (sa->sa_family == AF_INET) ? (void*)&((sockaddr_in*)sa)->sin_addr
: (void*)&((sockaddr_in6*)sa)->sin6_addr;
pk.pack("sa");
@@ -485,7 +493,7 @@ NetworkEngine::sendPing(std::shared_ptr<Node> node, RequestCb on_done, RequestEx
auto tid = TransId {TransPrefix::PING, getNewTid()};
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(1);
pk.pack(std::string("id")); pk.pack(myid);
@@ -495,6 +503,9 @@ NetworkEngine::sendPing(std::shared_ptr<Node> node, RequestCb on_done, RequestEx
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
Blob b {buffer.data(), buffer.data() + buffer.size()};
std::shared_ptr<Request> req(new Request {tid.getTid(), node, std::move(b),
@@ -519,7 +530,7 @@ void
NetworkEngine::sendPong(const sockaddr* sa, socklen_t salen, TransId tid) {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
@@ -529,6 +540,9 @@ NetworkEngine::sendPong(const sockaddr* sa, socklen_t salen, TransId tid) {
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, sa, salen);
}
@@ -539,7 +553,7 @@ NetworkEngine::sendFindNode(std::shared_ptr<Node> n, const InfoHash& target, wan
auto tid = TransId {TransPrefix::FIND_NODE, getNewTid()};
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(2 + (want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
@@ -556,7 +570,9 @@ NetworkEngine::sendFindNode(std::shared_ptr<Node> n, const InfoHash& target, wan
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
Blob b {buffer.data(), buffer.data() + buffer.size()};
std::shared_ptr<Request> req(new Request {tid.getTid(), n, std::move(b),
@@ -583,7 +599,7 @@ NetworkEngine::sendGetValues(std::shared_ptr<Node> n, const InfoHash& info_hash,
auto tid = TransId {TransPrefix::GET_VALUES, getNewTid()};
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(2 + (want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
@@ -600,6 +616,9 @@ NetworkEngine::sendGetValues(std::shared_ptr<Node> n, const InfoHash& info_hash,
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
Blob b {buffer.data(), buffer.data() + buffer.size()};
std::shared_ptr<Request> req(new Request {tid.getTid(), n, std::move(b),
@@ -664,7 +683,7 @@ NetworkEngine::sendNodesValues(const sockaddr* sa, socklen_t salen, TransId tid,
const std::vector<std::shared_ptr<Value>>& st, const Blob& token) {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r"));
pk.pack_map(2 + (not st.empty()?1:0) + (nodes.size()>0?1:0) + (nodes6.size()>0?1:0) + (not token.empty()?1:0));
@@ -715,6 +734,9 @@ NetworkEngine::sendNodesValues(const sockaddr* sa, socklen_t salen, TransId tid,
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, sa, salen);
}
@@ -725,7 +747,7 @@ NetworkEngine::bufferNodes(sa_family_t af, const InfoHash& id, std::vector<std::
std::sort(nodes.begin(), nodes.end(), [&](const std::shared_ptr<Node>& a, const std::shared_ptr<Node>& b){
return id.xorCmp(a->id, b->id) < 0;
});
size_t nnode = std::min<size_t>(TARGET_NODES, nodes.size());
size_t nnode = std::min<size_t>(SEND_NODES, nodes.size());
Blob bnodes;
if (af == AF_INET) {
bnodes.resize(NODE4_INFO_BUF_LEN * nnode);
@@ -777,7 +799,7 @@ NetworkEngine::sendListen(std::shared_ptr<Node> n, const InfoHash& infohash, con
auto tid = TransId {TransPrefix::LISTEN, getNewTid()};
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(3);
pk.pack(std::string("id")); pk.pack(myid);
@@ -789,7 +811,9 @@ NetworkEngine::sendListen(std::shared_ptr<Node> n, const InfoHash& infohash, con
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
Blob b {buffer.data(), buffer.data() + buffer.size()};
std::shared_ptr<Request> req(new Request {tid.getTid(), n, std::move(b),
@@ -812,7 +836,7 @@ void
NetworkEngine::sendListenConfirmation(const sockaddr* sa, socklen_t salen, TransId tid) {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
@@ -822,6 +846,9 @@ NetworkEngine::sendListenConfirmation(const sockaddr* sa, socklen_t salen, Trans
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, sa, salen);
}
@@ -832,7 +859,7 @@ NetworkEngine::sendAnnounceValue(std::shared_ptr<Node> n, const InfoHash& infoha
auto tid = TransId {TransPrefix::ANNOUNCE_VALUES, getNewTid()};
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map((created < scheduler.time() ? 5 : 4));
pk.pack(std::string("id")); pk.pack(myid);
@@ -849,6 +876,9 @@ NetworkEngine::sendAnnounceValue(std::shared_ptr<Node> n, const InfoHash& infoha
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
Blob b {buffer.data(), buffer.data() + buffer.size()};
std::shared_ptr<Request> req(new Request {tid.getTid(), n, std::move(b),
@@ -878,7 +908,7 @@ void
NetworkEngine::sendValueAnnounced(const sockaddr* sa, socklen_t salen, TransId tid, Value::Id vid) {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(3);
pk.pack(std::string("id")); pk.pack(myid);
@@ -889,6 +919,9 @@ NetworkEngine::sendValueAnnounced(const sockaddr* sa, socklen_t salen, TransId t
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, sa, salen);
}
@@ -917,6 +950,9 @@ NetworkEngine::sendError(const sockaddr* sa,
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("e"));
pk.pack(std::string("v")); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, sa, salen);
}
@@ -960,6 +996,9 @@ ParsedMessage::msgpack_unpack(msgpack::object msg)
error_code = e->via.array.ptr[0].as<uint16_t>();
}
if (auto netid = findMapValue(msg, "n"))
network = netid->as<NetId>();
if (auto rid = findMapValue(req, "id"))
id = {*rid};
+3 -3
View File
@@ -141,7 +141,7 @@ SecureDht::getCertificate(const InfoHash& node) const
return it->second;
}
const std::shared_ptr<crypto::PublicKey>
const std::shared_ptr<const crypto::PublicKey>
SecureDht::getPublicKey(const InfoHash& node) const
{
if (node == getId())
@@ -226,7 +226,7 @@ SecureDht::findCertificate(const InfoHash& node, std::function<void(const std::s
}
void
SecureDht::findPublicKey(const InfoHash& node, std::function<void(const std::shared_ptr<crypto::PublicKey>)> cb)
SecureDht::findPublicKey(const InfoHash& node, std::function<void(const std::shared_ptr<const crypto::PublicKey>)> cb)
{
auto pk = getPublicKey(node);
if (pk && *pk) {
@@ -342,7 +342,7 @@ SecureDht::putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallb
void
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) {
findPublicKey(to, [=](const std::shared_ptr<const crypto::PublicKey> pk) {
if(!pk || !*pk) {
if (callback)
callback(false, {});
+3 -2
View File
@@ -142,8 +142,9 @@ Value::msgpack_unpack_body(const msgpack::object& o)
seq = rseq->as<decltype(seq)>();
else
throw msgpack::type_error();
owner = std::make_shared<crypto::PublicKey>();
owner->msgpack_unpack(*rowner);
crypto::PublicKey new_owner;
new_owner.msgpack_unpack(*rowner);
owner = std::make_shared<const crypto::PublicKey>(std::move(new_owner));
if (auto rrecipient = findMapValue(*rbody, "to")) {
recipient = rrecipient->as<InfoHash>();
}
+1 -1
View File
@@ -53,7 +53,7 @@ main(int argc, char **argv)
throw std::runtime_error(std::string("Error initializing GnuTLS: ")+gnutls_strerror(rc));
DhtRunner dht;
dht.run(params.port, dht::crypto::generateIdentity("DHT Chat Node"), true);
dht.run(params.port, dht::crypto::generateIdentity("DHT Chat Node"), true, params.network);
if (not params.bootstrap.first.empty())
dht.bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
+2 -2
View File
@@ -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;
}
@@ -256,7 +256,7 @@ main(int argc, char **argv)
crt = dht::crypto::generateIdentity("DHT Node", ca_tmp);
}
dht.run(params.port, crt, true, params.is_bootstrap_node);
dht.run(params.port, crt, true, params.network);
if (params.log) {
if (not params.logfile.empty())
+1 -1
View File
@@ -80,7 +80,7 @@ main(int argc, char **argv)
auto crt_tmp = dht::crypto::generateIdentity("Scanner node", ca_tmp);
DhtRunner dht;
dht.run(params.port, crt_tmp, true, [](dht::NodeStatus /* ipv4 */, dht::NodeStatus /* ipv6 */) {});
dht.run(params.port, crt_tmp, true, params.network);
if (not params.bootstrap.first.empty())
dht.bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
+12 -18
View File
@@ -142,6 +142,7 @@ struct dht_params {
bool log {false};
std::string logfile {};
in_port_t port {0};
dht::NetId network {0};
bool is_bootstrap_node {false};
bool generate_identity {false};
bool daemonize {false};
@@ -151,9 +152,10 @@ struct dht_params {
static const constexpr struct option long_options[] = {
{"help", no_argument, nullptr, 'h'},
{"port", required_argument, nullptr, 'p'},
{"net", required_argument, nullptr, 'n'},
{"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,16 +164,19 @@ 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 'n':
params.network = strtoul(optarg, nullptr, 0);
break;
case 'b':
if (optarg) {
params.bootstrap = splitPort((optarg[0] == '=') ? optarg+1 : optarg);
@@ -180,8 +185,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 +202,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;
}