Compare commits

..
25 Commits
Author SHA1 Message Date
Adrien Béraud 83f8a92e5e travis: add llvm docker build 2016-07-29 21:16:43 -04:00
Adrien Béraud f41685b864 const shared_ptr 2016-07-29 20:25:34 -04:00
Adrien Béraud 84adbddd6f travis with docker 2016-07-29 20:21:06 -04:00
Simon Désaulniers fa9730dd07 add readme help text for benchmark 2016-06-15 15:57:56 -04:00
Adrien Béraud 33f29e95f4 value: add common crypto ops 2016-06-15 13:35:44 -04:00
Adrien Béraud fdfa10bd2e dht: clear search before expiring it 2016-06-13 15:55:34 -04:00
Adrien Béraud f200f9dfc2 pkgconfig: add private dependencies 2016-06-11 21:50:34 -04:00
Adrien Béraud 9615774114 cmake: build versioned shared library 2016-06-11 21:22:27 -04:00
Adrien Béraud c6b0e531c2 dht: add code documentation 2016-06-11 18:54:18 -04:00
Adrien Béraud 8e5f12dbf1 autotools: handle case where DESTDIR is empty 2016-06-11 16:10:52 -04:00
Adrien Béraud 5bcf1da505 autotools: cleanup 2016-06-11 16:10:27 -04:00
Adrien Béraud 97d88fcfed autotools: disable doxygen by default 2016-06-11 16:04:35 -04:00
Adrien Béraud 963dd6779e benchmark: don't block while putting values 2016-06-03 17:20:58 -04:00
Simon Désaulniers 54a4327039 dht: handle search expired before permanent put 2016-06-03 17:20:58 -04:00
Simon Désaulniers 10e5439048 securedht: permanent put of a certificate. 2016-06-03 17:20:58 -04:00
Simon Désaulniers dcca94aab7 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-06-03 17:20:58 -04:00
Simon Désaulniers 173a9ee642 revert attempt to avoid securedht cert put fail 2016-06-03 17:20:58 -04:00
Simon Désaulniers ed1ca6db8f Revert "dht: wait for connection before running searches"
This reverts commit bd08506146.
2016-06-03 17:20:58 -04:00
Adrien Béraud 7367158284 dht: new insertNode algorithm 2016-06-03 17:20:58 -04:00
Adrien Béraud cf8d9ccd0d infohash: merge Windows includes 2016-06-02 17:52:07 -04:00
Adrien Béraud fdbdc91d55 Merge pull request #74 from sim590/python-destdir
[packaging] support python installation with make DESTDIR=$DIR
2016-06-02 15:41:55 -04:00
Simon Désaulniers cf9c63abb7 enable python make DESTDIR=$DIR install support 2016-06-02 14:48:05 -04:00
Simon Désaulniers 475b26048f cmake: pass $DESTDIR environnement var to setup.py 2016-06-02 12:36:21 -04:00
Andreas Traczyk df1615e8d1 Update README.md 2016-06-02 12:22:34 -04:00
Andreas Traczyk 9e461e0960 microsoft compiler support 2016-06-02 12:17:09 -04:00
28 changed files with 159 additions and 299 deletions

No files matched your search

