Compare commits

...
28 Commits
Author SHA1 Message Date
Adrien Béraud b6a58ce784 link ssl 2019-04-17 10:00:15 -04:00
Adrien Béraud 5ec72e213e dht: add override 2019-04-17 10:00:15 -04:00
Adrien Béraud 683a111726 autotools: build versioned shared library 2019-04-16 12:23:32 -04:00
Adrien Béraud 0fd4fed537 search: add fallback return 2019-04-16 12:23:32 -04:00
Adrien Béraud ef82652a1e network: header cleanup 2019-04-14 11:30:10 -04:00
Adrien Béraud 4f03a5c64e network: tid, socket_id, value_id: default to 0 2019-04-14 09:15:16 -04:00
Adrien Béraud 5257ac314f add API to retrieve version string 2019-04-14 00:19:01 -04:00
Adrien Béraud 0580a4e7dd update to version 1.9.1 2019-04-13 23:29:43 -04:00
Yanfei Han fd1f2cd0e4 add peer_discovery.o object into auto configure lib 2019-04-13 23:04:18 -04:00
Adrien Béraud af940c63b1 proxy: mute unused variable warning if disabled 2019-04-13 23:02:57 -04:00
Adrien Béraud 15da502354 dhtrunner: make peer discovery port static constexpr 2019-04-13 22:56:31 -04:00
Adrien Béraud b7a9a52f97 network engine: DhtProtocolException cleanup 2019-04-13 22:56:31 -04:00
Adrien Béraud 6e10756e28 peerdiscovery: cleanup 2019-04-13 22:56:31 -04:00
Adrien Béraud aad4ad03cf network utils: add missing includes 2019-04-13 22:56:31 -04:00
Adrien Béraud 3d1e055c7b peerdiscovery: always use local node id 2019-04-13 20:50:00 -04:00
Adrien Béraud b02e9cfff7 peerdiscovery: flush stop socket if not stopping 2019-04-13 20:50:00 -04:00
Adrien Béraud 453db29058 dht: add override to getNodeId 2019-04-13 20:43:57 -04:00
Adrien Béraud a8ba536d44 update to version 1.9.0 2019-04-09 16:25:39 -04:00
Adrien Béraud a238183031 peerdiscovery: don't assign IPv6 multicast interface 2019-04-09 16:11:21 -04:00
Adrien Béraud 73827cd34d peerdiscovery: allow IPV6_MULTICAST_IF failure 2019-04-09 15:12:37 -04:00
Adrien Béraud 876190a392 peerdiscovery: SO_REUSEADDR, SO_REUSEPORT in different calls 2019-04-09 14:58:22 -04:00
Adrien Béraud 7fe321e4fc peerdiscovery: cleanup data serialization 2019-04-09 14:57:48 -04:00
Adrien Béraud 7f7075ca9a peerdiscovery: support IPV6_JOIN_GROUP 2019-04-09 12:31:23 -04:00
Adrien Béraud 9b9f12d87e tests: accept null token if callback returns false 2019-04-08 15:58:46 -04:00
Adrien Béraud 26ad6de3a4 dhtrunner: avoid race condition when setting token 2019-04-08 15:57:25 -04:00
Adrien Béraud ae91f8bd55 dhtrunner: default-initialize tokens 2019-04-08 15:36:24 -04:00
Adrien Béraud 28eeee24ba runnertester: reduce number of test values 2019-04-08 15:35:55 -04:00
Adrien Béraud 671c55a01d dhtrunner: print peer discovery error message to cerr 2019-04-08 14:36:15 -04:00
23 changed files with 231 additions and 208 deletions

No files matched your search

