mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ec83fa56f | ||
|
|
01a2a8d4d9 | ||
|
|
933781ee93 | ||
|
|
bd826b736b | ||
|
|
707a176135 | ||
|
|
19d17e3952 | ||
|
|
26fd35de77 | ||
|
|
fc64b7e1dc |
No files matched your search
@@ -19,9 +19,6 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
**/dhtnode
|
||||
**/dhtchat
|
||||
**/dhtscanner
|
||||
|
||||
# Autotools
|
||||
/ac
|
||||
@@ -76,4 +73,3 @@ doc/Doxyfile
|
||||
|
||||
# build dir
|
||||
build
|
||||
.DS_Store
|
||||
@@ -0,0 +1,4 @@
|
||||
[submodule "argon2"]
|
||||
path = argon2
|
||||
url = https://github.com/P-H-C/phc-winner-argon2
|
||||
ignore = dirty
|
||||
+48
-8
@@ -7,7 +7,7 @@ include(FindPkgConfig)
|
||||
include(cmake/CheckAtomic.cmake)
|
||||
|
||||
set (opendht_VERSION_MAJOR 2)
|
||||
set (opendht_VERSION_MINOR 3.0)
|
||||
set (opendht_VERSION_MINOR 2.0)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -20,6 +20,7 @@ option (OPENDHT_PYTHON "Build Python bindings" OFF)
|
||||
option (OPENDHT_TOOLS "Build DHT tools" ON)
|
||||
option (OPENDHT_SYSTEMD "Install systemd module" OFF)
|
||||
option (OPENDHT_SYSTEMD_UNIT_FILE_LOCATION "Where to install systemd unit file")
|
||||
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
|
||||
option (OPENDHT_LTO "Build with LTO" OFF)
|
||||
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
|
||||
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp" OFF)
|
||||
@@ -27,6 +28,7 @@ option (OPENDHT_PUSH_NOTIFICATIONS "Enable push notifications support" OFF)
|
||||
option (OPENDHT_PROXY_SERVER_IDENTITY "Allow clients to use the node identity" OFF)
|
||||
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
|
||||
option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
|
||||
option (OPENDHT_PROXY_HTTP_PARSER_FORK "Build DHT proxy with custom http_parser to support old API" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(OPENDHT_HTTP "Build embedded http(s) client" OFF "NOT OPENDHT_PROXY_SERVER;NOT OPENDHT_PROXY_CLIENT" ON)
|
||||
option (OPENDHT_PEER_DISCOVERY "Enable multicast peer discovery" ON)
|
||||
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
|
||||
@@ -44,12 +46,22 @@ if (NOT MSVC)
|
||||
find_package (Threads)
|
||||
find_package (PkgConfig REQUIRED)
|
||||
find_package (GnuTLS 3.3 REQUIRED)
|
||||
pkg_search_module (Nettle REQUIRED nettle)
|
||||
pkg_search_module (Nettle nettle)
|
||||
find_package (Msgpack 1.2 REQUIRED)
|
||||
if (OPENDHT_TOOLS)
|
||||
find_package (Readline 6 REQUIRED)
|
||||
endif ()
|
||||
pkg_search_module(argon2 REQUIRED libargon2)
|
||||
if (NOT OPENDHT_ARGON2)
|
||||
pkg_search_module(argon2 libargon2)
|
||||
if (argon2_FOUND)
|
||||
message("-- Found Argon2: " ${argon2_LIBRARY_DIRS} " (found version \"" ${argon2_VERSION} "\")")
|
||||
link_directories (${argon2_LIBRARY_DIRS})
|
||||
else ()
|
||||
message("Argon2 not found, using included version.")
|
||||
set(OPENDHT_ARGON2 ON)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
pkg_search_module(Jsoncpp jsoncpp)
|
||||
if (Jsoncpp_FOUND)
|
||||
add_definitions(-DOPENDHT_JSONCPP)
|
||||
@@ -83,6 +95,9 @@ if (NOT MSVC)
|
||||
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
|
||||
endif()
|
||||
endif()
|
||||
if (OPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
add_definitions(-DOPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
endif()
|
||||
else ()
|
||||
set(OPENDHT_PROXY_OPENSSL OFF)
|
||||
endif ()
|
||||
@@ -172,7 +187,6 @@ if (Jsoncpp_INCLUDE_DIRS)
|
||||
endif ()
|
||||
link_directories (${Nettle_LIBRARY_DIRS})
|
||||
link_directories (${Jsoncpp_LIBRARY_DIRS})
|
||||
link_directories (${argon2_LIBRARY_DIRS})
|
||||
include_directories (
|
||||
./
|
||||
include/
|
||||
@@ -300,6 +314,23 @@ if (OPENDHT_HTTP)
|
||||
)
|
||||
endif ()
|
||||
|
||||
if(OPENDHT_ARGON2)
|
||||
# make sure argon2 submodule is up to date and initialized
|
||||
message("Initializing Argon2 submodule")
|
||||
execute_process(COMMAND git submodule update --init)
|
||||
|
||||
# add local argon2 files to build
|
||||
list (APPEND opendht_SOURCES
|
||||
argon2/src/argon2.c
|
||||
argon2/src/core.c
|
||||
argon2/src/blake2/blake2b.c
|
||||
argon2/src/thread.c
|
||||
argon2/src/ref.c
|
||||
argon2/src/encoding.c
|
||||
)
|
||||
include_directories(argon2/include/)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
list (APPEND opendht_HEADERS src/compat/msvc/unistd.h)
|
||||
endif ()
|
||||
@@ -312,7 +343,11 @@ if (OPENDHT_STATIC)
|
||||
${opendht_HEADERS}
|
||||
)
|
||||
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE argon2)
|
||||
else ()
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
target_link_libraries(opendht-static
|
||||
PRIVATE ${argon2_LIBRARIES}
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_STATIC_LIBRARIES}
|
||||
@@ -377,20 +412,25 @@ if (OPENDHT_SHARED)
|
||||
set_target_properties (opendht PROPERTIES IMPORT_SUFFIX "_import.lib")
|
||||
set_target_properties (opendht PROPERTIES SOVERSION ${opendht_VERSION_MAJOR} VERSION ${opendht_VERSION})
|
||||
target_compile_definitions(opendht PRIVATE OPENDHT_BUILD)
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht SYSTEM PRIVATE argon2)
|
||||
else ()
|
||||
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
if (APPLE)
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${argon2_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
|
||||
SYSTEM "-framework CoreFoundation" "-framework Security")
|
||||
else ()
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${argon2_LIBRARIES})
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
|
||||
endif ()
|
||||
|
||||
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
|
||||
|
||||
@@ -103,7 +103,7 @@ for r in results:
|
||||
|
||||
## Contact
|
||||
|
||||
IRC: join us on Libera.chat at [`#opendht`](https://web.libera.chat/#opendht).
|
||||
IRC: join us on Freenode at [`#opendht`](https://webchat.freenode.net/?channels=%23opendht).
|
||||
|
||||
## License
|
||||
Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
|
||||
Submodule
+1
Submodule argon2 added at 62358ba212.
@@ -1 +1,2 @@
|
||||
git submodule update --init
|
||||
autoreconf --install --verbose -Wall
|
||||
+30
-3
@@ -1,6 +1,6 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 2)
|
||||
m4_define([opendht_minor_version], 3)
|
||||
m4_define([opendht_minor_version], 2)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
@@ -132,8 +132,6 @@ AM_CONDITIONAL(PROXY_CLIENT_OR_SERVER, test x$proxy_client == xyes || test x$pro
|
||||
PKG_CHECK_MODULES([Nettle], [nettle >= 2.4])
|
||||
PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.3])
|
||||
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
|
||||
PKG_CHECK_MODULES([Argon2], [libargon2])
|
||||
AC_SUBST(argon2_lib, [", libargon2"])
|
||||
|
||||
AC_ARG_WITH([jsoncpp], AS_HELP_STRING([--without-jsoncpp], [Build without JsonCpp support]))
|
||||
AS_IF([test "x$with_jsoncpp" != "xno"],
|
||||
@@ -159,6 +157,14 @@ AS_IF([test "x$have_openssl" = "xyes"], [
|
||||
AC_MSG_NOTICE([Not using OpenSSL])
|
||||
])
|
||||
|
||||
AC_ARG_WITH([http_parser_fork], AS_HELP_STRING([--with-http-parser-fork], [Build with http_parser fork to support old API]))
|
||||
AS_IF([test "x$with_http_parser_fork" = "xyes"],[
|
||||
AC_MSG_NOTICE([Using http_parser fork])
|
||||
AC_DEFINE([OPENDHT_PROXY_HTTP_PARSER_FORK], [], [Define if using http parser fork])
|
||||
], [
|
||||
AC_MSG_NOTICE([Not using http_parser fork])
|
||||
])
|
||||
|
||||
AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
AC_CHECK_HEADERS([asio.hpp], exit,, AC_MSG_ERROR([Missing Asio headers files]))
|
||||
CXXFLAGS="${CXXFLAGS} -DASIO_STANDALONE"
|
||||
@@ -177,6 +183,27 @@ AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
|
||||
CXXFLAGS="${CXXFLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
|
||||
|
||||
dnl Check for Argon2
|
||||
AC_ARG_WITH([argon2], AS_HELP_STRING([--without-argon2], [Use included Argon2]))
|
||||
AS_IF([test "x$with_argon2" != "xno"],
|
||||
[PKG_CHECK_MODULES([Argon2], [libargon2], [have_argon2=yes], [have_argon2=no])],
|
||||
[have_argon2=no])
|
||||
AS_IF([test "x$have_argon2" = "xyes"], [
|
||||
AC_MSG_NOTICE([Using system Argon2])
|
||||
AC_SUBST(argon2_lib, [", libargon2"])
|
||||
], [
|
||||
AS_IF([test "x$with_argon2" = "xyes"], [
|
||||
AC_MSG_ERROR([Argon2 requested but not found])
|
||||
],[
|
||||
AC_MSG_NOTICE([Using included Argon2])
|
||||
AC_SUBST(Argon2_CFLAGS, "-I\${top_srcdir}/argon2/src -I\${top_srcdir}/argon2/include")
|
||||
AC_SUBST(Argon2_LIBS, "libargon2.la")
|
||||
AC_SUBST(Argon2_LDFLAGS, "-L\${abs_top_srcdir}/argon2/src/.libs")
|
||||
])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([WITH_INCLUDED_ARGON2], [test "x$have_argon2" = "xno"])
|
||||
|
||||
AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes)
|
||||
AM_CONDITIONAL(ENABLE_TOOLS, test x$build_tools == xyes)
|
||||
AM_COND_IF([ENABLE_TOOLS], [
|
||||
|
||||
@@ -78,6 +78,7 @@ struct OPENDHT_PUBLIC NodeStats {
|
||||
|
||||
struct OPENDHT_PUBLIC NodeInfo {
|
||||
InfoHash id;
|
||||
PkId pkid;
|
||||
InfoHash node_id;
|
||||
NodeStats ipv4 {};
|
||||
NodeStats ipv6 {};
|
||||
@@ -94,7 +95,7 @@ struct OPENDHT_PUBLIC NodeInfo {
|
||||
explicit NodeInfo(const Json::Value& v);
|
||||
#endif
|
||||
|
||||
MSGPACK_DEFINE_MAP(id, node_id, ipv4, ipv6)
|
||||
MSGPACK_DEFINE_MAP(id, pkid, node_id, ipv4, ipv6)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -167,6 +168,7 @@ using ShutdownCallback = std::function<void()>;
|
||||
using IdentityAnnouncedCb = std::function<void(bool)>;
|
||||
|
||||
using CertificateStoreQuery = std::function<std::vector<std::shared_ptr<crypto::Certificate>>(const InfoHash& pk_id)>;
|
||||
using CertificateStoreLongQuery = std::function<std::vector<std::shared_ptr<crypto::Certificate>>(const PkId& pk_id)>;
|
||||
|
||||
typedef bool (*GetCallbackRaw)(std::shared_ptr<Value>, void *user_data);
|
||||
typedef bool (*ValueCallbackRaw)(std::shared_ptr<Value>, bool expired, void *user_data);
|
||||
|
||||
@@ -164,9 +164,7 @@ struct OPENDHT_PUBLIC PrivateKey
|
||||
~PrivateKey();
|
||||
explicit operator bool() const { return key; }
|
||||
|
||||
const PublicKey& getPublicKey() const;
|
||||
const std::shared_ptr<PublicKey>& getSharedPublicKey() const;
|
||||
|
||||
PublicKey getPublicKey() const;
|
||||
int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const;
|
||||
Blob serialize(const std::string& password = {}) const;
|
||||
|
||||
@@ -201,7 +199,7 @@ private:
|
||||
PrivateKey& operator=(const PrivateKey&) = delete;
|
||||
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
|
||||
|
||||
mutable std::shared_ptr<PublicKey> publicKey_ {};
|
||||
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC RevocationList
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
if (v.owner) {
|
||||
owner = v.owner;
|
||||
from = v.owner->getId();
|
||||
fromId = v.owner->getLongId();
|
||||
}
|
||||
BaseClass::unpackValue(v);
|
||||
}
|
||||
@@ -79,6 +80,7 @@ public:
|
||||
|
||||
Sp<crypto::PublicKey> owner;
|
||||
dht::InfoHash from;
|
||||
dht::PkId fromId;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb, bool stop = false) override;
|
||||
void shutdown(ShutdownCallback cb) override;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
|
||||
@@ -61,10 +61,8 @@ public:
|
||||
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
* stop: if true, cancel ongoing operations and call their 'done'
|
||||
* callbacks synchronously.
|
||||
*/
|
||||
virtual void shutdown(ShutdownCallback cb, bool stop = false) = 0;
|
||||
virtual void shutdown(ShutdownCallback cb) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb, bool) override;
|
||||
void shutdown(ShutdownCallback cb) override;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
|
||||
@@ -74,6 +74,7 @@ public:
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery {};
|
||||
StatusCallback statusChangedCallback {};
|
||||
CertificateStoreQuery certificateStore {};
|
||||
CertificateStoreLongQuery certificateStoreSha256 {};
|
||||
IdentityAnnouncedCb identityAnnouncedCb {};
|
||||
Context() {}
|
||||
};
|
||||
@@ -257,6 +258,16 @@ public:
|
||||
}
|
||||
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
|
||||
void putEncrypted(InfoHash hash, PkId to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, PkId to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, PkId to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, PkId to, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
@@ -314,7 +325,7 @@ public:
|
||||
* Get the public key fingerprint if an identity is used with this node, 0 otherwise.
|
||||
*/
|
||||
InfoHash getId() const;
|
||||
std::shared_ptr<crypto::PublicKey> getPublicKey() const;
|
||||
PkId getLongId() const;
|
||||
|
||||
/**
|
||||
* Get the ID of the DHT node.
|
||||
@@ -379,7 +390,7 @@ public:
|
||||
|
||||
void findCertificate(InfoHash hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
|
||||
void registerCertificate(std::shared_ptr<crypto::Certificate> cert);
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method, CertificateStoreLongQuery&& query_sha256_method = {});
|
||||
|
||||
/**
|
||||
* @param port: Local port to bind. Both IPv4 and IPv6 will be tried (ANY).
|
||||
@@ -420,7 +431,7 @@ public:
|
||||
/**
|
||||
* Gracefuly disconnect from network.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb = {}, bool stop = false);
|
||||
void shutdown(ShutdownCallback cb = {});
|
||||
|
||||
/**
|
||||
* Quit and wait for all threads to terminate.
|
||||
|
||||
@@ -375,3 +375,15 @@ private:
|
||||
} // namespace http
|
||||
} // namespace dht
|
||||
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
namespace restinio
|
||||
{
|
||||
/* Custom HTTP-methods for RESTinio > 0.5.0.
|
||||
* https://github.com/Stiffstream/restinio/issues/26
|
||||
*/
|
||||
constexpr const restinio::http_method_id_t method_listen {HTTP_LISTEN, "LISTEN"};
|
||||
constexpr const restinio::http_method_id_t method_stats {HTTP_STATS, "STATS"};
|
||||
constexpr const restinio::http_method_id_t method_sign {HTTP_SIGN, "SIGN"};
|
||||
constexpr const restinio::http_method_id_t method_encrypt {HTTP_ENCRYPT, "ENCRYPT"};
|
||||
} // namespace restinio
|
||||
#endif
|
||||
@@ -342,7 +342,7 @@ Hash<N>::getRandom(Rd& rdev)
|
||||
return h;
|
||||
}
|
||||
|
||||
struct alignas(std::max_align_t) HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
struct HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
HexMap() {
|
||||
for (size_t i=0; i<size(); i++) {
|
||||
auto& e = (*this)[i];
|
||||
@@ -376,7 +376,7 @@ template <size_t N>
|
||||
const char*
|
||||
Hash<N>::to_c_str() const
|
||||
{
|
||||
alignas(std::max_align_t) thread_local std::array<char, N*2+1> buf;
|
||||
thread_local std::array<char, N*2+1> buf;
|
||||
for (size_t i=0; i<N; i++) {
|
||||
auto b = buf.data()+i*2;
|
||||
const auto& m = hex_map[data_[i]];
|
||||
|
||||
@@ -61,9 +61,6 @@ public:
|
||||
PkId getLongId() const {
|
||||
return key_ ? key_->getPublicKey().getLongId() : PkId();
|
||||
}
|
||||
Sp<crypto::PublicKey> getPublicKey() const {
|
||||
return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey>{};
|
||||
}
|
||||
|
||||
ValueType secureType(ValueType&& type);
|
||||
|
||||
@@ -118,6 +115,10 @@ public:
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
void putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
|
||||
void putEncrypted(const InfoHash& hash, const PkId& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
|
||||
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
@@ -141,20 +142,27 @@ public:
|
||||
Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
|
||||
void findCertificate(const PkId& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
|
||||
void findPublicKey(const PkId& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
|
||||
Sp<crypto::Certificate> registerCertificate(const PkId& node, const Blob& cert);
|
||||
Sp<crypto::Certificate> getCertificate(const PkId& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const PkId& node) const;
|
||||
|
||||
/**
|
||||
* Allows to set a custom callback called by the library to find a locally-stored certificate.
|
||||
* The search key used is the public key ID, so there may be multiple certificates retured, signed with
|
||||
* the same private key.
|
||||
*/
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method) {
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method, CertificateStoreLongQuery&& query_sha256_method) {
|
||||
localQueryMethod_ = std::move(query_method);
|
||||
localQuerySha256Method_ = std::move(query_sha256_method);
|
||||
}
|
||||
|
||||
/**
|
||||
* SecureDht to Dht proxy
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb, bool stop = false) override {
|
||||
dht_->shutdown(cb, stop);
|
||||
void shutdown(ShutdownCallback cb) override {
|
||||
dht_->shutdown(cb);
|
||||
}
|
||||
void dumpTables() const override {
|
||||
dht_->dumpTables();
|
||||
@@ -358,10 +366,13 @@ private:
|
||||
|
||||
// method to query the local certificate store
|
||||
CertificateStoreQuery localQueryMethod_ {};
|
||||
CertificateStoreLongQuery localQuerySha256Method_ {};
|
||||
|
||||
// our certificate cache
|
||||
std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
|
||||
std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
|
||||
std::map<PkId, Sp<crypto::Certificate>> nodesCertificatesLong_ {};
|
||||
std::map<PkId, Sp<crypto::PublicKey>> nodesPubKeysLong_ {};
|
||||
|
||||
std::atomic_bool forward_all_ {false};
|
||||
bool enableCache_ {false};
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
* Build from existing address.
|
||||
*/
|
||||
SockAddr(const sockaddr* sa, socklen_t length) {
|
||||
if (length > static_cast<socklen_t>(sizeof(sockaddr_storage)))
|
||||
if (length > (socklen_t)sizeof(sockaddr_storage))
|
||||
throw std::runtime_error("Socket address length is too large");
|
||||
set(sa, length);
|
||||
}
|
||||
|
||||
@@ -93,71 +93,4 @@ private:
|
||||
void schedule();
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC ExecutionContext {
|
||||
public:
|
||||
ExecutionContext(ThreadPool& pool)
|
||||
: threadPool_(pool), state_(std::make_shared<SharedState>())
|
||||
{}
|
||||
|
||||
~ExecutionContext() {
|
||||
state_->destroy();
|
||||
}
|
||||
|
||||
/** Wait for ongoing tasks to complete execution and drop other pending tasks */
|
||||
void stop() {
|
||||
state_->destroy(false);
|
||||
}
|
||||
|
||||
void run(std::function<void()>&& task) {
|
||||
std::lock_guard<std::mutex> lock(state_->mtx);
|
||||
if (state_->shutdown_) return;
|
||||
state_->pendingTasks++;
|
||||
threadPool_.get().run([task = std::move(task), state = state_] {
|
||||
state->run(task);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
struct SharedState {
|
||||
std::mutex mtx {};
|
||||
std::condition_variable cv {};
|
||||
unsigned pendingTasks {0};
|
||||
unsigned ongoingTasks {0};
|
||||
/** When true, prevents new tasks to be scheduled */
|
||||
bool shutdown_ {false};
|
||||
/** When true, prevents scheduled tasks to be executed */
|
||||
std::atomic_bool destroyed {false};
|
||||
|
||||
void destroy(bool wait = true) {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
if (destroyed) return;
|
||||
if (wait) {
|
||||
cv.wait(lock, [this] { return pendingTasks == 0 && ongoingTasks == 0; });
|
||||
}
|
||||
shutdown_ = true;
|
||||
if (not wait) {
|
||||
cv.wait(lock, [this] { return ongoingTasks == 0; });
|
||||
}
|
||||
destroyed = true;
|
||||
}
|
||||
|
||||
void run(const std::function<void()>& task) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
pendingTasks--;
|
||||
ongoingTasks++;
|
||||
}
|
||||
if (destroyed) return;
|
||||
task();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
ongoingTasks--;
|
||||
cv.notify_all();
|
||||
}
|
||||
}
|
||||
};
|
||||
std::reference_wrapper<ThreadPool> threadPool_;
|
||||
std::shared_ptr<SharedState> state_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -356,7 +356,7 @@ struct OPENDHT_PUBLIC Value
|
||||
void sign(const crypto::PrivateKey& key) {
|
||||
if (isEncrypted())
|
||||
throw DhtException("Can't sign encrypted data.");
|
||||
owner = key.getSharedPublicKey();
|
||||
owner = std::make_shared<crypto::PublicKey>(key.getPublicKey());
|
||||
signature = key.sign(getToSign());
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -329,11 +329,11 @@ cdef class PrivateKey(_WithID):
|
||||
cdef shared_ptr[cpp.PrivateKey] _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.get().getSharedPublicKey().get().getId()
|
||||
h._infohash = self._key.get().getPublicKey().getId()
|
||||
return h
|
||||
def getPublicKey(self):
|
||||
pk = PublicKey()
|
||||
pk._key = self._key.get().getSharedPublicKey()
|
||||
pk._key = self._key.get().getPublicKey()
|
||||
return pk
|
||||
def decrypt(self, bytes dat):
|
||||
cdef size_t d_len = len(dat)
|
||||
@@ -358,17 +358,17 @@ cdef class PrivateKey(_WithID):
|
||||
return k
|
||||
|
||||
cdef class PublicKey(_WithID):
|
||||
cdef cpp.shared_ptr[cpp.PublicKey] _key
|
||||
cdef cpp.PublicKey _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.get().getId()
|
||||
h._infohash = self._key.getId()
|
||||
return h
|
||||
def encrypt(self, bytes dat):
|
||||
cdef size_t d_len = len(dat)
|
||||
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
|
||||
cdef cpp.Blob indat
|
||||
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
|
||||
cdef cpp.Blob encrypted = self._key.get().encrypt(indat)
|
||||
cdef cpp.Blob encrypted = self._key.encrypt(indat)
|
||||
cdef char* encrypted_c_str = <char *>encrypted.data()
|
||||
cdef Py_ssize_t length = encrypted.size()
|
||||
return encrypted_c_str[:length]
|
||||
@@ -440,7 +440,7 @@ cdef class Identity(object):
|
||||
property publickey:
|
||||
def __get__(self):
|
||||
k = PublicKey()
|
||||
k._key = self._id.first.get().getSharedPublicKey()
|
||||
k._key = self._id.first.get().getPublicKey()
|
||||
return k
|
||||
property certificate:
|
||||
def __get__(self):
|
||||
|
||||
@@ -97,7 +97,7 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto":
|
||||
|
||||
cdef cppclass PrivateKey:
|
||||
PrivateKey()
|
||||
shared_ptr[PublicKey] getSharedPublicKey() const
|
||||
PublicKey getPublicKey() const
|
||||
Blob decrypt(Blob data) const
|
||||
@staticmethod
|
||||
PrivateKey generate()
|
||||
|
||||
+28
-1
@@ -2,7 +2,7 @@ lib_LTLIBRARIES = libopendht.la
|
||||
|
||||
libopendht_la_CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/include/opendht @Argon2_CFLAGS@ @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@ @OpenSSL_CFLAGS@ @Fmt_CFLAGS@
|
||||
libopendht_la_LIBADD = @Argon2_LIBS@ @JsonCpp_LIBS@ @GnuTLS_LIBS@ @Nettle_LIBS@ @OpenSSL_LIBS@ @Fmt_LIBS@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ @Argon2_LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_SOURCES = \
|
||||
dht.cpp \
|
||||
storage.h \
|
||||
@@ -87,3 +87,30 @@ endif
|
||||
|
||||
clean-local:
|
||||
rm -rf libargon2.la
|
||||
|
||||
######################
|
||||
# ARGON2 submodule #
|
||||
######################
|
||||
|
||||
if WITH_INCLUDED_ARGON2
|
||||
noinst_LTLIBRARIES = libargon2.la
|
||||
libopendht_la_DEPENDENCIES = libargon2.la
|
||||
|
||||
libargon2_la_CFLAGS = -std=c89 -fPIC -pthread -O3 -Wall -I@top_builddir@/argon2/include -I@top_builddir@/argon2/src
|
||||
libargon2_la_SOURCES = \
|
||||
@top_builddir@/argon2/src/argon2.c \
|
||||
@top_builddir@/argon2/src/core.c \
|
||||
@top_builddir@/argon2/src/blake2/blake2b.c \
|
||||
@top_builddir@/argon2/src/thread.c \
|
||||
@top_builddir@/argon2/src/ref.c \
|
||||
@top_builddir@/argon2/src/encoding.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
@top_builddir@/argon2/include/argon2.h \
|
||||
@top_builddir@/argon2/src/blake2/blake2.h \
|
||||
@top_builddir@/argon2/src/blake2/blake2-impl.h \
|
||||
@top_builddir@/argon2/src/blake2/blamka-round-ref.h \
|
||||
@top_builddir@/argon2/src/core.h \
|
||||
@top_builddir@/argon2/src/encoding.h \
|
||||
@top_builddir@/argon2/src/thread.h
|
||||
endif
|
||||
@@ -141,6 +141,8 @@ NodeInfo::toJson() const
|
||||
Json::Value val;
|
||||
if (id)
|
||||
val["id"] = id.toString();
|
||||
if (pkid)
|
||||
val["pkid"] = pkid.toString();
|
||||
val["node_id"] = node_id.toString();
|
||||
val["ipv4"] = ipv4.toJson();
|
||||
val["ipv6"] = ipv6.toJson();
|
||||
@@ -152,6 +154,8 @@ NodeInfo::NodeInfo(const Json::Value& v)
|
||||
{
|
||||
if (v.isMember("id"))
|
||||
id = InfoHash(v["id"].asString());
|
||||
if (v.isMember("pkid"))
|
||||
pkid = PkId(v["pkid"].asString());
|
||||
node_id = InfoHash(v["node_id"].asString());
|
||||
ipv4 = NodeStats(v["ipv4"]);
|
||||
ipv6 = NodeStats(v["ipv6"]);
|
||||
|
||||
+11
-15
@@ -368,22 +368,13 @@ PrivateKey::serialize(uint8_t* out, size_t* out_len, const std::string& password
|
||||
: gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, password.c_str(), GNUTLS_PKCS_PBES2_AES_256, out, out_len);
|
||||
}
|
||||
|
||||
const PublicKey&
|
||||
PublicKey
|
||||
PrivateKey::getPublicKey() const
|
||||
{
|
||||
return *getSharedPublicKey();
|
||||
}
|
||||
|
||||
const std::shared_ptr<PublicKey>&
|
||||
PrivateKey::getSharedPublicKey() const
|
||||
{
|
||||
if (publicKey_)
|
||||
return publicKey_;
|
||||
auto pk = std::make_shared<PublicKey>();
|
||||
if (auto err = gnutls_pubkey_import_privkey(pk->pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
|
||||
PublicKey pk;
|
||||
if (auto err = gnutls_pubkey_import_privkey(pk.pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
|
||||
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
|
||||
publicKey_ = pk;
|
||||
return publicKey_;
|
||||
return pk;
|
||||
}
|
||||
|
||||
PublicKey::PublicKey()
|
||||
@@ -549,7 +540,12 @@ PublicKey::getId() const
|
||||
return {};
|
||||
InfoHash id;
|
||||
size_t sz = id.size();
|
||||
if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz))
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030401
|
||||
const int flags = 0;
|
||||
#else
|
||||
const int flags = (id.size() == 32) ? GNUTLS_KEYID_USE_SHA256 : 0;
|
||||
#endif
|
||||
if (auto err = gnutls_pubkey_get_key_id(pk, flags, id.data(), &sz))
|
||||
throw CryptoException(std::string("Can't get public key ID: ") + gnutls_strerror(err));
|
||||
if (sz != id.size())
|
||||
throw CryptoException("Can't get public key ID: wrong output length.");
|
||||
@@ -1173,7 +1169,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
}
|
||||
|
||||
// TODO: compute the subject key using the recommended RFC method
|
||||
const auto& pk = key.getPublicKey();
|
||||
auto pk = key.getPublicKey();
|
||||
auto pk_id = pk.getId();
|
||||
const std::string uid_str = pk_id.toString();
|
||||
|
||||
|
||||
+6
-45
@@ -30,8 +30,6 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace dht {
|
||||
|
||||
using namespace std::placeholders;
|
||||
@@ -79,27 +77,11 @@ Dht::Kad::getStatus(time_point now) const
|
||||
}
|
||||
|
||||
void
|
||||
Dht::shutdown(ShutdownCallback cb, bool stop)
|
||||
Dht::shutdown(ShutdownCallback cb)
|
||||
{
|
||||
if (not persistPath.empty())
|
||||
saveState(persistPath);
|
||||
|
||||
if (stop) {
|
||||
for (auto dht : {&dht4, &dht6}) {
|
||||
for (auto& sr : dht->searches) {
|
||||
for (const auto& r : sr.second->callbacks)
|
||||
r.second.done_cb(false, {});
|
||||
sr.second->callbacks.clear();
|
||||
for (const auto& a : sr.second->announce) {
|
||||
if (a.callback) a.callback(false, {});
|
||||
}
|
||||
sr.second->announce.clear();
|
||||
sr.second->listeners.clear();
|
||||
}
|
||||
}
|
||||
network_engine.clear();
|
||||
}
|
||||
|
||||
if (not maintain_storage) {
|
||||
if (cb) cb();
|
||||
return;
|
||||
@@ -491,7 +473,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
/* only put the value if the node doesn't already have it */
|
||||
if (not hasValue or seq_no < a.value->seq) {
|
||||
if (logger_)
|
||||
logger_->d(sr->id, sn->node->id, "[search %s] [node %s] sending 'put' (vid: %016" PRIx64 ")",
|
||||
logger_->d(sr->id, sn->node->id, "[search %s] [node %s] sending 'put' (vid: %d)",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
auto created = a.permanent ? time_point::max() : a.created;
|
||||
sn->acked[a.value->id] = {
|
||||
@@ -500,7 +482,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
};
|
||||
} else if (hasValue and a.permanent) {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %016" PRIx64 ")",
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %d)",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
sn->acked[a.value->id] = {
|
||||
network_engine.sendRefreshValue(sn->node, sr->id, a.value->id, sn->token, onDone,
|
||||
@@ -530,7 +512,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
};
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] already has value (vid: %016" PRIx64 "). Aborting.",
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] already has value (vid: %d). Aborting.",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
auto ack_req = std::make_shared<net::Request>(net::Request::State::COMPLETED);
|
||||
ack_req->reply_time = now;
|
||||
@@ -569,7 +551,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
sendQuery = true;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, n.node->id, "[search %s] [node %s] sending 'put' (vid: %016" PRIx64 ")",
|
||||
logger_->w(sr->id, n.node->id, "[search %s] [node %s] sending 'put' (vid: %d)",
|
||||
sr->id.toString().c_str(), n.node->toString().c_str(), a.value->id);
|
||||
n.acked[a.value->id] = {
|
||||
network_engine.sendAnnounceValue(n.node, sr->id, a.value, a.created, n.token, onDone, onExpired),
|
||||
@@ -875,11 +857,6 @@ Dht::listenTo(const InfoHash& id, sa_family_t af, ValueCallback cb, Value::Filte
|
||||
size_t
|
||||
Dht::listen(const InfoHash& id, ValueCallback cb, Value::Filter f, Where where)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Listen called with invalid key");
|
||||
return 0;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
|
||||
auto token = ++listener_token;
|
||||
@@ -962,9 +939,7 @@ struct GetStatus : public OpStatus {
|
||||
void
|
||||
Dht::put(const InfoHash& id, Sp<Value> val, DoneCallback callback, time_point created, bool permanent)
|
||||
{
|
||||
if (not id or not val) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Put called with invalid key or value");
|
||||
if (not val) {
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
@@ -1034,13 +1009,6 @@ bool callbackWrapper(Cb get_cb, DoneCallback done_cb, const std::vector<Sp<T>>&
|
||||
void
|
||||
Dht::get(const InfoHash& id, GetCallback getcb, DoneCallback donecb, Value::Filter&& filter, Where&& where)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Get called with invalid key");
|
||||
if (donecb)
|
||||
donecb(false, {});
|
||||
return;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
|
||||
auto op = std::make_shared<GetStatus<std::map<Value::Id, Sp<Value>>>>();
|
||||
@@ -1081,13 +1049,6 @@ Dht::get(const InfoHash& id, GetCallback getcb, DoneCallback donecb, Value::Filt
|
||||
|
||||
void Dht::query(const InfoHash& id, QueryCallback cb, DoneCallback done_cb, Query&& q)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Query called with invalid key");
|
||||
if (done_cb)
|
||||
done_cb(false, {});
|
||||
return;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
auto op = std::make_shared<GetStatus<std::vector<Sp<FieldValueIndex>>>>();
|
||||
auto f = q.where.getFilter();
|
||||
|
||||
@@ -242,7 +242,7 @@ DhtProxyClient::cancelAllListeners()
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClient::shutdown(ShutdownCallback cb, bool)
|
||||
DhtProxyClient::shutdown(ShutdownCallback cb)
|
||||
{
|
||||
stop();
|
||||
if (cb)
|
||||
@@ -829,8 +829,13 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
|
||||
restinio::http_request_header_t header;
|
||||
if (deviceKey_.empty()){ // listen
|
||||
method = ListenMethod::LISTEN;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
header.method(restinio::method_listen);
|
||||
header.request_target("/" + key.toString());
|
||||
#else
|
||||
header.method(restinio::http_method_get());
|
||||
header.request_target("/key/" + key.toString() + "/listen");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
method = ListenMethod::SUBSCRIBE;
|
||||
@@ -1146,8 +1151,13 @@ DhtProxyClient::restartListeners(const asio::error_code &ec)
|
||||
auto cb = listener.cb;
|
||||
// define header
|
||||
restinio::http_request_header_t header;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
header.method(restinio::method_listen);
|
||||
header.request_target("/" + search.first.toString());
|
||||
#else
|
||||
header.method(restinio::http_method_get());
|
||||
header.request_target("/key/" + search.first.toString() + "/listen");
|
||||
#endif
|
||||
sendListen(header, cb, opstate, listener, ListenMethod::LISTEN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,26 @@
|
||||
using namespace std::placeholders;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
namespace restinio {
|
||||
struct custom_http_methods_t
|
||||
{
|
||||
static constexpr restinio::http_method_id_t from_nodejs(int m) noexcept {
|
||||
if(m == method_listen.raw_id())
|
||||
return method_listen;
|
||||
else if(m == method_stats.raw_id())
|
||||
return method_stats;
|
||||
else if(m == method_sign.raw_id())
|
||||
return method_sign;
|
||||
else if(m == method_encrypt.raw_id())
|
||||
return method_encrypt;
|
||||
else
|
||||
return restinio::default_http_methods_t::from_nodejs(m);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
constexpr char RESP_MSG_JSON_INCORRECT[] = "{\"err:\":\"Incorrect JSON\"}";
|
||||
constexpr char RESP_MSG_SERVICE_UNAVAILABLE[] = "{\"err\":\"Incorrect DhtRunner\"}";
|
||||
@@ -136,6 +156,9 @@ DhtProxyServer::onConnectionClosed(restinio::connection_id_t id)
|
||||
struct DhtProxyServer::RestRouterTraitsTls : public restinio::default_tls_traits_t
|
||||
{
|
||||
using timer_manager_t = restinio::asio_timer_manager_t;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
using http_methods_mapper_t = restinio::custom_http_methods_t;
|
||||
#endif
|
||||
using logger_t = opendht_logger_t;
|
||||
using request_handler_t = RestRouter;
|
||||
using connection_state_listener_t = ConnectionListener;
|
||||
@@ -143,6 +166,9 @@ struct DhtProxyServer::RestRouterTraitsTls : public restinio::default_tls_traits
|
||||
struct DhtProxyServer::RestRouterTraits : public restinio::default_traits_t
|
||||
{
|
||||
using timer_manager_t = restinio::asio_timer_manager_t;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
using http_methods_mapper_t = restinio::custom_http_methods_t;
|
||||
#endif
|
||||
using logger_t = opendht_logger_t;
|
||||
using request_handler_t = RestRouter;
|
||||
using connection_state_listener_t = ConnectionListener;
|
||||
@@ -587,6 +613,11 @@ DhtProxyServer::createRestRouter()
|
||||
// **************************** LEGACY ROUTES ****************************
|
||||
// node.info
|
||||
router->http_get("/", std::bind(&DhtProxyServer::getNodeInfo, this, _1, _2));
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// node.stats
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_stats.raw_id()),
|
||||
"/", std::bind(&DhtProxyServer::getStats, this, _1, _2));
|
||||
#endif
|
||||
// key.options
|
||||
router->add_handler(restinio::http_method_options(),
|
||||
"/:hash", std::bind(&DhtProxyServer::options, this, _1, _2));
|
||||
@@ -594,6 +625,11 @@ DhtProxyServer::createRestRouter()
|
||||
router->http_get("/:hash", std::bind(&DhtProxyServer::get, this, _1, _2));
|
||||
// key.post
|
||||
router->http_post("/:hash", std::bind(&DhtProxyServer::put, this, _1, _2));
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// key.listen
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_listen.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::listen, this, _1, _2));
|
||||
#endif
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
// key.subscribe
|
||||
router->add_handler(restinio::http_method_subscribe(),
|
||||
@@ -603,6 +639,14 @@ DhtProxyServer::createRestRouter()
|
||||
"/:hash", std::bind(&DhtProxyServer::unsubscribe, this, _1, _2));
|
||||
#endif //OPENDHT_PUSH_NOTIFICATIONS
|
||||
#ifdef OPENDHT_PROXY_SERVER_IDENTITY
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// key.sign
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_sign.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::putSigned, this, _1, _2));
|
||||
// key.encrypt
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_encrypt.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::putEncrypted, this, _1, _2));
|
||||
#endif
|
||||
#endif // OPENDHT_PROXY_SERVER_IDENTITY
|
||||
|
||||
// **************************** NEW ROUTES ****************************
|
||||
|
||||
+66
-56
@@ -119,24 +119,22 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
local6.setFamily(AF_INET6);
|
||||
}
|
||||
auto state_path = config.dht_config.node_config.persist_path;
|
||||
if (not state_path.empty() && (local4.getPort() == 0 || local6.getPort() == 0)) {
|
||||
if (not state_path.empty()) {
|
||||
state_path += "_port.txt";
|
||||
std::ifstream inConfig(state_path);
|
||||
if (inConfig.is_open()) {
|
||||
in_port_t port;
|
||||
if (inConfig >> port) {
|
||||
if (local4.getPort() == 0) {
|
||||
if (context.logger)
|
||||
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
|
||||
if (context.logger)
|
||||
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
|
||||
if (local4.getPort() == 0)
|
||||
local4.setPort(port);
|
||||
}
|
||||
}
|
||||
if (inConfig >> port) {
|
||||
if (local6.getPort() == 0) {
|
||||
if (context.logger)
|
||||
context.logger->d("[runner %p] Using IPv6 port %hu from saved configuration", this, port);
|
||||
if (context.logger)
|
||||
context.logger->d("[runner %p] Using IPv6 port %hu from saved configuration", this, port);
|
||||
if (local6.getPort() == 0)
|
||||
local6.setPort(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,10 +185,10 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
if (context.statusChangedCallback) {
|
||||
statusCb = std::move(context.statusChangedCallback);
|
||||
}
|
||||
if (context.certificateStore) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
if (context.certificateStore || context.certificateStoreSha256) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStore), std::move(context.certificateStoreSha256));
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
dht_via_proxy_->setLocalCertificateStore(std::move(context.certificateStore), std::move(context.certificateStoreSha256));
|
||||
}
|
||||
|
||||
if (not config.threaded)
|
||||
@@ -268,31 +266,29 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::shutdown(ShutdownCallback cb, bool stop) {
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
DhtRunner::shutdown(ShutdownCallback cb) {
|
||||
auto expected = State::Running;
|
||||
if (not running.compare_exchange_strong(expected, State::Stopping)) {
|
||||
if (expected == State::Stopping and ongoing_ops) {
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
shutdownCallbacks_.emplace_back(std::move(cb));
|
||||
}
|
||||
else if (cb) {
|
||||
lck.unlock();
|
||||
cb();
|
||||
}
|
||||
else if (cb) cb();
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->d("[runner %p] state changed to Stopping, %zu ongoing ops", this, ongoing_ops.load());
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
shutdownCallbacks_.emplace_back(std::move(cb));
|
||||
pending_ops.emplace([=](SecureDht&) mutable {
|
||||
pending_ops_prio.emplace([=](SecureDht&) mutable {
|
||||
auto onShutdown = [this]{ opEnded(); };
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->shutdown(onShutdown, stop);
|
||||
dht_via_proxy_->shutdown(onShutdown);
|
||||
#endif
|
||||
if (dht_)
|
||||
dht_->shutdown(onShutdown, stop);
|
||||
dht_->shutdown(onShutdown);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -321,11 +317,11 @@ DhtRunner::bindOpDoneCallback(DoneCallbackSimple&& cb) {
|
||||
|
||||
bool
|
||||
DhtRunner::checkShutdown() {
|
||||
if (running != State::Stopping or ongoing_ops)
|
||||
return false;
|
||||
decltype(shutdownCallbacks_) cbs;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Stopping or ongoing_ops)
|
||||
return false;
|
||||
cbs = std::move(shutdownCallbacks_);
|
||||
}
|
||||
for (auto& cb : cbs)
|
||||
@@ -357,13 +353,9 @@ DhtRunner::join()
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
if (ongoing_ops and logger_) {
|
||||
logger_->w("[runner %p] stopping with %zu remaining ops", this, ongoing_ops.load());
|
||||
}
|
||||
pending_ops = decltype(pending_ops)();
|
||||
pending_ops_prio = decltype(pending_ops_prio)();
|
||||
ongoing_ops = 0;
|
||||
shutdownCallbacks_.clear();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
@@ -406,14 +398,15 @@ DhtRunner::getId() const
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<crypto::PublicKey>
|
||||
DhtRunner::getPublicKey() const
|
||||
PkId
|
||||
DhtRunner::getLongId() const
|
||||
{
|
||||
if (auto dht = activeDht())
|
||||
return dht->getPublicKey();
|
||||
return dht->getLongId();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
InfoHash
|
||||
DhtRunner::getNodeId() const
|
||||
{
|
||||
@@ -525,6 +518,7 @@ DhtRunner::getNodeInfo() const {
|
||||
NodeInfo info {};
|
||||
if (auto dht = activeDht()) {
|
||||
info.id = dht->getId();
|
||||
info.pkid = dht->getLongId();
|
||||
info.node_id = dht->getNodeId();
|
||||
info.ipv4 = dht->getNodesStats(AF_INET);
|
||||
info.ipv6 = dht->getNodesStats(AF_INET6);
|
||||
@@ -546,6 +540,7 @@ DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
|
||||
auto sinfo = std::make_shared<NodeInfo>();
|
||||
auto& info = *sinfo;
|
||||
info.id = dht.getId();
|
||||
info.pkid = dht.getLongId();
|
||||
info.node_id = dht.getNodeId();
|
||||
info.ipv4 = dht.getNodesStats(AF_INET);
|
||||
info.ipv6 = dht.getNodesStats(AF_INET6);
|
||||
@@ -632,14 +627,14 @@ DhtRunner::registerCertificate(std::shared_ptr<crypto::Certificate> cert) {
|
||||
activeDht()->registerCertificate(cert);
|
||||
}
|
||||
void
|
||||
DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method) {
|
||||
DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method, CertificateStoreLongQuery&& query_sha256_method) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->setLocalCertificateStore(std::forward<CertificateStoreQuery>(query_method));
|
||||
dht_via_proxy_->setLocalCertificateStore(std::move(query_method), std::move(query_sha256_method));
|
||||
#endif
|
||||
if (dht_)
|
||||
dht_->setLocalCertificateStore(std::forward<CertificateStoreQuery>(query_method));
|
||||
dht_->setLocalCertificateStore(std::move(query_method), std::move(query_sha256_method));
|
||||
}
|
||||
|
||||
time_point
|
||||
@@ -723,12 +718,11 @@ DhtRunner::loop_()
|
||||
void
|
||||
DhtRunner::get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f, Where w)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (dcb) dcb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=](SecureDht& dht) mutable {
|
||||
dht.get(hash, std::move(vcb), bindOpDoneCallback(std::move(dcb)), std::move(f), std::move(w));
|
||||
@@ -743,12 +737,11 @@ DhtRunner::get(const std::string& key, GetCallback vcb, DoneCallbackSimple dcb,
|
||||
}
|
||||
void
|
||||
DhtRunner::query(const InfoHash& hash, QueryCallback cb, DoneCallback done_cb, Query q) {
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (done_cb) done_cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=](SecureDht& dht) mutable {
|
||||
dht.query(hash, std::move(cb), bindOpDoneCallback(std::move(done_cb)), std::move(q));
|
||||
@@ -760,12 +753,11 @@ std::future<size_t>
|
||||
DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
|
||||
{
|
||||
auto ret_token = std::make_shared<std::promise<size_t>>();
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
ret_token->set_value(0);
|
||||
return ret_token->get_future();
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops.emplace([=](SecureDht& dht) mutable {
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
auto tokenbGlobal = listener_token_++;
|
||||
@@ -846,12 +838,11 @@ DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb, time_point created, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
@@ -865,12 +856,11 @@ DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb, time_point created
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, time_point created, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=, cb = std::move(cb)](SecureDht& dht) mutable {
|
||||
dht.put(hash, value, bindOpDoneCallback(std::move(cb)), created, permanent);
|
||||
@@ -907,12 +897,11 @@ DhtRunner::cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value)
|
||||
void
|
||||
DhtRunner::putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
@@ -938,12 +927,11 @@ DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple c
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
@@ -966,15 +954,39 @@ DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, Done
|
||||
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
DhtRunner::putEncrypted(InfoHash hash, PkId to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
value = std::move(value)
|
||||
] (SecureDht& dht) mutable {
|
||||
dht.putEncrypted(hash, to, value, bindOpDoneCallback(std::move(cb)), permanent);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, PkId to, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
if (running != State::Running) {
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
@@ -1054,12 +1066,11 @@ DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple&& cb)
|
||||
void
|
||||
DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false);
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([addr, cb = bindOpDoneCallback(std::move(cb))](SecureDht& dht) mutable {
|
||||
dht.pingNode(std::move(addr), std::move(cb));
|
||||
@@ -1070,9 +1081,9 @@ DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb)
|
||||
void
|
||||
DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([id, address](SecureDht& dht) mutable {
|
||||
dht.insertNode(id, address);
|
||||
});
|
||||
@@ -1082,9 +1093,9 @@ DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
|
||||
void
|
||||
DhtRunner::bootstrap(const std::vector<NodeExport>& nodes)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht& dht) {
|
||||
for (auto& node : nodes)
|
||||
dht.insertNode(node);
|
||||
@@ -1108,12 +1119,11 @@ DhtRunner::connectivityChanged()
|
||||
|
||||
void
|
||||
DhtRunner::findCertificate(InfoHash hash, std::function<void(const Sp<crypto::Certificate>&)> cb) {
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
cb({});
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([this, hash, cb = std::move(cb)] (SecureDht& dht) {
|
||||
dht.findCertificate(hash, [this, cb = std::move(cb)](const Sp<crypto::Certificate>& crt){
|
||||
|
||||
+142
-10
@@ -155,12 +155,9 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
if (node == h) {
|
||||
if (logger_)
|
||||
logger_->d("Registering certificate for %s", h.toString().c_str());
|
||||
auto it = nodesCertificates_.find(h);
|
||||
if (it == nodesCertificates_.end())
|
||||
std::tie(it, std::ignore) = nodesCertificates_.emplace(h, std::move(crt));
|
||||
else
|
||||
it->second = std::move(crt);
|
||||
return it->second;
|
||||
nodesCertificates_[h] = crt;
|
||||
nodesCertificatesLong_[crt->getLongId()] = crt;
|
||||
return crt;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w("Certificate %s for node %s does not match node id !", h.toString().c_str(), node.toString().c_str());
|
||||
@@ -171,8 +168,10 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
void
|
||||
SecureDht::registerCertificate(Sp<crypto::Certificate>& cert)
|
||||
{
|
||||
if (cert)
|
||||
if (cert) {
|
||||
nodesCertificates_[cert->getId()] = cert;
|
||||
nodesCertificatesLong_[cert->getLongId()] = cert;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -192,6 +191,7 @@ SecureDht::findCertificate(const InfoHash& node, const std::function<void(const
|
||||
if (logger_)
|
||||
logger_->d("Registering certificate from local store for %s", node.to_c_str());
|
||||
nodesCertificates_.emplace(node, res.front());
|
||||
nodesCertificatesLong_.emplace(res.front()->getLongId(), res.front());
|
||||
if (cb)
|
||||
cb(res.front());
|
||||
return;
|
||||
@@ -228,11 +228,12 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp
|
||||
cb(pk);
|
||||
return;
|
||||
}
|
||||
findCertificate(node, [=](const Sp<crypto::Certificate>& crt) {
|
||||
findCertificate(node, [=](const Sp<crypto::Certificate> crt) {
|
||||
if (crt && *crt) {
|
||||
auto pk = std::make_shared<crypto::PublicKey>(crt->getPublicKey());
|
||||
if (*pk) {
|
||||
nodesPubKeys_[pk->getId()] = pk;
|
||||
nodesPubKeysLong_[pk->getLongId()] = pk;
|
||||
if (cb) cb(pk);
|
||||
return;
|
||||
}
|
||||
@@ -241,6 +242,106 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findCertificate(const PkId& node, const std::function<void(const Sp<crypto::Certificate>)>& cb)
|
||||
{
|
||||
Sp<crypto::Certificate> b = getCertificate(node);
|
||||
if (b && *b) {
|
||||
if (logger_)
|
||||
logger_->d("Using certificate from cache for %s", node.to_c_str());
|
||||
if (cb)
|
||||
cb(b);
|
||||
return;
|
||||
}
|
||||
if (localQueryMethod_) {
|
||||
auto res = localQuerySha256Method_(node);
|
||||
if (not res.empty()) {
|
||||
if (logger_)
|
||||
logger_->d("Registering certificate from local store for %s", node.to_c_str());
|
||||
nodesCertificates_.emplace(res.front()->getId(), res.front());
|
||||
nodesCertificatesLong_.emplace(node, res.front());
|
||||
if (cb)
|
||||
cb(res.front());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cb)
|
||||
cb(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findPublicKey(const PkId& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb)
|
||||
{
|
||||
auto pk = getPublicKey(node);
|
||||
if (pk && *pk) {
|
||||
if (logger_)
|
||||
logger_->d("Found public key from cache for %s", node.to_c_str());
|
||||
if (cb)
|
||||
cb(pk);
|
||||
return;
|
||||
}
|
||||
findCertificate(node, [=](const Sp<crypto::Certificate> crt) {
|
||||
if (crt && *crt) {
|
||||
auto pk = std::make_shared<crypto::PublicKey>(crt->getPublicKey());
|
||||
if (*pk) {
|
||||
nodesPubKeys_[pk->getId()] = pk;
|
||||
nodesPubKeysLong_[pk->getLongId()] = pk;
|
||||
if (cb) cb(pk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cb) cb(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::registerCertificate(const PkId& pkId, const Blob& data)
|
||||
{
|
||||
Sp<crypto::Certificate> crt;
|
||||
try {
|
||||
crt = std::make_shared<crypto::Certificate>(data);
|
||||
} catch (const std::exception& e) {
|
||||
return nullptr;
|
||||
}
|
||||
PkId id = crt->getPublicKey().getLongId();
|
||||
if (pkId == id) {
|
||||
if (logger_)
|
||||
logger_->d("Registering certificate for %s", id.toString().c_str());
|
||||
nodesCertificates_[crt->getId()] = crt;
|
||||
nodesCertificatesLong_[id] = crt;
|
||||
return crt;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w("Certificate %s for node %s does not match node id !", id.toString().c_str(), pkId.toString().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::getCertificate(const PkId& pkId) const
|
||||
{
|
||||
if (pkId == getLongId())
|
||||
return certificate_;
|
||||
auto it = nodesCertificatesLong_.find(pkId);
|
||||
if (it == nodesCertificatesLong_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Sp<crypto::PublicKey>
|
||||
SecureDht::getPublicKey(const PkId& pkId) const
|
||||
{
|
||||
if (pkId == getLongId())
|
||||
return std::make_shared<crypto::PublicKey>(certificate_->getPublicKey());
|
||||
auto it = nodesPubKeysLong_.find(pkId);
|
||||
if (it == nodesPubKeysLong_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
Sp<Value>
|
||||
SecureDht::checkValue(const Sp<Value>& v)
|
||||
{
|
||||
@@ -260,8 +361,10 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
try {
|
||||
Value decrypted_val (decrypt(*v));
|
||||
if (decrypted_val.recipient == getId()) {
|
||||
if (decrypted_val.owner)
|
||||
if (decrypted_val.owner) {
|
||||
nodesPubKeys_[decrypted_val.owner->getId()] = decrypted_val.owner;
|
||||
nodesPubKeysLong_[decrypted_val.owner->getLongId()] = decrypted_val.owner;
|
||||
}
|
||||
v->decryptedValue = std::make_shared<Value>(std::move(decrypted_val));
|
||||
return v->decryptedValue;
|
||||
}
|
||||
@@ -279,8 +382,10 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
v->signatureChecked = true;
|
||||
if (v->owner and v->owner->checkSignature(v->getToSign(), v->signature)) {
|
||||
v->signatureValid = true;
|
||||
if (enableCache_)
|
||||
if (enableCache_) {
|
||||
nodesPubKeys_[v->owner->getId()] = v->owner;
|
||||
nodesPubKeysLong_[v->owner->getLongId()] = v->owner;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
else if (logger_)
|
||||
@@ -422,6 +527,33 @@ SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val,
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
if (not key_) {
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
}
|
||||
findPublicKey(to, [this, hash, val = std::move(val), callback = std::move(callback), permanent](const Sp<crypto::PublicKey>& pk) {
|
||||
if(!pk || !*pk) {
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->w("Encrypting data for PK: %s", pk->getLongId().toString().c_str());
|
||||
try {
|
||||
dht_->put(hash, encrypt(*val, *pk), callback, time_point::max(), permanent);
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->e("Error putting encrypted data: %s", e.what());
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const crypto::PublicKey& pk, Sp<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
|
||||
+3
-3
@@ -496,10 +496,10 @@ Query::msgpack_unpack(const msgpack::object& o)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool subset(const std::vector<T>& fds, const std::vector<T>& qfds)
|
||||
bool subset(std::vector<T> fds, std::vector<T> qfds)
|
||||
{
|
||||
for (const auto& fd : fds) {
|
||||
if (std::find_if(qfds.begin(), qfds.end(), [&fd](const T& _vfd) { return fd == _vfd; }) == qfds.end())
|
||||
for (auto& fd : fds) {
|
||||
if (std::find_if(qfds.begin(), qfds.end(), [&fd](T& _vfd) { return fd == _vfd; }) == qfds.end())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -33,7 +33,7 @@ CryptoTester::setUp() {
|
||||
void
|
||||
CryptoTester::testSignatureEncryption() {
|
||||
auto key = dht::crypto::PrivateKey::generate();
|
||||
const auto& public_key = key.getPublicKey();
|
||||
auto public_key = key.getPublicKey();
|
||||
|
||||
std::vector<uint8_t> data1 {5, 10};
|
||||
std::vector<uint8_t> data2(64 * 1024, 10);
|
||||
|
||||
@@ -71,7 +71,7 @@ DhtProxyTester::tearDown() {
|
||||
cv.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 15s, [&]{ return done; }));
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&]{ return done; }));
|
||||
serverProxy.reset();
|
||||
nodeProxy.reset();
|
||||
}
|
||||
@@ -289,47 +289,4 @@ DhtProxyTester::testFuzzy()
|
||||
CPPUNIT_ASSERT(value->data == mtu);
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyTester::testShutdownStop()
|
||||
{
|
||||
constexpr size_t N = 40000;
|
||||
constexpr unsigned C = 100;
|
||||
|
||||
// Arrange
|
||||
auto key = dht::InfoHash::get("testShutdownStop");
|
||||
std::vector<std::shared_ptr<dht::Value>> values;
|
||||
std::vector<uint8_t> mtu;
|
||||
mtu.reserve(N);
|
||||
for (size_t i = 0; i < N; i++)
|
||||
mtu.emplace_back((i % 2) ? 'T' : 'M');
|
||||
|
||||
std::atomic_uint callback_count {0};
|
||||
|
||||
// Act
|
||||
for (size_t i = 0; i < C; i++) {
|
||||
auto nodeTest = std::make_shared<dht::DhtRunner>();
|
||||
nodeTest->run(0, clientConfig);
|
||||
nodeTest->put(key, dht::Value(mtu), [&](bool ok) {
|
||||
callback_count++;
|
||||
});
|
||||
nodeTest->get(key, [&](const std::vector<std::shared_ptr<dht::Value>>& vals){
|
||||
values.insert(values.end(), vals.begin(), vals.end());
|
||||
return true;
|
||||
},[&](bool ok){
|
||||
callback_count++;
|
||||
});
|
||||
bool done = false;
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
nodeTest->shutdown([&]{
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
}, true);
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&]{ return done; }));
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL(2*C, callback_count.load());
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
@@ -36,7 +36,6 @@ class DhtProxyTester : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST(testResubscribeGetValues);
|
||||
CPPUNIT_TEST(testPutGet40KChars);
|
||||
CPPUNIT_TEST(testFuzzy);
|
||||
CPPUNIT_TEST(testShutdownStop);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -69,8 +68,6 @@ class DhtProxyTester : public CppUnit::TestFixture {
|
||||
|
||||
void testFuzzy();
|
||||
|
||||
void testShutdownStop();
|
||||
|
||||
private:
|
||||
dht::DhtRunner::Config clientConfig {};
|
||||
dht::DhtRunner nodePeer;
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
|
||||
#include "dhtrunnertester.h"
|
||||
|
||||
#include <opendht/thread_pool.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
@@ -54,7 +52,7 @@ DhtRunnerTester::tearDown() {
|
||||
node1.shutdown(shutdown);
|
||||
node2.shutdown(shutdown);
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 12s, [&]{ return done == 2; }));
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 5s, [&]{ return done == 2; }));
|
||||
node1.join();
|
||||
node2.join();
|
||||
}
|
||||
@@ -232,24 +230,17 @@ DhtRunnerTester::testIdOps() {
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
node1.putEncrypted(key, node2.getPublicKey(), dht::Value("yo"), [&](bool ok){
|
||||
CPPUNIT_ASSERT(ok);
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
valueCount++;
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
node2.listen<std::string>(key, [&](std::string&& value){
|
||||
CPPUNIT_ASSERT_EQUAL("yo"s, value);
|
||||
std::lock_guard<std::mutex> lk(mutex);
|
||||
valueCount++;
|
||||
cv.notify_all();
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(mutex);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]{ return valueCount == 7; }));
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]{ return valueCount == 4; }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,39 +291,4 @@ DhtRunnerTester::testListenLotOfBytes() {
|
||||
node3.cancelListen(foo, ftokenfoo.get());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DhtRunnerTester::testMultithread() {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
unsigned putCount(0);
|
||||
unsigned putOkCount(0);
|
||||
|
||||
constexpr unsigned N = 2048;
|
||||
|
||||
for (unsigned i=0; i<N; i++) {
|
||||
dht::ThreadPool::computation().run([&]{
|
||||
node2.put(dht::InfoHash::get("123" + std::to_string(i)), "hehe", [&](bool ok) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
putCount++;
|
||||
if (ok) putOkCount++;
|
||||
cv.notify_all();
|
||||
});
|
||||
node2.get(dht::InfoHash::get("123" + std::to_string(N-i-1)), [](const std::shared_ptr<dht::Value>&){
|
||||
return true;
|
||||
}, [&](bool ok) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
putCount++;
|
||||
if (ok) putOkCount++;
|
||||
cv.notify_all();
|
||||
});
|
||||
});
|
||||
}
|
||||
std::unique_lock<std::mutex> lk(mutex);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]{ return putCount == 2*N; }));
|
||||
CPPUNIT_ASSERT_EQUAL(2*N, putOkCount);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace test
|
||||
@@ -67,11 +67,6 @@ class DhtRunnerTester : public CppUnit::TestFixture {
|
||||
* Test listen method with lot of datas
|
||||
*/
|
||||
void testListenLotOfBytes();
|
||||
/**
|
||||
* Test multithread
|
||||
*/
|
||||
void testMultithread();
|
||||
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -59,7 +59,7 @@ ThreadPoolTester::testExecutor()
|
||||
auto executor8 = std::make_shared<dht::Executor>(pool, 8);
|
||||
|
||||
constexpr unsigned N = 64 * 1024;
|
||||
unsigned count1 {0};
|
||||
std::atomic_uint count1 {0};
|
||||
std::atomic_uint count4 {0};
|
||||
std::atomic_uint count8 {0};
|
||||
for (unsigned i=0; i<N; i++) {
|
||||
@@ -69,7 +69,7 @@ ThreadPoolTester::testExecutor()
|
||||
}
|
||||
|
||||
auto start = clock::now();
|
||||
while ((count1 != N ||
|
||||
while ((count1.load() != N ||
|
||||
count4.load() != N ||
|
||||
count8.load() != N) && clock::now() - start < std::chrono::seconds(20))
|
||||
{
|
||||
@@ -78,28 +78,11 @@ ThreadPoolTester::testExecutor()
|
||||
executor1.reset();
|
||||
executor4.reset();
|
||||
executor8.reset();
|
||||
CPPUNIT_ASSERT_EQUAL(N, count1);
|
||||
CPPUNIT_ASSERT_EQUAL(N, count1.load());
|
||||
CPPUNIT_ASSERT_EQUAL(N, count4.load());
|
||||
CPPUNIT_ASSERT_EQUAL(N, count8.load());
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::testContext()
|
||||
{
|
||||
std::atomic_uint count {0};
|
||||
constexpr unsigned N = 64 * 1024;
|
||||
|
||||
{
|
||||
dht::ExecutionContext ctx(dht::ThreadPool::computation());
|
||||
for (unsigned i=0; i<N; i++) {
|
||||
ctx.run([&] { count++; });
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(N, count.load());
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::tearDown() {
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ class ThreadPoolTester : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(ThreadPoolTester);
|
||||
CPPUNIT_TEST(testThreadPool);
|
||||
CPPUNIT_TEST(testExecutor);
|
||||
CPPUNIT_TEST(testContext);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -44,7 +43,6 @@ class ThreadPoolTester : public CppUnit::TestFixture {
|
||||
|
||||
void testThreadPool();
|
||||
void testExecutor();
|
||||
void testContext();
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
+3
-3
@@ -4,10 +4,10 @@ noinst_HEADERS = tools_common.h
|
||||
AM_CPPFLAGS = -isystem @top_srcdir@/include @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@
|
||||
|
||||
dhtnode_SOURCES = dhtnode.cpp
|
||||
dhtnode_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIBS@
|
||||
dhtnode_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @Argon2_LDFLAGS@ @GnuTLS_LIBS@
|
||||
|
||||
dhtchat_SOURCES = dhtchat.cpp
|
||||
dhtchat_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIBS@
|
||||
dhtchat_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @Argon2_LDFLAGS@ @GnuTLS_LIBS@
|
||||
|
||||
dhtscanner_SOURCES = dhtscanner.cpp
|
||||
dhtscanner_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIBS@
|
||||
dhtscanner_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @Argon2_LDFLAGS@ @GnuTLS_LIBS@
|
||||
+1
-1
@@ -467,7 +467,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
|
||||
<< " hash: " << p.hash() << std::endl;
|
||||
std::cout << " entries:" << std::endl;
|
||||
for (const auto& v : vals)
|
||||
std::cout << " " << v->first.toString() << "[vid: " << std::hex << v->second << std::dec << "]" << std::endl;
|
||||
std::cout << " " << v->first.toString() << "[vid: " << v->second << "]" << std::endl;
|
||||
},
|
||||
[start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@@ -200,6 +200,8 @@ void print_node_info(const dht::NodeInfo& info) {
|
||||
std::cout << "IPv4 port " << info.bound4 << ", IPv6 port " << info.bound6 << std::endl;
|
||||
if (info.id)
|
||||
std::cout << "Public key ID " << info.id << std::endl;
|
||||
if (info.pkid)
|
||||
std::cout << "Public key long ID " << info.pkid << std::endl;
|
||||
}
|
||||
|
||||
static const constexpr struct option long_options[] = {
|
||||
|
||||
Reference in new issue
Block a user