+5 -31
View File
@@ -1,44 +1,18 @@
sudo: false
sudo: required
services:
- docker
language: cpp
compiler:
- gcc
- clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-6
- g++-6
- libgnutls28-dev
- cmake
before_install:
- if [ $TRAVIS_OS_NAME == linux ] && [ $CXX == g++ ]; then export CXX=/usr/bin/g++-6 && export CC=/usr/bin/gcc-6; fi
- if [ $TRAVIS_OS_NAME == linux ]; then git clone https://github.com/msgpack/msgpack-c.git; fi
- if [ $TRAVIS_OS_NAME == linux ]; then cd msgpack-c && git checkout cpp-1.2.0 && mkdir build && mkdir -p $HOME/usr && cd build; fi
- if [ $TRAVIS_OS_NAME == linux ]; then cmake -DCMAKE_INSTALL_PREFIX=$HOME/usr -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF .. && make -j && make install && cd ../.. && pwd; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install llvm36 && brew install msgpack && brew install gnutls && brew link --force llvm36; fi
before_script:
- if [ $TRAVIS_OS_NAME == linux ]; then travis_retry ./autogen.sh && ./configure --prefix=$HOME/usr; fi
- if [ $TRAVIS_OS_NAME == osx ]; then travis_retry ./autogen.sh && ./configure; fi
- docker pull aberaud/opendht-deps
- docker pull aberaud/opendht-deps-llvm
script:
- make -j
- docker build -f docker/DockerfileTravis .
- docker build -f docker/DockerfileTravisLlvm .
notifications:
email:
- adrien.beraud@savoirfairelinux.com
env:
- LANG="en_US.UTF-8"
os:
- osx
+1 -2
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.3)
set (opendht_VERSION_MINOR 6.1)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -132,7 +132,6 @@ endif ()
if (OPENDHT_TOOLS)
add_subdirectory(tools)
endif ()
add_subdirectory(doc)
if (OPENDHT_PYTHON)
add_subdirectory(python)
+2
View File
@@ -10,7 +10,9 @@ if USE_CYTHON
SUBDIRS += python
endif
if HAVE_DOXYGEN
SUBDIRS += doc
endif
ACLOCAL_AMFLAGS = -I m4
+1 -5
View File
@@ -97,11 +97,7 @@ Licence
-
Copyright (C) 2014-2016 Savoir-faire Linux Inc.
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.
Licenced under the GNU General Public License version 3 (see COPYING for the full licence).
This project is independent from another project called OpenDHT (Sean Rhea. Ph.D. Thesis, 2005), now extinct.
+2 -13
View File
@@ -1,21 +1,10 @@
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_INIT(opendht, 0.6.1)
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"],
@@ -99,7 +88,7 @@ AM_COND_IF([ENABLE_TOOLS], [
])
])
AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])
AM_COND_IF([HAVE_DOXYGEN], [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
@@ -1,3 +0,0 @@
if (OPENDHT_TOOLS)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dhtnode.1 DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man1)
endif ()
-4
View File
@@ -1,6 +1,3 @@
dist_man1_MANS = dhtnode.1
if HAVE_DOXYGEN
doxyfile.stamp:
$(DOXYGEN) Doxyfile
echo stamp > doxyfile.stamp
@@ -10,4 +7,3 @@ CLEANFILES = doxyfile.stamp
all-local: doxyfile.stamp
clean-local:
rm -rf $(top_srcdir)/doc/man $(top_srcdir)/doc/html
endif
-85
View File
@@ -1,85 +0,0 @@
.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>
+6
View File
@@ -0,0 +1,6 @@
FROM aberaud/opendht-deps
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+9
View File
@@ -0,0 +1,9 @@
FROM ubuntu:16.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev libgnutls-dev cython3 python3-dev python3-setuptools
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-1.4.2/msgpack-1.4.2.tar.gz \
&& tar -xzf msgpack-1.4.2.tar.gz \
&& cd msgpack-1.4.2 && mkdir build && cd build \
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
&& make -j8 && make install \
&& cd ../.. && rm -rf msgpack-1.4.2
+11
View File
@@ -0,0 +1,11 @@
FROM ubuntu:16.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update \
&& apt-get install -y llvm clang make cmake git wget libncurses5-dev libreadline-dev nettle-dev libgnutls-dev cython3 python3-dev python3-setuptools \
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-1.4.2/msgpack-1.4.2.tar.gz \
&& tar -xzf msgpack-1.4.2.tar.gz \
&& cd msgpack-1.4.2 && mkdir build && cd build \
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
&& make -j8 && make install \
&& cd ../.. && rm -rf msgpack-1.4.2
+6
View File
@@ -0,0 +1,6 @@
FROM aberaud/opendht-deps-llvm
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+6
View File
@@ -0,0 +1,6 @@
FROM aberaud/opendht-deps
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
COPY . /root/opendht
RUN cd /root/opendht && mkdir build && cd build \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+6
View File
@@ -0,0 +1,6 @@
FROM aberaud/opendht-deps-llvm
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
COPY . /root/opendht
RUN cd /root/opendht && mkdir build && cd build \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr .. && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+2 -21
View File
@@ -30,44 +30,23 @@ 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)>;
@@ -78,6 +57,8 @@ 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<std::unique_ptr<Storage>> store;
std::vector<Storage> store;
size_t total_values {0};
size_t total_store_size {0};
size_t max_store_size {DEFAULT_STORAGE_LIMIT};
+2 -3
View File
@@ -268,13 +268,12 @@ 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, NetId network = 0) {
void run(in_port_t port, const crypto::Identity identity, bool threaded = false, bool is_bootstrap = false) {
run(port, {
/*.dht_config = */{
/*.node_config = */{
/*.node_id = */{},
/*.network = */network,
/*.is_bootstrap = */false
/*.is_bootstrap = */is_bootstrap
},
/*.id = */identity
},
+2 -3
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, NetId net, int s, int s6, Logger& log, Scheduler& scheduler,
NetworkEngine(InfoHash& myid, 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), network(net),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), myid(myid),
dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{
transaction_id = std::uniform_int_distribution<decltype(transaction_id)>{1}(rd_device);
@@ -376,7 +376,6 @@ 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,8 +23,6 @@
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())
+2 -1
View File
@@ -40,8 +40,9 @@
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);
+13 -10
View File
@@ -208,23 +208,23 @@ class DhtFeatureTest(FeatureTest):
FeatureTest.lock.notify()
def _dhtPut(self, producer, _hash, *values):
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:
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
producer.put(_hash, val, DhtFeatureTest.putDoneCb)
FeatureTest.lock.wait()
while FeatureTest.done > 0:
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 50
NUM_VALUES = self._num_values/wb.node_num if self._num_values else 5
nr_values = NUM_VALUES * wb.node_num
nr_nodes = wb.node_num
nr_nodes_cv = threading.Condition()
@@ -365,8 +365,11 @@ 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@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
libopendht_la_LDFLAGS = @LDFLAGS@ @GnuTLS_LIBS@ @Nettle_LIBS@
libopendht_la_LIBADD = ./argon2/libargon2.la
libopendht_la_SOURCES = \
+45 -45
View File
@@ -170,10 +170,9 @@ private:
size_t total_size {};
};
struct Dht::SearchNode {
SearchNode() : node() {}
SearchNode(std::shared_ptr<Node> node) : node(node) {}
SearchNode(const std::shared_ptr<Node>& node) : node(node) {}
using AnnounceStatusMap = std::map<Value::Id, std::shared_ptr<Request>>;
@@ -396,7 +395,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 +1369,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(new Storage(id, scheduler.time()));
store.emplace_back(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 +1385,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 +1411,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) {
@@ -1488,6 +1487,7 @@ Dht::get(const InfoHash& id, GetCallback getcb, DoneCallback donecb, Value::Filt
auto status = std::make_shared<OpStatus>();
auto status4 = std::make_shared<OpStatus>();
auto status6 = std::make_shared<OpStatus>();
auto vals = std::make_shared<std::vector<std::shared_ptr<Value>>>();
auto all_nodes = std::make_shared<std::vector<std::shared_ptr<Node>>>();
@@ -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 std::unique_ptr<Storage>& st) {
return st->id == id;
return std::find_if(store.begin(), store.end(), [&](const 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 std::unique_ptr<Storage>& st) {
return st->id == id;
return std::find_if(store.cbegin(), store.cend(), [&](const 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(new Storage(id, now));
store.emplace_back(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(new Storage(id, now));
store.emplace_back(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, config.network, s, s6, DHT_LOG, scheduler,
network_engine(myid, 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;
+14 -53
View File
@@ -49,7 +49,6 @@ 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,
@@ -64,7 +63,6 @@ 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 */
@@ -295,11 +293,6 @@ 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;
@@ -458,10 +451,9 @@ packToken(msgpack::packer<msgpack::sbuffer>& pk, Blob token)
}
void
insertAddr(msgpack::packer<msgpack::sbuffer>& pk, const sockaddr *sa, socklen_t sa_len)
insertAddr(msgpack::packer<msgpack::sbuffer>& pk, const sockaddr *sa, socklen_t)
{
size_t addr_len = std::min<size_t>(sa_len,
(sa->sa_family == AF_INET) ? sizeof(in_addr) : sizeof(in6_addr));
size_t addr_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");
@@ -493,7 +485,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+(network?1:0));
pk.pack_map(5);
pk.pack(std::string("a")); pk.pack_map(1);
pk.pack(std::string("id")); pk.pack(myid);
@@ -503,9 +495,6 @@ 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),
@@ -530,7 +519,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+(network?1:0));
pk.pack_map(4);
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
@@ -540,9 +529,6 @@ 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);
}
@@ -553,7 +539,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+(network?1:0));
pk.pack_map(5);
pk.pack(std::string("a")); pk.pack_map(2 + (want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
@@ -570,9 +556,7 @@ 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),
@@ -599,7 +583,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+(network?1:0));
pk.pack_map(5);
pk.pack(std::string("a")); pk.pack_map(2 + (want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
@@ -616,9 +600,6 @@ 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),
@@ -683,7 +664,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+(network?1:0));
pk.pack_map(4);
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));
@@ -734,9 +715,6 @@ 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);
}
@@ -747,7 +725,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>(SEND_NODES, nodes.size());
size_t nnode = std::min<size_t>(TARGET_NODES, nodes.size());
Blob bnodes;
if (af == AF_INET) {
bnodes.resize(NODE4_INFO_BUF_LEN * nnode);
@@ -799,7 +777,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+(network?1:0));
pk.pack_map(5);
pk.pack(std::string("a")); pk.pack_map(3);
pk.pack(std::string("id")); pk.pack(myid);
@@ -811,9 +789,7 @@ 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),
@@ -836,7 +812,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+(network?1:0));
pk.pack_map(4);
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
@@ -846,9 +822,6 @@ 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);
}
@@ -859,7 +832,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+(network?1:0));
pk.pack_map(5);
pk.pack(std::string("a")); pk.pack_map((created < scheduler.time() ? 5 : 4));
pk.pack(std::string("id")); pk.pack(myid);
@@ -876,9 +849,6 @@ 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),
@@ -908,7 +878,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+(network?1:0));
pk.pack_map(4);
pk.pack(std::string("r")); pk.pack_map(3);
pk.pack(std::string("id")); pk.pack(myid);
@@ -919,9 +889,6 @@ 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);
}
@@ -950,9 +917,6 @@ 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);
}
@@ -996,9 +960,6 @@ 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};
+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, params.network);
dht.run(params.port, dht::crypto::generateIdentity("DHT Chat Node"), true);
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 [-v[logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b[bootstrap_host[:port]]]" << std::endl << std::endl;
std::cout << "Usage: dhtnode [-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.network);
dht.run(params.port, crt, true, params.is_bootstrap_node);
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, params.network);
dht.run(params.port, crt_tmp, true, [](dht::NodeStatus /* ipv4 */, dht::NodeStatus /* ipv6 */) {});
if (not params.bootstrap.first.empty())
dht.bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
+18 -12
View File
@@ -142,7 +142,6 @@ 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};
@@ -152,10 +151,9 @@ 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", optional_argument, nullptr, 'v'},
{"verbose", no_argument , nullptr, 'v'},
{"daemonize", no_argument , nullptr, 'd'},
{nullptr, 0, nullptr, 0}
};
@@ -164,19 +162,16 @@ dht_params
parseArgs(int argc, char **argv) {
dht_params params;
int opt;
while ((opt = getopt_long(argc, argv, "hidv::p:n:b::", long_options, nullptr)) != -1) {
while ((opt = getopt_long(argc, argv, ":hidv:p: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::cerr << "Invalid port: " << port_arg << std::endl;
std::cout << "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);
@@ -185,7 +180,8 @@ parseArgs(int argc, char **argv) {
ss << DHT_DEFAULT_PORT;
params.bootstrap.second = ss.str();
}
} else
}
else
params.is_bootstrap_node = true;
break;
case 'h':
@@ -202,9 +198,19 @@ parseArgs(int argc, char **argv) {
case 'd':
params.daemonize = true;
break;
case '?':
std::cerr << "unrecognized option -- '" << static_cast<char>(optopt) << '\'' << std::endl;
exit(EXIT_FAILURE);
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;
default:
break;
}