+19 -3
View File
@@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 3.1)
project (opendht)
set (opendht_VERSION_MAJOR 1)
set (opendht_VERSION_MINOR 8.2)
set (opendht_VERSION_MINOR 9.1)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -62,6 +62,9 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
if (NOT Jsoncpp_FOUND)
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
endif()
pkg_search_module(SSL libssl)
pkg_search_module(Crypto libcrypto)
pkg_search_module(Tls libtls)
endif()
# Build flags
@@ -75,6 +78,7 @@ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif ()
add_definitions(-DPACKAGE_VERSION="${opendht_VERSION}")
if (OPENDHT_LOG)
add_definitions(-DOPENDHT_LOG=true)
else ()
@@ -105,8 +109,20 @@ endif ()
if (Jsoncpp_INCLUDE_DIRS)
include_directories (SYSTEM "${Jsoncpp_INCLUDE_DIRS}")
endif ()
if (SSL_INCLUDE_DIRS)
include_directories (SYSTEM "${SSL_INCLUDE_DIRS}")
endif ()
if (Crypto_INCLUDE_DIRS)
include_directories (SYSTEM "${Crypto_INCLUDE_DIRS}")
endif ()
if (Tls_INCLUDE_DIRS)
include_directories (SYSTEM "${Tls_INCLUDE_DIRS}")
endif ()
link_directories (${Nettle_LIBRARY_DIRS})
link_directories (${Jsoncpp_LIBRARY_DIRS})
link_directories (${SSL_LIBRARY_DIRS})
link_directories (${Crypto_LIBRARY_DIRS})
link_directories (${Tls_LIBRARY_DIRS})
include_directories (
./
include/
@@ -254,7 +270,7 @@ if (OPENDHT_STATIC)
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht-static
PRIVATE ${Restbed_LIBRARY} ${argon2_LIBRARIES}
PRIVATE ${Restbed_LIBRARY} ${argon2_LIBRARIES} ${SSL_LIBRARIES} ${Crypto_LIBRARIES} ${Tls_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Jsoncpp_LIBRARIES})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
@@ -273,7 +289,7 @@ if (OPENDHT_SHARED)
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Restbed_LIBRARY} ${Jsoncpp_LIBRARIES})
target_link_libraries(opendht PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Restbed_LIBRARY} ${Jsoncpp_LIBRARIES} ${SSL_LIBRARIES} ${Crypto_LIBRARIES} ${Tls_LIBRARIES})
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
+2 -2
View File
@@ -1,7 +1,7 @@
dnl define macros
m4_define([opendht_major_version], 1)
m4_define([opendht_minor_version], 8)
m4_define([opendht_patch_version], 2)
m4_define([opendht_minor_version], 9)
m4_define([opendht_patch_version], 1)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
+42 -42
View File
@@ -74,21 +74,21 @@ public:
/**
* Get the ID of the node.
*/
inline const InfoHash& getNodeId() const { return myid; }
inline const InfoHash& getNodeId() const override { return myid; }
/**
* Get the current status of the node for the given family.
*/
NodeStatus getStatus(sa_family_t af) const;
NodeStatus getStatus(sa_family_t af) const override;
NodeStatus getStatus() const {
NodeStatus getStatus() const override {
return std::max(getStatus(AF_INET), getStatus(AF_INET6));
}
/**
* Performs final operations before quitting.
*/
void shutdown(ShutdownCallback cb);
void shutdown(ShutdownCallback cb) override;
/**
* Returns true if the node is running (have access to an open socket).
@@ -96,12 +96,12 @@ public:
* af: address family. If non-zero, will return true if the node
* is running for the provided family.
*/
bool isRunning(sa_family_t af = 0) const;
bool isRunning(sa_family_t af = 0) const override;
virtual void registerType(const ValueType& type) {
virtual void registerType(const ValueType& type) override {
types.registerType(type);
}
const ValueType& getType(ValueType::Id type_id) const {
const ValueType& getType(ValueType::Id type_id) const override {
return types.getType(type_id);
}
@@ -110,18 +110,18 @@ public:
* The node is not pinged, so this should be
* used to bootstrap efficiently from previously known nodes.
*/
void insertNode(const InfoHash& id, const SockAddr&);
void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) {
void insertNode(const InfoHash& id, const SockAddr&) override;
void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) override {
insertNode(id, SockAddr(sa, salen));
}
void insertNode(const NodeExport& n) {
void insertNode(const NodeExport& n) override {
insertNode(n.id, SockAddr(n.ss, n.sslen));
}
void pingNode(const sockaddr*, socklen_t, DoneCallbackSimple&& cb={});
void pingNode(const sockaddr*, socklen_t, DoneCallbackSimple&& cb={}) override;
time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr&);
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) {
time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr&) override;
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) override {
return periodic(buf, buflen, SockAddr(from, fromlen));
}
@@ -135,14 +135,14 @@ public:
cb and donecb won't be called again afterward.
* @param f a filter function used to prefilter values.
*/
virtual void get(const InfoHash& key, GetCallback cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {});
virtual void get(const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f={}, Where&& w = {}) {
virtual void get(const InfoHash& key, GetCallback cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) override;
virtual void get(const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f={}, Where&& w = {}) override {
get(key, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) {
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) override {
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) {
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) override {
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
/**
@@ -155,20 +155,20 @@ public:
* @param q a query used to filter values on the remotes before they send a
* response.
*/
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {});
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) {
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override;
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override {
query(key, cb, bindDoneCb(done_cb), std::forward<Query>(q));
}
/**
* Get locally stored data for the given hash.
*/
std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const;
std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override;
/**
* Get locally stored data for the given key and value id.
*/
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const;
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override;
/**
* Announce a value on all available protocols (IPv4, IPv6).
@@ -180,12 +180,12 @@ public:
Sp<Value>,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false);
bool permanent = false) override;
void put(const InfoHash& key,
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
put(key, v, bindDoneCb(cb), created, permanent);
}
@@ -194,7 +194,7 @@ public:
Value&& v,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
put(key, std::make_shared<Value>(std::move(v)), cb, created, permanent);
}
@@ -202,7 +202,7 @@ public:
Value&& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
put(key, std::forward<Value>(v), bindDoneCb(cb), created, permanent);
}
@@ -210,18 +210,18 @@ public:
/**
* Get data currently being put at the given hash.
*/
std::vector<Sp<Value>> getPut(const InfoHash&) const;
std::vector<Sp<Value>> getPut(const InfoHash&) const override;
/**
* Get data currently being put at the given hash with the given id.
*/
Sp<Value> getPut(const InfoHash&, const Value::Id&) const;
Sp<Value> getPut(const InfoHash&, const Value::Id&) const override;
/**
* Stop any put/announce operation at the given location,
* for the value with the given id.
*/
bool cancelPut(const InfoHash&, const Value::Id&);
bool cancelPut(const InfoHash&, const Value::Id&) override;
/**
* Listen on the network for any changes involving a specified hash.
@@ -230,28 +230,28 @@ public:
*
* @return a token to cancel the listener later.
*/
virtual size_t listen(const InfoHash&, ValueCallback, Value::Filter={}, Where={});
size_t listen(const InfoHash&, ValueCallback, Value::Filter={}, Where={}) override;
virtual size_t listen(const InfoHash& key, GetCallback cb, Value::Filter f={}, Where w={}) {
size_t listen(const InfoHash& key, GetCallback cb, Value::Filter f={}, Where w={}) override {
return listen(key, [cb](const std::vector<Sp<Value>>& vals, bool expired){
if (not expired)
return cb(vals);
return true;
}, std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w={}) {
size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w={}) override {
return listen(key, bindGetCb(cb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual bool cancelListen(const InfoHash&, size_t token);
bool cancelListen(const InfoHash&, size_t token) override;
/**
* Inform the DHT of lower-layer connectivity changes.
* This will cause the DHT to assume a public IP address change.
* The DHT will recontact neighbor nodes, re-register for listen ops etc.
*/
void connectivityChanged(sa_family_t);
void connectivityChanged() {
void connectivityChanged(sa_family_t) override;
void connectivityChanged() override {
reported_addr.clear();
connectivityChanged(AF_INET);
connectivityChanged(AF_INET6);
@@ -261,18 +261,18 @@ public:
* Get the list of good nodes for local storage saving purposes
* The list is ordered to minimize the back-to-work delay.
*/
std::vector<NodeExport> exportNodes() const;
std::vector<NodeExport> exportNodes() const override;
std::vector<ValuesExport> exportValues() const;
void importValues(const std::vector<ValuesExport>&);
std::vector<ValuesExport> exportValues() const override;
void importValues(const std::vector<ValuesExport>&) override;
void saveState(const std::string& path) const;
void loadState(const std::string& path);
NodeStats getNodesStats(sa_family_t af) const;
NodeStats getNodesStats(sa_family_t af) const override;
std::string getStorageLog() const;
std::string getStorageLog(const InfoHash&) const;
std::string getStorageLog() const override;
std::string getStorageLog(const InfoHash&) const override;
std::string getRoutingTablesLog(sa_family_t) const;
std::string getSearchesLog(sa_family_t) const;
@@ -298,9 +298,9 @@ public:
return {total_store_size, total_values};
}
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0);
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override;
void pushNotificationReceived(const std::map<std::string, std::string>&) {}
void pushNotificationReceived(const std::map<std::string, std::string>&) override {}
void resubscribe(unsigned) {}
private:
+2
View File
@@ -49,6 +49,8 @@ public:
virtual void setPushNotificationToken(const std::string& token) {
#ifdef OPENDHT_PUSH_NOTIFICATIONS
deviceKey_ = token;
#else
(void) token;
#endif
}
-2
View File
@@ -541,8 +541,6 @@ private:
/** PeerDiscovery Parameters */
std::unique_ptr<PeerDiscovery> peerDiscovery4_;
std::unique_ptr<PeerDiscovery> peerDiscovery6_;
const in_port_t port_multicast = 8888;
};
}
+4 -3
View File
@@ -27,6 +27,7 @@
#include "utils.h"
#include "rng.h"
#include "rate_limiter.h"
#include "log_enable.h"
#include <vector>
#include <string>
@@ -68,14 +69,14 @@ public:
DhtProtocolException(uint16_t code, const std::string& msg="", InfoHash failing_node_id={})
: DhtException(msg), msg(msg), code(code), failing_node_id(failing_node_id) {}
std::string getMsg() const { return msg; }
const std::string& getMsg() const { return msg; }
uint16_t getCode() const { return code; }
const InfoHash getNodeId() const { return failing_node_id; }
const InfoHash& getNodeId() const { return failing_node_id; }
private:
std::string msg;
uint16_t code;
const InfoHash failing_node_id;
InfoHash failing_node_id;
};
struct ParsedMessage;
+1 -17
View File
@@ -18,13 +18,10 @@
#pragma once
#include "def.h"
#include "sockaddr.h"
#include "infohash.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <mutex>
#include <condition_variable>
@@ -119,19 +116,6 @@ private:
* Sender Parameters Setup
*/
void sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send);
/**
* Binary Converters
*/
static void inttolitend(uint32_t x, uint8_t *lit_int) {
lit_int[0] = (uint8_t)(x >> 0);
lit_int[1] = (uint8_t)(x >> 8);
}
static uint16_t litendtoint(uint8_t *lit_int) {
return (uint32_t)lit_int[0] << 0
| (uint32_t)lit_int[1] << 8;
}
};
}
-1
View File
@@ -21,7 +21,6 @@
#pragma once
#include "utils.h"
#include "log_enable.h"
#include <functional>
#include <map>
+2
View File
@@ -40,6 +40,8 @@ namespace dht {
using NetId = uint32_t;
using want_t = int_fast8_t;
OPENDHT_PUBLIC const char* version();
// shortcut for std::shared_ptr
template<class T>
using Sp = std::shared_ptr<T>;
+3 -1
View File
@@ -2,7 +2,7 @@ lib_LTLIBRARIES = libopendht.la
libopendht_la_CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/include/opendht @Argon2_CFLAGS@ @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@
libopendht_la_LIBADD = @Argon2_LIBS@ @JsonCpp_LIBS@ @GnuTLS_LIBS@ @Nettle_LIBS@
libopendht_la_LDFLAGS = @LDFLAGS@ @Argon2_LDFLAGS@
libopendht_la_LDFLAGS = @LDFLAGS@ @Argon2_LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
libopendht_la_SOURCES = \
dht.cpp \
storage.h \
@@ -27,6 +27,7 @@ libopendht_la_SOURCES = \
dhtrunner.cpp \
default_types.cpp \
log.cpp \
peer_discovery.cpp \
network_utils.h \
network_utils.cpp
@@ -55,6 +56,7 @@ nobase_include_HEADERS = \
../include/opendht/default_types.h \
../include/opendht/log.h \
../include/opendht/log_enable.h \
../include/opendht/peer_discovery.h \
../include/opendht/rng.h
if ENABLE_PROXY_SERVER
+5
View File
@@ -1037,6 +1037,8 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
} catch (const std::exception& e) {
DHT_LOG.e("Error handling push notification: %s", e.what());
}
#else
(void) notification;
#endif
}
@@ -1066,6 +1068,9 @@ DhtProxyClient::resubscribe(const InfoHash& key, Listener& listener)
listener.thread = std::thread([this, req, vcb, filter, state]() {
sendListen(req, vcb, filter, state, ListenMethod::RESUBSCRIBE);
});
#else
(void) key;
(void) listener;
#endif
}
+45 -37
View File
@@ -27,16 +27,23 @@
#include "dht_proxy_client.h"
#endif
#ifdef _WIN32
#include <cstring>
#define close(x) closesocket(x)
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
#endif
namespace dht {
constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD;
static constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 16;
static constexpr in_port_t PEER_DISCOVERY_PORT = 8888;
struct DhtRunner::Listener {
size_t tokenClassicDht;
size_t tokenProxyDht;
size_t tokenClassicDht {0};
size_t tokenProxyDht {0};
ValueCallback gcb;
InfoHash hash;
InfoHash hash {};
Value::Filter f;
Where w;
};
@@ -137,33 +144,31 @@ DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const DhtRunner::
if (config.peer_discovery or config.peer_publish) {
try {
peerDiscovery4_.reset(new PeerDiscovery(AF_INET, port_multicast));
} catch(std::exception &exception){
perror(exception.what());
peerDiscovery4_.reset(new PeerDiscovery(AF_INET, PEER_DISCOVERY_PORT));
} catch(const std::exception& e){
std::cerr << "Can't start peer discovery (IPv4): " << e.what() << std::endl;
}
try{
peerDiscovery6_.reset(new PeerDiscovery(AF_INET6, port_multicast));
} catch(std::exception &exception){
perror(exception.what());
try {
peerDiscovery6_.reset(new PeerDiscovery(AF_INET6, PEER_DISCOVERY_PORT));
} catch(const std::exception& e) {
std::cerr << "Can't start peer discovery (IPv6): " << e.what() << std::endl;
}
}
if (config.peer_discovery) {
using sig = void (DhtRunner::*)(const InfoHash&, const SockAddr&);
if (peerDiscovery4_)
peerDiscovery4_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap),
this,
peerDiscovery4_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap), this,
std::placeholders::_1,std::placeholders::_2));
if (peerDiscovery6_)
peerDiscovery6_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap),
this,
peerDiscovery6_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap), this,
std::placeholders::_1,std::placeholders::_2));
}
if (config.peer_publish) {
if (peerDiscovery4_)
peerDiscovery4_->startPublish(getNodeId(), getBoundPort(AF_INET));
peerDiscovery4_->startPublish(dht_->getNodeId(), getBoundPort(AF_INET));
if (peerDiscovery6_)
peerDiscovery6_->startPublish(getNodeId(), getBoundPort(AF_INET6));
peerDiscovery6_->startPublish(dht_->getNodeId(), getBoundPort(AF_INET6));
}
}
@@ -187,10 +192,8 @@ DhtRunner::join()
running = false;
cv.notify_all();
bootstrap_cv.notify_all();
if (peerDiscovery4_)
peerDiscovery4_->stop();
if (peerDiscovery6_)
peerDiscovery6_->stop();
if (peerDiscovery4_) peerDiscovery4_->stop();
if (peerDiscovery6_) peerDiscovery6_->stop();
if (dht_thread.joinable())
dht_thread.join();
@@ -198,10 +201,9 @@ DhtRunner::join()
bootstrap_thread.join();
if (rcv_thread.joinable())
rcv_thread.join();
if (peerDiscovery4_)
peerDiscovery4_->join();
if (peerDiscovery6_)
peerDiscovery6_->join();
if (peerDiscovery4_) peerDiscovery4_->join();
if (peerDiscovery6_) peerDiscovery6_->join();
{
std::lock_guard<std::mutex> lck(storage_mtx);
@@ -226,17 +228,17 @@ DhtRunner::dumpTables() const
InfoHash
DhtRunner::getId() const
{
if (!activeDht())
return {};
return activeDht()->getId();
if (auto dht = activeDht())
return dht->getId();
return {};
}
InfoHash
DhtRunner::getNodeId() const
{
if (!activeDht())
return {};
return activeDht()->getNodeId();
if (auto dht = activeDht())
return dht->getNodeId();
return {};
}
@@ -485,6 +487,7 @@ int bindSocket(const SockAddr& addr, SockAddr& bound)
#endif
if (is_ipv6)
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&set, sizeof(set));
net::set_nonblocking(sock);
int rc = bind(sock, addr.get(), addr.getLength());
if(rc < 0) {
rc = errno;
@@ -661,22 +664,21 @@ DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
pending_ops.emplace([=](SecureDht& dht) mutable {
#ifdef OPENDHT_PROXY_CLIENT
auto tokenbGlobal = listener_token_++;
Listener listener {};
auto& listener = listeners_[tokenbGlobal];
listener.hash = hash;
listener.f = std::move(f);
listener.w = std::move(w);
listener.gcb = [hash,vcb,tokenbGlobal,this](const std::vector<Sp<Value>>& vals, bool expired){
listener.gcb = [hash,vcb,tokenbGlobal,this](const std::vector<Sp<Value>>& vals, bool expired) {
if (not vcb(vals, expired)) {
cancelListen(hash, tokenbGlobal);
return false;
}
return true;
};
if (use_proxy)
listener.tokenProxyDht = dht.listen(hash, listener.gcb, listener.f, listener.w);
else
listener.tokenClassicDht = dht.listen(hash, listener.gcb, listener.f, listener.w);
listeners_.emplace(tokenbGlobal, std::move(listener));
if (auto token = dht.listen(hash, listener.gcb, listener.f, listener.w)) {
if (use_proxy) listener.tokenProxyDht = token;
else listener.tokenClassicDht = token;
}
ret_token->set_value(tokenbGlobal);
#else
ret_token->set_value(dht.listen(hash, std::move(vcb), std::move(f), std::move(w)));
@@ -1081,6 +1083,8 @@ DhtRunner::forwardAllMessages(bool forward)
#endif // OPENDHT_PROXY_CLIENT
if (dht_)
dht_->forwardAllMessages(forward);
#else
(void) forward;
#endif // OPENDHT_PROXY_SERVER
}
@@ -1093,6 +1097,8 @@ DhtRunner::setPushNotificationToken(const std::string& token) {
pushToken_ = token;
if (dht_via_proxy_)
dht_via_proxy_->setPushNotificationToken(token);
#else
(void) token;
#endif
}
@@ -1108,6 +1114,8 @@ DhtRunner::pushNotificationReceived(const std::map<std::string, std::string>& da
});
}
cv.notify_all();
#else
(void) data;
#endif
}
+2 -24
View File
@@ -17,27 +17,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "network_engine.h"
#include "request.h"
#include "default_types.h"
#include "log_enable.h"
#include "parsed_message.h"
#include "network_utils.h"
#include <msgpack.hpp>
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
#else
#include <ws2tcpip.h>
#include <io.h>
#endif
#include <fcntl.h>
#include <cstring>
namespace dht {
namespace net {
@@ -56,7 +43,7 @@ constexpr std::chrono::seconds NetworkEngine::RX_TIMEOUT;
const std::string NetworkEngine::my_v {"RNG1"};
constexpr size_t NetworkEngine::MAX_REQUESTS_PER_SEC;
static const uint8_t v4prefix[16] = {
static constexpr uint8_t v4prefix[16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0
};
@@ -138,16 +125,7 @@ NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, const int& s, const int&
onAnnounce(std::move(onAnnounce)),
onRefresh(std::move(onRefresh)),
myid(myid), network(net), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{
if (dht_socket >= 0) {
if (!set_nonblocking(dht_socket))
throw DhtException("Can't set socket to non-blocking mode");
}
if (dht_socket6 >= 0) {
if (!set_nonblocking(dht_socket6))
throw DhtException("Can't set socket to non-blocking mode");
}
}
{}
NetworkEngine::~NetworkEngine() {
clear();
+11 -12
View File
@@ -18,18 +18,17 @@
#include "network_utils.h"
#ifndef _WIN32
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#ifdef _WIN32
#include "utils.h"
#include "sockaddr.h"
#include <io.h>
#include <string>
#include <cstring>
#define close(x) closesocket(x)
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
#endif
#else
#include <fcntl.h>
#endif
namespace dht {
namespace net {
@@ -55,7 +54,7 @@ void udpPipe(int fds[2])
{
int lst = socket(AF_INET, SOCK_DGRAM, 0);
if (lst < 0)
throw DhtException(std::string("Can't open socket: ") + strerror(lst));
throw DhtException(std::string("Can't open socket: ") + strerror(WSAGetLastError()));
sockaddr_in inaddr;
sockaddr addr;
memset(&inaddr, 0, sizeof(inaddr));
@@ -63,14 +62,14 @@ void udpPipe(int fds[2])
inaddr.sin_family = AF_INET;
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
inaddr.sin_port = 0;
int yes=1;
int yes = 1;
setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes));
int rc = bind(lst, (sockaddr*)&inaddr, sizeof(inaddr));
if (rc < 0) {
close(lst);
throw DhtException("Can't bind socket on " + print_addr((sockaddr*)&addr, sizeof(inaddr)) + " " + strerror(rc));
throw DhtException("Can't bind socket on " + print_addr((sockaddr*)&inaddr, sizeof(inaddr)) + " " + strerror(rc));
}
socklen_t len = sizeof(inaddr);
socklen_t len = sizeof(addr);
getsockname(lst, &addr, &len);
fds[0] = lst;
fds[1] = socket(AF_INET, SOCK_DGRAM, 0);
+9 -3
View File
@@ -18,9 +18,16 @@
#pragma once
#ifdef _WIN32
#include <ws2tcpip.h>
#include <winsock2.h>
#define close(x) closesocket(x)
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#ifndef IPV6_JOIN_GROUP
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
#endif
namespace dht {
@@ -30,7 +37,6 @@ bool set_nonblocking(int fd, bool nonblocking = true);
#ifdef _WIN32
void udpPipe(int fds[2]);
// extern const char *inet_ntop(int, const void *, char *, socklen_t);
#endif
}
+3 -3
View File
@@ -84,13 +84,13 @@ struct ParsedMessage {
/* target id around which to find nodes */
InfoHash target;
/* transaction id */
Tid tid;
Tid tid {0};
/* tid for packets going through request socket */
Tid socket_id;
Tid socket_id {0};
/* security token */
Blob token;
/* the value id (announce confirmation) */
Value::Id value_id;
Value::Id value_id {0};
/* time when value was first created */
time_point created { time_point::max() };
/* IPv4 nodes in response to a 'find' request */
+37 -41
View File
@@ -22,8 +22,12 @@
#ifdef _WIN32
#include <Ws2tcpip.h> // needed for ip_mreq definition for multicast
#include <Windows.h>
#include <cstring>
#define close(x) closesocket(x)
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
#else
#include <sys/types.h>
#include <unistd.h>
#endif
#include <fcntl.h>
@@ -75,13 +79,16 @@ PeerDiscovery::listener_setup()
sockAddrListen_.setAny();
unsigned int opt = 1;
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, (char*) &opt, sizeof(opt)) < 0){
throw std::runtime_error(std::string("Reusing ADDR failed: ") + strerror(errno));
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
std::cerr << "setsockopt SO_REUSEADDR failed: " << strerror(errno) << std::endl;
}
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
std::cerr << "setsockopt SO_REUSEPORT failed: " << strerror(errno) << std::endl;
}
// bind to receive address
if (bind(sockfd_, sockAddrListen_.get(), sockAddrListen_.getLength()) < 0){
throw std::runtime_error(std::string("Bind Socket For Listener Error: ") + strerror(errno));
throw std::runtime_error(std::string("Error binding socket: ") + strerror(errno));
}
}
@@ -97,31 +104,31 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
//multicast datagrams from the sockets application.
config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) {
throw std::runtime_error(std::string("Bound Network Interface IPV4 Error: ") + strerror(errno));
throw std::runtime_error(std::string("Bound Network Interface IPv4 Error: ") + strerror(errno));
}
//The IP_MULTICAST_TTL socket option allows the application to primarily
//limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely
unsigned char ttl4 = 20;
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) {
throw std::runtime_error(std::string(" TTL Sockopt Error: ") + strerror(errno));
throw std::runtime_error(std::string("TTL Sockopt Error: ") + strerror(errno));
}
// config the listener to be interested in joining in the multicast group
config_ipv4.imr_multiaddr.s_addr = inet_addr(MULTICAST_ADDRESS_IPV4);
config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&config_ipv4, sizeof(config_ipv4)) < 0){
throw std::runtime_error(std::string(" Member Addition IPV4 Error: ") + strerror(errno));
throw std::runtime_error(std::string(" Member Addition IPv4 Error: ") + strerror(errno));
}
break;
}
case AF_INET6: {
ipv6_mreq config_ipv6;
unsigned int outif = 0;
if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof( outif )) < 0 ) {
throw std::runtime_error(std::string("Bound Network Interface IPV6 Error: ") + strerror(errno));
}
/* unsigned int outif = 0;
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif, sizeof(outif)) < 0) {
std::cerr << "Can't assign multicast interface: " << strerror(errno) << std::endl;
} */
unsigned int ttl6 = 20;
if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) {
@@ -130,8 +137,8 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
config_ipv6.ipv6mr_interface = 0;
inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr);
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &config_ipv6, sizeof(config_ipv6)) < 0){
throw std::runtime_error(std::string("Member Addition IPV6 Error: ") + strerror(errno));
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &config_ipv6, sizeof(config_ipv6)) < 0){
throw std::runtime_error(std::string("Member Addition IPv6 Error: ") + strerror(errno));
}
break;
}
@@ -181,20 +188,15 @@ void
PeerDiscovery::sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send)
{
nodeId_ = nodeId;
//Set up for Sender
// Setup sender address
sockAddrSend_.setFamily(domain_);
sockAddrSend_.setAddress(domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6);
sockAddrSend_.setPort(port_);
//Setup for send data
int port_node = port_to_send;
uint8_t port_node_binary[2];
PeerDiscovery::inttolitend(port_node,port_node_binary);
//Copy Node id and node port
memcpy (data_send_.data(), nodeId.data(), nodeId.size());
data_send_[InfoHash::size()] = port_node_binary[0];
data_send_[InfoHash::size() + 1] = port_node_binary[1];
// Setup sent data
std::copy_n(nodeId.cbegin(), nodeId.size(), data_send_.begin());
auto portAddr = reinterpret_cast<in_port_t*>(data_send_.data() + dht::InfoHash::size());
*portAddr = htons(port_to_send);
}
void
@@ -219,10 +221,8 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
{
int stopfds_pipe[2];
#ifndef _WIN32
auto status = pipe(stopfds_pipe);
if (status == -1) {
if (pipe(stopfds_pipe) == -1)
throw std::runtime_error(std::string("Can't open pipe: ") + strerror(errno));
}
#else
net::udpPipe(stopfds_pipe);
#endif
@@ -252,29 +252,25 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
}
if (data_coming > 0) {
if(FD_ISSET(stop_readfd, &readfds)){ break; }
if (FD_ISSET(stop_readfd, &readfds)) {
std::array<uint8_t, 64 * 1024> buf;
recv(stop_readfd, buf.data(), buf.size(), 0);
}
std::array<uint8_t,dht::InfoHash::size() + sizeof(in_port_t)> data_receive;
size_t data_receive_size = data_receive.size();
auto from = recvFrom(data_receive.data(), data_receive_size);
//Data_receive_size as a value-result member will hlep to filter packs
// Data_receive_size as a value-result member will hlep to filter packs
if(data_receive_size != data_receive.size()){
perror("Data Received Unmatch");
// std::cerr << "Received invalid peer discovery packet" << std::endl;
continue;
}
std::array<uint8_t,dht::InfoHash::size()> data_infohash;
uint8_t data_port[2];
memcpy (data_infohash.data(), data_receive.data(), dht::InfoHash::size());
data_port[0] = data_receive[dht::InfoHash::size()];
data_port[1] = data_receive[dht::InfoHash::size() + 1];
auto port = PeerDiscovery::litendtoint(data_port);
auto nodeId = dht::InfoHash(data_infohash.data(), dht::InfoHash::size());
dht::InfoHash nodeId;
std::copy_n(data_receive.begin(), dht::InfoHash::size(), nodeId.begin());
auto portAddr = reinterpret_cast<in_port_t*>(data_receive.data() + dht::InfoHash::size());
auto port = ntohs(*portAddr);
if (nodeId != nodeId_){
from.setPort(port);
callback(nodeId, from);
@@ -297,7 +293,7 @@ PeerDiscovery::startDiscovery(PeerDiscoveredCallback callback)
}
void
PeerDiscovery::startPublish(const dht::InfoHash &nodeId, in_port_t port_to_send)
PeerDiscovery::startPublish(const dht::InfoHash& nodeId, in_port_t port_to_send)
{
sender_setup(nodeId, port_to_send);
running_send = std::thread(&PeerDiscovery::sender_thread, this);
@@ -310,7 +306,7 @@ PeerDiscovery::stop()
std::unique_lock<std::mutex> lck(mtx_);
running_ = false;
}
cv_.notify_one();
cv_.notify_all();
if (stop_writefd_ != -1) {
if (write(stop_writefd_, "\0", 1) == -1) {
perror("write");
+1
View File
@@ -545,6 +545,7 @@ struct Dht::Search {
if (a.value->id == vid)
return a.value;
}
return {};
}
bool cancelPut(Value::Id vid) {
+8
View File
@@ -25,10 +25,18 @@
#define IN_IS_ADDR_UNSPECIFIED(a) (((long int) (a)->s_addr) == 0x00000000)
#endif /* IN_IS_ADDR_UNSPECIFIED */
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "(unknown version)"
#endif
namespace dht {
static constexpr std::array<uint8_t, 12> MAPPED_IPV4_PREFIX {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}};
const char* version() {
return PACKAGE_VERSION;
}
std::pair<std::string, std::string>
splitPort(const std::string& s) {
if (s.empty())
+8 -5
View File
@@ -71,7 +71,7 @@ DhtRunnerTester::testListen() {
auto a = dht::InfoHash::get("234");
auto b = dht::InfoHash::get("2345");
auto c = dht::InfoHash::get("23456");
constexpr unsigned N = 64;
constexpr unsigned N = 32;
auto ftokena = node1.listen(a, [&](const std::shared_ptr<dht::Value>&) {
valueCount++;
@@ -114,18 +114,21 @@ DhtRunnerTester::testListen() {
CPPUNIT_ASSERT_EQUAL(N * 2u, putOkCount);
}
CPPUNIT_ASSERT(ftokena.valid());
CPPUNIT_ASSERT(ftokenb.valid());
CPPUNIT_ASSERT(ftokenc.valid());
auto tokena = ftokena.get();
auto tokenb = ftokenb.get();
auto tokenc = ftokenc.get();
// tokenb might be 0 since the callback returns false.
CPPUNIT_ASSERT(tokena);
CPPUNIT_ASSERT(tokenb);
CPPUNIT_ASSERT(tokenc);
CPPUNIT_ASSERT_EQUAL(N + 1u, valueCount.load());
node1.cancelListen(a, tokena);
node1.cancelListen(b, tokena);
node1.cancelListen(c, tokena);
node1.cancelListen(b, std::move(ftokenb));
node1.cancelListen(c, tokenc);
}
} // namespace test
+5 -8
View File
@@ -42,7 +42,7 @@ void PeerDiscoveryTester::testTransmission_ipv4(){
test_n.startPublish(data_n,port_n);
sleep(5);
std::this_thread::sleep_for(std::chrono::seconds(5));
test_n.stop();
test_s.stop();
test_n.join();
@@ -63,8 +63,8 @@ void PeerDiscoveryTester::testTransmission_ipv6(){
int port = 3333;
in_port_t port_n = 50001;
try{
dht::PeerDiscovery test_n(AF_INET6,port);
dht::PeerDiscovery test_s(AF_INET6,port);
dht::PeerDiscovery test_n(AF_INET6, port);
dht::PeerDiscovery test_s(AF_INET6, port);
try{
test_s.startDiscovery([&](const dht::InfoHash& node, const dht::SockAddr& addr){
@@ -74,19 +74,16 @@ void PeerDiscoveryTester::testTransmission_ipv6(){
test_n.startPublish(data_n,port_n);
sleep(5);
std::this_thread::sleep_for(std::chrono::seconds(5));
test_n.stop();
test_s.stop();
test_n.join();
test_s.join();
} catch(std::exception &exception){
perror(exception.what());
CPPUNIT_ASSERT(false);
}
} catch(std::exception &exception){
perror(exception.what());
} catch(std::exception &exception) {
}
}
void PeerDiscoveryTester::tearDown(){}
+17 -4
View File
@@ -29,24 +29,33 @@ extern "C" {
using namespace dht;
void print_usage() {
std::cout << "Usage: dhtnode [-v [-l logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b bootstrap_host[:port]] [--proxyserver local_port]" << std::endl << std::endl;
void print_info() {
std::cout << "dhtnode, a simple OpenDHT command line node runner." << std::endl;
std::cout << "Report bugs to: https://opendht.net" << std::endl;
}
void print_version() {
std::cout << "OpenDHT version " << dht::version() << std::endl;
print_info();
}
void print_usage() {
std::cout << "Usage: dhtnode [-v [-l logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b bootstrap_host[:port]] [--proxyserver local_port]" << std::endl << std::endl;
print_info();
}
void print_id_req() {
std::cout << "An identity is required to perform this operation (run with -i)" << std::endl;
}
void print_node_info(const std::shared_ptr<DhtRunner>& dht, const dht_params& params) {
std::cout << "OpenDht node " << dht->getNodeId() << " running on port " << dht->getBoundPort() << std::endl;
std::cout << "OpenDHT node " << dht->getNodeId() << " running on port " << dht->getBoundPort() << std::endl;
if (params.generate_identity)
std::cout << "Public key ID " << dht->getId() << std::endl;
}
void print_help() {
std::cout << "OpenDht command line interface (CLI)" << std::endl;
std::cout << "OpenDHT command line interface (CLI)" << std::endl;
std::cout << "Possible commands:" << std::endl
<< " h, help Print this help message." << std::endl
<< " x, quit Quit the program." << std::endl
@@ -484,6 +493,10 @@ main(int argc, char **argv)
print_usage();
return 0;
}
if (params.version) {
print_version();
return 0;
}
if (params.daemonize) {
daemonize();
+5
View File
@@ -90,6 +90,7 @@ static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
struct dht_params {
bool help {false}; // print help and exit
bool version {false};
bool log {false};
std::string logfile {};
bool syslog {false};
@@ -124,6 +125,7 @@ static const constexpr struct option long_options[] = {
{"proxyclient", required_argument, nullptr, 'C'},
{"pushserver", required_argument, nullptr, 'y'},
{"devicekey", required_argument, nullptr, 'z'},
{"version", no_argument , nullptr, 'V'},
{nullptr, 0 , nullptr, 0}
};
@@ -173,6 +175,9 @@ parseArgs(int argc, char **argv) {
params.bootstrap.second = std::to_string(DHT_DEFAULT_PORT);
}
break;
case 'V':
params.version = true;
break;
case 'h':
params.help = true;
break;