mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e601f4f081 | ||
|
|
183620645f | ||
|
|
341217cf34 | ||
|
|
3742af2a44 | ||
|
|
db000a2f88 | ||
|
|
59880df60e | ||
|
|
75f1b07e7a | ||
|
|
f191c4f636 | ||
|
|
1b2bc7b1e3 | ||
|
|
a89e4d626e | ||
|
|
dbbfdaab0f | ||
|
|
536f30ec84 | ||
|
|
b7aec1310c | ||
|
|
31d76b1080 | ||
|
|
2fbafc3591 | ||
|
|
19fe34415a | ||
|
|
2a50f85a30 | ||
|
|
26b71ab993 | ||
|
|
04a78445c6 | ||
|
|
fa19897016 | ||
|
|
3806355509 | ||
|
|
3f6738185b | ||
|
|
e58d09e5da | ||
|
|
71cd9d22c6 | ||
|
|
6c58d4f2e9 | ||
|
|
4070eecea7 | ||
|
|
ffb53ceb1d | ||
|
|
0c00544798 | ||
|
|
471d443e4a | ||
|
|
ba9a445263 | ||
|
|
056bc2850b | ||
|
|
b668d6ad68 | ||
|
|
29fab5560f | ||
|
|
8aef63ce4a | ||
|
|
1ea7a2994e | ||
|
|
208b3fa6fe | ||
|
|
d9ff95da49 | ||
|
|
c8a0b443f3 | ||
|
|
00e595d737 | ||
|
|
a178a8f820 | ||
|
|
ec359d50fb | ||
|
|
3c5aeccd53 | ||
|
|
f99fe16a46 | ||
|
|
43dc7cf222 | ||
|
|
ad549098f8 | ||
|
|
6795ba3838 | ||
|
|
efb5f8e36a | ||
|
|
8aa24f1289 | ||
|
|
14d882d220 | ||
|
|
f4c6c54a08 | ||
|
|
4dc7a5ca0a | ||
|
|
40fdd04cb3 | ||
|
|
a24dedd225 | ||
|
|
ae2445fd07 | ||
|
|
7ba53cb4b3 | ||
|
|
fbff8389c5 | ||
|
|
827fdacc4b | ||
|
|
3efc27e9f3 | ||
|
|
f7104199e3 | ||
|
|
5c0fbf7e68 | ||
|
|
55c595330a | ||
|
|
d3fc75589f | ||
|
|
f8605f45f7 | ||
|
|
d541b17fe1 | ||
|
|
29eb1d97f8 | ||
|
|
623b1c4585 | ||
|
|
74f7d7811e | ||
|
|
7774331a20 | ||
|
|
aae30c5891 | ||
|
|
41760e4b65 | ||
|
|
9ca0de250b | ||
|
|
d0156b4637 | ||
|
|
f6cca88593 | ||
|
|
c6da80573e | ||
|
|
5527869d13 | ||
|
|
5c599b2feb | ||
|
|
122d814a33 | ||
|
|
a1a8adbe4b | ||
|
|
5a370cabb5 | ||
|
|
639ae26ac1 | ||
|
|
896b6de60c | ||
|
|
d025f9d1b5 | ||
|
|
0b029bc0bf | ||
|
|
2256434ec7 | ||
|
|
0b4caeda73 | ||
|
|
18a1a1c47f | ||
|
|
6702956521 | ||
|
|
c996220685 | ||
|
|
df85abfabe | ||
|
|
e6c760ec6b | ||
|
|
a77dc855f0 | ||
|
|
2524e167d9 | ||
|
|
638d1c91f1 | ||
|
|
ba4058dfd9 | ||
|
|
ab90a170af | ||
|
|
f780499241 | ||
|
|
91709bc999 | ||
|
|
72725dc5c1 | ||
|
|
3098439db2 | ||
|
|
6441a09e09 | ||
|
|
57e7699723 | ||
|
|
17e1cfbbbe | ||
|
|
bfe1311ca8 | ||
|
|
537a1650f2 | ||
|
|
8c852c20e7 | ||
|
|
1da46382d3 | ||
|
|
4953888af3 | ||
|
|
22de868c6c | ||
|
|
0998707e03 | ||
|
|
b5fcd49b7b | ||
|
|
81cdd9650b | ||
|
|
e028cea687 | ||
|
|
17ed4a9e26 | ||
|
|
3ff318b9e4 | ||
|
|
0c11c25c66 | ||
|
|
0d31139402 | ||
|
|
e970cac4d7 | ||
|
|
7c8eecd745 | ||
|
|
4d87c2267b | ||
|
|
88b2439deb | ||
|
|
766a06c69a | ||
|
|
aa502553bb | ||
|
|
05ff4205d2 | ||
|
|
9d937bb277 | ||
|
|
1621515b3c | ||
|
|
30261e70ad | ||
|
|
c2a4f667a7 | ||
|
|
05b95331d8 | ||
|
|
c986f44704 | ||
|
|
7f62073d93 | ||
|
|
1a562962ba | ||
|
|
065be0621d | ||
|
|
6c085ed975 | ||
|
|
4c5776f9d2 | ||
|
|
c84fac6823 | ||
|
|
1778f64048 | ||
|
|
d1000635dd | ||
|
|
1273b062e1 | ||
|
|
961b96ca3d | ||
|
|
bcb29c3588 | ||
|
|
5d9395b16f | ||
|
|
23a75a3f50 | ||
|
|
7b87d32c0a | ||
|
|
d5f4f81566 | ||
|
|
a69863da4e | ||
|
|
4d70c214b0 | ||
|
|
11afc2b468 | ||
|
|
879e4f4e02 | ||
|
|
b5b4eea253 | ||
|
|
67adc09d52 | ||
|
|
e2b39dd3a0 | ||
|
|
9dc0ce7392 | ||
|
|
1a025c5cea | ||
|
|
732e9af439 | ||
|
|
4e5666fc3a | ||
|
|
b41f5b04f5 | ||
|
|
cfa21df8b3 | ||
|
|
6ac451a5de | ||
|
|
9efb8bb662 | ||
|
|
f0aee6f909 | ||
|
|
f72bfc9df2 | ||
|
|
c9ebfd1119 | ||
|
|
cf1874baaa | ||
|
|
c221cfdafe | ||
|
|
31b84e6d92 | ||
|
|
ae05bc8ea5 | ||
|
|
acbf7cfcf0 | ||
|
|
8250116946 | ||
|
|
45e9458373 | ||
|
|
2623b86274 | ||
|
|
2e1dda8189 | ||
|
|
e26256b819 | ||
|
|
18e59ad7c8 | ||
|
|
a7a3d23f50 | ||
|
|
323a2b5093 | ||
|
|
563811ebf8 | ||
|
|
190c7f2063 | ||
|
|
6158751a32 | ||
|
|
4c7d126782 | ||
|
|
3e24ea1212 | ||
|
|
a7ac979da6 | ||
|
|
87f48f0a28 | ||
|
|
15586a3cb1 | ||
|
|
2195c0ed3e | ||
|
|
af1e904895 | ||
|
|
a4fbf7ced0 | ||
|
|
1b7e0679d5 | ||
|
|
9292c1116c | ||
|
|
a2afb5bb31 | ||
|
|
15fbfdebcc | ||
|
|
15eb221cd1 | ||
|
|
7d3781acc8 | ||
|
|
f3100a6752 | ||
|
|
e3cd2a9d02 | ||
|
|
19ccc3a327 | ||
|
|
4587c0925f | ||
|
|
fc96245891 | ||
|
|
a27815b4a9 | ||
|
|
5daaf372b4 | ||
|
|
cc51d2684c | ||
|
|
28b5893239 | ||
|
|
c754b5cfce | ||
|
|
b0c1249710 | ||
|
|
c41ee417fb | ||
|
|
47ba0415ca | ||
|
|
99857e25cc | ||
|
|
7f832ba9d5 | ||
|
|
8c4a894f93 | ||
|
|
dd3de412fb | ||
|
|
4ad5e6c9ba | ||
|
|
b445818521 | ||
|
|
7c14ea1730 | ||
|
|
7bf9f861a5 | ||
|
|
4cf5c87761 | ||
|
|
e1c6fec581 | ||
|
|
31da5b91fa | ||
|
|
01bcb1a750 | ||
|
|
35348bf77f | ||
|
|
ae58ea8312 | ||
|
|
f30d21e96f | ||
|
|
7628aab230 | ||
|
|
f4cba56b3c | ||
|
|
7155dc4fb7 | ||
|
|
c961e2e99f | ||
|
|
2fb8e1c7ee | ||
|
|
4d689ef51a | ||
|
|
face9f12b2 | ||
|
|
c92f553a24 | ||
|
|
8564cf3b86 | ||
|
|
e7c810d5d6 | ||
|
|
e76c80b8be | ||
|
|
69f8969883 | ||
|
|
bc200cd76d | ||
|
|
187c7dbce3 | ||
|
|
81131f1c4e | ||
|
|
ce9445a93f | ||
|
|
16372cba0c | ||
|
|
a2cbef315a | ||
|
|
bc7c43dfd1 | ||
|
|
771b300622 | ||
|
|
5ffb5c628d | ||
|
|
cfa4ce61b4 | ||
|
|
5f15043f03 | ||
|
|
f445b2536d | ||
|
|
6c2f791c4d | ||
|
|
780726c66d | ||
|
|
8703cfdaee | ||
|
|
1c536cbf5e | ||
|
|
a39e2443a0 | ||
|
|
57528e7aab | ||
|
|
e9d70f204a | ||
|
|
ceb35c05c1 | ||
|
|
55ccec5871 | ||
|
|
95028e3770 | ||
|
|
abede1e72a | ||
|
|
859d8dc9cf | ||
|
|
1a67140463 | ||
|
|
9ae3d3c4d4 | ||
|
|
d3508c80f5 | ||
|
|
6c43efa4da | ||
|
|
c5c4c217dd | ||
|
|
5cfcf4861d | ||
|
|
8597267c63 | ||
|
|
1b81d707f3 | ||
|
|
7791163d49 | ||
|
|
56db1bba19 | ||
|
|
a7092c2dc7 | ||
|
|
fc95c85983 | ||
|
|
3490b19fe3 | ||
|
|
4a20814d59 | ||
|
|
707fb39975 | ||
|
|
cbb2406a12 | ||
|
|
7764620460 | ||
|
|
5af0f0c3d0 | ||
|
|
ec8beec427 | ||
|
|
7b8ebbc54d | ||
|
|
dc46c2274c | ||
|
|
052ed1f58c | ||
|
|
9096f650f5 | ||
|
|
900655b11f | ||
|
|
2900b1d17f | ||
|
|
69e71dbeaa | ||
|
|
3793423b2f | ||
|
|
b012878488 | ||
|
|
c1005fa334 | ||
|
|
0f9f623b31 | ||
|
|
2cfebdf9fa | ||
|
|
481b1cb3b4 | ||
|
|
7f1d960a56 | ||
|
|
91e1e942ab | ||
|
|
ae89365f23 | ||
|
|
93cd8d541c | ||
|
|
9487bc5e42 | ||
|
|
10d48137a9 | ||
|
|
5b15fdeeef | ||
|
|
3ba43c80a2 | ||
|
|
16333f4224 | ||
|
|
0864ac9a39 | ||
|
|
616d6fe4b8 | ||
|
|
dea4b202bf | ||
|
|
dc2f354652 | ||
|
|
87041e301f | ||
|
|
189f94442e | ||
|
|
c5c3695612 | ||
|
|
6a7ad871e2 | ||
|
|
99890fca64 | ||
|
|
2dbf57d36b | ||
|
|
5438d50578 | ||
|
|
548255073f | ||
|
|
abaf091772 | ||
|
|
7094b79714 | ||
|
|
1f672773ba | ||
|
|
374fdd6cc9 | ||
|
|
54b1314ab8 | ||
|
|
51c35d8b54 | ||
|
|
fea736428e | ||
|
|
2d358adf0e | ||
|
|
26c2e16a42 | ||
|
|
e8b385c220 |
No files matched your search
@@ -13,12 +13,9 @@ jobs:
|
||||
run: |
|
||||
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
|
||||
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev
|
||||
- name: autogen
|
||||
run: ./autogen.sh
|
||||
- name: argon2
|
||||
run: |
|
||||
cd argon2 && make && sudo make install && cd ..
|
||||
- name: asio
|
||||
run: |
|
||||
wget https://github.com/aberaud/asio/archive/b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz \
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
**/dhtnode
|
||||
**/dhtchat
|
||||
**/dhtscanner
|
||||
|
||||
# Autotools
|
||||
/ac
|
||||
@@ -73,3 +76,4 @@ doc/Doxyfile
|
||||
|
||||
# build dir
|
||||
build
|
||||
.DS_Store
|
||||
@@ -1,4 +0,0 @@
|
||||
[submodule "argon2"]
|
||||
path = argon2
|
||||
url = https://github.com/P-H-C/phc-winner-argon2
|
||||
ignore = dirty
|
||||
+4
-5
@@ -16,13 +16,12 @@ env:
|
||||
|
||||
before_install:
|
||||
- |
|
||||
# non llvm builds
|
||||
if [[ "$OPENDHT_TEST_JOB" != *"opendht.llvm"* ]]; then
|
||||
if [[ "$OPENDHT_TEST_JOB" == *"opendht.classic"* ]]; then
|
||||
docker pull aberaud/opendht-deps-bionic;
|
||||
fi
|
||||
if [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyclient"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyserver"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.push"* ]]; then
|
||||
docker pull aberaud/opendht-deps;
|
||||
fi
|
||||
|
||||
- |
|
||||
# classic build
|
||||
if [[ "$OPENDHT_TEST_JOB" == *"opendht.llvm"* ]]; then
|
||||
docker pull aberaud/opendht-deps-llvm
|
||||
fi
|
||||
|
||||
+189
-116
@@ -1,7 +1,13 @@
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
project (opendht)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(FindPkgConfig)
|
||||
include(cmake/CheckAtomic.cmake)
|
||||
|
||||
set (opendht_VERSION_MAJOR 2)
|
||||
set (opendht_VERSION_MINOR 0.0)
|
||||
set (opendht_VERSION_MINOR 3.2)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -13,7 +19,7 @@ option (OPENDHT_LOG "Build with logs" ON)
|
||||
option (OPENDHT_PYTHON "Build Python bindings" OFF)
|
||||
option (OPENDHT_TOOLS "Build DHT tools" ON)
|
||||
option (OPENDHT_SYSTEMD "Install systemd module" OFF)
|
||||
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
|
||||
option (OPENDHT_SYSTEMD_UNIT_FILE_LOCATION "Where to install systemd unit file")
|
||||
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)
|
||||
@@ -21,10 +27,11 @@ 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)
|
||||
option (OPENDHT_TESTS "Add unit tests executable" OFF)
|
||||
option (OPENDHT_TESTS_NETWORK "Enable unit tests that require network access" ON)
|
||||
option (OPENDHT_C "Build C bindings" OFF)
|
||||
|
||||
find_package(Doxygen)
|
||||
@@ -32,72 +39,97 @@ option (OPENDHT_DOCUMENTATION "Create and install the HTML based API documentati
|
||||
|
||||
# Dependencies
|
||||
list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
find_package (Threads)
|
||||
find_package (PkgConfig)
|
||||
find_package (GnuTLS 3.3 REQUIRED)
|
||||
pkg_search_module (Nettle nettle)
|
||||
find_package (Msgpack 1.2 REQUIRED)
|
||||
if (OPENDHT_TOOLS)
|
||||
find_package (Readline 6 REQUIRED)
|
||||
endif ()
|
||||
if (NOT OPENDHT_ARGON2)
|
||||
find_package(PkgConfig)
|
||||
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)
|
||||
if (NOT MSVC)
|
||||
set (THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
find_package (Threads)
|
||||
find_package (PkgConfig REQUIRED)
|
||||
find_package (GnuTLS 3.3 REQUIRED)
|
||||
pkg_search_module (Nettle REQUIRED nettle)
|
||||
find_package (Msgpack 1.2 REQUIRED)
|
||||
if (OPENDHT_TOOLS)
|
||||
find_package (Readline 6 REQUIRED)
|
||||
endif ()
|
||||
pkg_search_module(argon2 REQUIRED libargon2)
|
||||
pkg_search_module(Jsoncpp jsoncpp)
|
||||
if (Jsoncpp_FOUND)
|
||||
add_definitions(-DOPENDHT_JSONCPP)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/base64.h
|
||||
src/base64.cpp
|
||||
)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
pkg_search_module(Jsoncpp jsoncpp)
|
||||
if (Jsoncpp_FOUND)
|
||||
add_definitions(-DOPENDHT_JSONCPP)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/base64.h
|
||||
src/base64.cpp
|
||||
)
|
||||
endif()
|
||||
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED)
|
||||
endif ()
|
||||
|
||||
if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
|
||||
find_package(Restinio REQUIRED)
|
||||
if (Restinio_FOUND)
|
||||
if (OPENDHT_HTTP)
|
||||
find_package(Restinio REQUIRED)
|
||||
find_library(FMT_LIBRARY fmt)
|
||||
add_library(fmt SHARED IMPORTED)
|
||||
find_library(HTTP_PARSER_LIBRARY http_parser)
|
||||
add_library(http_parser SHARED IMPORTED)
|
||||
endif()
|
||||
if (NOT Jsoncpp_FOUND)
|
||||
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
|
||||
endif()
|
||||
if (OPENDHT_PROXY_OPENSSL)
|
||||
# https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
|
||||
pkg_search_module(OPENSSL REQUIRED openssl)
|
||||
if (OPENSSL_FOUND)
|
||||
message(STATUS "Found OpenSSL ${OPENSSL_VERSION}")
|
||||
include_directories(${OPENSSL_INCLUDE_DIRS})
|
||||
else ()
|
||||
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
|
||||
if (NOT Jsoncpp_FOUND)
|
||||
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
|
||||
endif()
|
||||
endif()
|
||||
if (OPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
add_definitions(-DOPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
endif()
|
||||
else()
|
||||
set(OPENDHT_PROXY_OPENSSL OFF)
|
||||
endif()
|
||||
if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT OR OPENDHT_PEER_DISCOVERY)
|
||||
if (OPENDHT_PROXY_OPENSSL)
|
||||
# https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
|
||||
pkg_search_module(OPENSSL REQUIRED openssl)
|
||||
if (OPENSSL_FOUND)
|
||||
message(STATUS "Found OpenSSL ${OPENSSL_VERSION} ${OPENSSL_INCLUDE_DIRS}")
|
||||
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIRS})
|
||||
link_directories (${OPENSSL_LIBRARY_DIRS})
|
||||
else ()
|
||||
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
|
||||
endif()
|
||||
endif()
|
||||
else ()
|
||||
set(OPENDHT_PROXY_OPENSSL OFF)
|
||||
endif ()
|
||||
else ()
|
||||
set (WIN32_DEP_DIR ${PROJECT_SOURCE_DIR}/../)
|
||||
include_directories(${WIN32_DEP_DIR}/../msvc/include) # SMP gnutls
|
||||
include_directories(${WIN32_DEP_DIR}/argon2/include)
|
||||
include_directories(${WIN32_DEP_DIR}/jsoncpp/include)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/base64.h
|
||||
src/base64.cpp
|
||||
)
|
||||
add_definitions(-DOPENDHT_JSONCPP)
|
||||
include_directories(${WIN32_DEP_DIR}/msgpack-c/include)
|
||||
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
include_directories(
|
||||
${WIN32_DEP_DIR}/asio/asio/include
|
||||
${WIN32_DEP_DIR}/openssl/include
|
||||
${WIN32_DEP_DIR}/restinio/dev
|
||||
${WIN32_DEP_DIR}/fmt/include
|
||||
${WIN32_DEP_DIR}/http_parser
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
endif()
|
||||
|
||||
# Build flags
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED on)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
|
||||
if (OPENDHT_SANITIZE)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
|
||||
|
||||
if (NOT MSVC)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
|
||||
if (OPENDHT_SANITIZE)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
|
||||
endif ()
|
||||
else ()
|
||||
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
-DWIN32_LEAN_AND_MEAN
|
||||
-DSTATIC_GETOPT
|
||||
-DGNUTLS_INTERNAL_BUILD)
|
||||
set(DISABLE_MSC_WARNINGS "/wd4101 /wd4244 /wd4267 /wd4273 /wd4804 /wd4834 /wd4996")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DISABLE_MSC_WARNINGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif ()
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
|
||||
|
||||
@@ -110,7 +142,7 @@ if (OPENDHT_LOG)
|
||||
else ()
|
||||
add_definitions(-DOPENDHT_LOG=false)
|
||||
endif()
|
||||
if (OPENDHT_LTO)
|
||||
if (OPENDHT_LTO AND NOT MSVC)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
|
||||
if (CMAKE_COMPILER_IS_GNUCC)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-linker-plugin")
|
||||
@@ -129,17 +161,18 @@ endif ()
|
||||
if (Nettle_INCLUDE_DIRS)
|
||||
include_directories (SYSTEM "${Nettle_INCLUDE_DIRS}")
|
||||
endif ()
|
||||
if (ASIO_INCLUDE_DIR)
|
||||
include_directories (SYSTEM "${ASIO_INCLUDE_DIR}")
|
||||
endif ()
|
||||
if (Restinio_INCLUDE_DIR)
|
||||
include_directories (SYSTEM "${Restinio_INCLUDE_DIR}")
|
||||
endif ()
|
||||
if (Jsoncpp_INCLUDE_DIRS)
|
||||
include_directories (SYSTEM "${Jsoncpp_INCLUDE_DIRS}")
|
||||
endif ()
|
||||
if (OpenSSL_INCLUDE_DIR)
|
||||
include_directories (SYSTEM "${OpenSSL_INCLUDE_DIR}")
|
||||
endif ()
|
||||
link_directories (${Nettle_LIBRARY_DIRS})
|
||||
link_directories (${Jsoncpp_LIBRARY_DIRS})
|
||||
link_directories (${argon2_LIBRARY_DIRS})
|
||||
include_directories (
|
||||
./
|
||||
include/
|
||||
@@ -251,7 +284,7 @@ if (OPENDHT_PROXY_CLIENT)
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
|
||||
if (OPENDHT_HTTP)
|
||||
if (OPENDHT_PUSH_NOTIFICATIONS)
|
||||
message("Using push notification")
|
||||
add_definitions(-DOPENDHT_PUSH_NOTIFICATIONS)
|
||||
@@ -259,46 +292,80 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND opendht_HEADERS
|
||||
include/opendht/proxy.h
|
||||
include/opendht/http.h
|
||||
src/compat/os_cert.h
|
||||
)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/http.cpp
|
||||
src/compat/os_cert.cpp
|
||||
)
|
||||
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 ()
|
||||
|
||||
# Targets
|
||||
if (OPENDHT_STATIC)
|
||||
add_library (opendht-static STATIC
|
||||
${opendht_SOURCES}
|
||||
${opendht_HEADERS}
|
||||
)
|
||||
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE argon2)
|
||||
else ()
|
||||
if (NOT MSVC)
|
||||
add_library (opendht-static STATIC
|
||||
${opendht_SOURCES}
|
||||
${opendht_HEADERS}
|
||||
)
|
||||
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
|
||||
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_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
|
||||
${OPENSSL_LIBRARIES})
|
||||
target_link_libraries(opendht-static
|
||||
PRIVATE ${argon2_LIBRARIES}
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_STATIC_LIBRARIES}
|
||||
${Jsoncpp_STATIC_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
|
||||
${OPENSSL_STATIC_LIBRARIES})
|
||||
else ()
|
||||
if (OPENDHT_TOOLS)
|
||||
function (add_obj_lib name libfile)
|
||||
add_library(${name} OBJECT IMPORTED)
|
||||
set_property(TARGET ${name} PROPERTY IMPORTED_OBJECTS ${libfile})
|
||||
endfunction ()
|
||||
add_obj_lib (win32_json ${WIN32_DEP_DIR}/../msvc/lib/x64/lib_json.lib)
|
||||
add_obj_lib (win32_gnutls ${WIN32_DEP_DIR}/../msvc/lib/x64/libgnutls.lib)
|
||||
add_obj_lib (win32_argon2 ${WIN32_DEP_DIR}/argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib)
|
||||
list (APPEND obj_libs
|
||||
$<TARGET_OBJECTS:win32_json>
|
||||
$<TARGET_OBJECTS:win32_gnutls>
|
||||
$<TARGET_OBJECTS:win32_argon2>
|
||||
)
|
||||
if (OPENDHT_HTTP)
|
||||
add_obj_lib (win32_fmt ${WIN32_DEP_DIR}/fmt/msvc/Release/fmt.lib)
|
||||
add_obj_lib (win32_http_parser ${WIN32_DEP_DIR}/http_parser/x64/Release/http-parser.lib)
|
||||
add_obj_lib (win32_ssl ${WIN32_DEP_DIR}/openssl/libssl_static.lib)
|
||||
add_obj_lib (win32_crypto ${WIN32_DEP_DIR}/openssl/libcrypto_static.lib)
|
||||
list (APPEND obj_libs
|
||||
$<TARGET_OBJECTS:win32_fmt>
|
||||
$<TARGET_OBJECTS:win32_http_parser>
|
||||
$<TARGET_OBJECTS:win32_ssl>
|
||||
$<TARGET_OBJECTS:win32_crypto>
|
||||
)
|
||||
endif ()
|
||||
else ()
|
||||
list (APPEND win32_Libs
|
||||
${PROJECT_SOURCE_DIR}/../../msvc/lib/x64/libgnutls.lib
|
||||
${PROJECT_SOURCE_DIR}/../../msvc/lib/x64/lib_json.lib
|
||||
${PROJECT_SOURCE_DIR}/../argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib
|
||||
)
|
||||
list (APPEND win32_Libs
|
||||
${PROJECT_SOURCE_DIR}/../fmt/msvc/Release/fmt.lib
|
||||
${PROJECT_SOURCE_DIR}/../http_parser/x64/Release/http-parser.lib
|
||||
${PROJECT_SOURCE_DIR}/../openssl/libssl.lib
|
||||
${PROJECT_SOURCE_DIR}/../openssl/libcrypto.lib
|
||||
)
|
||||
endif ()
|
||||
add_library (opendht-static STATIC
|
||||
${opendht_SOURCES}
|
||||
${opendht_HEADERS}
|
||||
${obj_libs}
|
||||
)
|
||||
target_link_libraries(opendht-static PUBLIC ${Win32_STATIC_LIBRARIES} ${Win32_IMPORT_LIBRARIES})
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4006")
|
||||
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "libopendht")
|
||||
endif()
|
||||
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
|
||||
endif ()
|
||||
|
||||
@@ -310,17 +377,21 @@ 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)
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht SYSTEM PRIVATE argon2)
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
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}
|
||||
SYSTEM "-framework CoreFoundation" "-framework Security")
|
||||
else ()
|
||||
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
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})
|
||||
endif ()
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
|
||||
|
||||
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
|
||||
endif ()
|
||||
@@ -357,7 +428,6 @@ if (OPENDHT_PYTHON)
|
||||
endif ()
|
||||
|
||||
# CMake module
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/opendhtConfigVersion.cmake"
|
||||
VERSION ${opendht_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
@@ -377,7 +447,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/opendhtConfigVersion.cmake DESTINATIO
|
||||
|
||||
# Unit tests
|
||||
if (OPENDHT_TESTS)
|
||||
FIND_PACKAGE(Cppunit REQUIRED)
|
||||
pkg_search_module(Cppunit REQUIRED cppunit)
|
||||
# unit testing
|
||||
list (APPEND test_FILES
|
||||
tests/infohashtester.h
|
||||
@@ -391,25 +461,28 @@ if (OPENDHT_TESTS)
|
||||
tests/threadpooltester.h
|
||||
tests/threadpooltester.cpp
|
||||
)
|
||||
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND test_FILES
|
||||
tests/httptester.h
|
||||
tests/httptester.cpp
|
||||
tests/dhtproxytester.h
|
||||
tests/dhtproxytester.cpp
|
||||
)
|
||||
endif()
|
||||
if (OPENDHT_PEER_DISCOVERY)
|
||||
list (APPEND test_FILES
|
||||
tests/peerdiscoverytester.h
|
||||
tests/peerdiscoverytester.cpp
|
||||
)
|
||||
if (OPENDHT_TESTS_NETWORK)
|
||||
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND test_FILES
|
||||
tests/httptester.h
|
||||
tests/httptester.cpp
|
||||
tests/dhtproxytester.h
|
||||
tests/dhtproxytester.cpp
|
||||
)
|
||||
endif()
|
||||
if (OPENDHT_PEER_DISCOVERY)
|
||||
list (APPEND test_FILES
|
||||
tests/peerdiscoverytester.h
|
||||
tests/peerdiscoverytester.cpp
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
add_executable(opendht_unit_tests
|
||||
tests/tests_runner.cpp
|
||||
${test_FILES}
|
||||
)
|
||||
target_include_directories(opendht_unit_tests SYSTEM PRIVATE ${CPPUNIT_INCLUDE_DIRS})
|
||||
target_include_directories(opendht_unit_tests SYSTEM PRIVATE ${Cppunit_INCLUDE_DIR})
|
||||
target_link_directories(opendht_unit_tests PRIVATE ${Cppunit_LIBRARY_DIRS})
|
||||
if (OPENDHT_SHARED)
|
||||
target_link_libraries(opendht_unit_tests opendht)
|
||||
else ()
|
||||
@@ -417,7 +490,7 @@ if (OPENDHT_TESTS)
|
||||
endif ()
|
||||
target_link_libraries(opendht_unit_tests
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${CPPUNIT_LIBRARIES}
|
||||
${Cppunit_LIBRARIES}
|
||||
${GNUTLS_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
)
|
||||
|
||||
-248
@@ -1,248 +0,0 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
#output directories
|
||||
DebugLib/
|
||||
Debug/
|
||||
ReleaseLib/
|
||||
Release/
|
||||
.config/
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
*.VC.VC.opendb
|
||||
*.VC.db
|
||||
*.db
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Microsoft Azure ApplicationInsights config file
|
||||
ApplicationInsights.config
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
!config.h
|
||||
contrib/build/
|
||||
@@ -1,168 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8BE7F14D-B227-4D54-9105-7E5473F2D0BA}</ProjectGuid>
|
||||
<RootNamespace>dhtchat</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tools\dhtchat.cpp" />
|
||||
<ClCompile Include="wingetopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tools\tools_common.h" />
|
||||
<ClInclude Include="wingetopt.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,168 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BF92AECF-AA1D-4B05-9D00-0247E92A24B5}</ProjectGuid>
|
||||
<RootNamespace>dhtnode</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tools\dhtnode.cpp" />
|
||||
<ClCompile Include="wingetopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tools\tools_common.h" />
|
||||
<ClInclude Include="wingetopt.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,168 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{78443BCD-4689-4007-A246-F8F34B27F561}</ProjectGuid>
|
||||
<RootNamespace>dhtscanner</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tools\dhtscanner.cpp" />
|
||||
<ClCompile Include="wingetopt.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tools\tools_common.h" />
|
||||
<ClInclude Include="wingetopt.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,257 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opendht", "opendht.vcxproj", "{711397CE-E5D5-467D-9457-8716C047E50C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
DebugDLL|x64 = DebugDLL|x64
|
||||
DebugDLL|x86 = DebugDLL|x86
|
||||
DebugDLLStaticDeps|x64 = DebugDLLStaticDeps|x64
|
||||
DebugDLLStaticDeps|x86 = DebugDLLStaticDeps|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
ReleaseDLL|x64 = ReleaseDLL|x64
|
||||
ReleaseDLL|x86 = ReleaseDLL|x86
|
||||
ReleaseDLLStaticDeps|x64 = ReleaseDLLStaticDeps|x64
|
||||
ReleaseDLLStaticDeps|x86 = ReleaseDLLStaticDeps|x86
|
||||
ReleaseLTO|x64 = ReleaseLTO|x64
|
||||
ReleaseLTO|x86 = ReleaseLTO|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.Build.0 = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.ActiveCfg = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.Build.0 = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.ActiveCfg = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.Build.0 = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.ActiveCfg = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.Build.0 = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.Build.0 = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.ActiveCfg = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.Build.0 = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.ActiveCfg = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.Build.0 = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.ActiveCfg = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.Build.0 = Release|x64
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.ActiveCfg = Release|Win32
|
||||
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.Build.0 = Release|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.Build.0 = Debug|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.ActiveCfg = Release|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.Build.0 = Release|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.Build.0 = Release|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.Build.0 = Debug|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.ActiveCfg = Release|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.Build.0 = Release|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.Build.0 = Release|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.Build.0 = Debug|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.ActiveCfg = Release|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.Build.0 = Release|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.Build.0 = Release|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.Build.0 = Debug|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.ActiveCfg = Release|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.Build.0 = Release|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.Build.0 = Release|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.Build.0 = Debug|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.Build.0 = Debug|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.ActiveCfg = Release|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.Build.0 = Release|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.ActiveCfg = Release|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.Build.0 = Release|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.Build.0 = Debug|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.Build.0 = DebugDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.Build.0 = DebugDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.ActiveCfg = Release|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.Build.0 = Release|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.Build.0 = Release|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
|
||||
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.Build.0 = Debug|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.ActiveCfg = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.Build.0 = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.Build.0 = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.ActiveCfg = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.Build.0 = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.ActiveCfg = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.Build.0 = Release|x64
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.ActiveCfg = Release|Win32
|
||||
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,271 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\dht_proxy_client.cpp" />
|
||||
<ClCompile Include="..\src\http.cpp" />
|
||||
<ClCompile Include="..\src\network_utils.cpp" />
|
||||
<ClCompile Include="..\src\op_cache.cpp" />
|
||||
<ClCompile Include="..\src\peer_discovery.cpp" />
|
||||
<ClCompile Include="..\src\rng.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\thread_pool.cpp" />
|
||||
<ClCompile Include="wingetopt.c" />
|
||||
<ClCompile Include="..\src\base64.cpp" />
|
||||
<ClCompile Include="..\src\callbacks.cpp" />
|
||||
<ClCompile Include="..\src\crypto.cpp" />
|
||||
<ClCompile Include="..\src\default_types.cpp" />
|
||||
<ClCompile Include="..\src\dht.cpp" />
|
||||
<ClCompile Include="..\src\dhtrunner.cpp" />
|
||||
<ClCompile Include="..\src\dht_proxy_server.cpp" />
|
||||
<ClCompile Include="..\src\indexation\pht.cpp" />
|
||||
<ClCompile Include="..\src\infohash.cpp" />
|
||||
<ClCompile Include="..\src\log.cpp" />
|
||||
<ClCompile Include="..\src\network_engine.cpp" />
|
||||
<ClCompile Include="..\src\node.cpp" />
|
||||
<ClCompile Include="..\src\node_cache.cpp" />
|
||||
<ClCompile Include="..\src\routing_table.cpp" />
|
||||
<ClCompile Include="..\src\securedht.cpp" />
|
||||
<ClCompile Include="..\src\utils.cpp" />
|
||||
<ClCompile Include="..\src\value.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\opendht\http.h" />
|
||||
<ClInclude Include="..\src\network_utils.h" />
|
||||
<ClInclude Include="..\src\thread_pool.h" />
|
||||
<ClInclude Include="unistd.h" />
|
||||
<ClInclude Include="wingetopt.h" />
|
||||
<ClInclude Include="..\include\opendht.h" />
|
||||
<ClInclude Include="..\include\opendht\callbacks.h" />
|
||||
<ClInclude Include="..\include\opendht\crypto.h" />
|
||||
<ClInclude Include="..\include\opendht\def.h" />
|
||||
<ClInclude Include="..\include\opendht\default_types.h" />
|
||||
<ClInclude Include="..\include\opendht\dht.h" />
|
||||
<ClInclude Include="..\include\opendht\dhtrunner.h" />
|
||||
<ClInclude Include="..\include\opendht\dht_proxy_server.h" />
|
||||
<ClInclude Include="..\include\opendht\indexation\pht.h" />
|
||||
<ClInclude Include="..\include\opendht\infohash.h" />
|
||||
<ClInclude Include="..\include\opendht\log.h" />
|
||||
<ClInclude Include="..\include\opendht\log_enable.h" />
|
||||
<ClInclude Include="..\include\opendht\network_engine.h" />
|
||||
<ClInclude Include="..\include\opendht\node.h" />
|
||||
<ClInclude Include="..\include\opendht\node_cache.h" />
|
||||
<ClInclude Include="..\include\opendht\rate_limiter.h" />
|
||||
<ClInclude Include="..\include\opendht\rng.h" />
|
||||
<ClInclude Include="..\include\opendht\routing_table.h" />
|
||||
<ClInclude Include="..\include\opendht\scheduler.h" />
|
||||
<ClInclude Include="..\include\opendht\securedht.h" />
|
||||
<ClInclude Include="..\include\opendht\sockaddr.h" />
|
||||
<ClInclude Include="..\include\opendht\utils.h" />
|
||||
<ClInclude Include="..\include\opendht\value.h" />
|
||||
<ClInclude Include="..\src\base64.h" />
|
||||
<ClInclude Include="..\src\listener.h" />
|
||||
<ClInclude Include="..\src\net.h" />
|
||||
<ClInclude Include="..\src\parsed_message.h" />
|
||||
<ClInclude Include="..\src\request.h" />
|
||||
<ClInclude Include="..\src\search.h" />
|
||||
<ClInclude Include="..\src\storage.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{711397CE-E5D5-467D-9457-8716C047E50C}</ProjectGuid>
|
||||
<RootNamespace>opendht</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
mkdir $(OutDir)\include\opendht
|
||||
mkdir $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
mkdir $(OutDir)\include\opendht
|
||||
mkdir $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
mkdir $(OutDir)\include\opendht
|
||||
mkdir $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
mkdir $(OutDir)\include\opendht
|
||||
mkdir $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
|
||||
copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,198 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\callbacks.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\crypto.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\default_types.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\dht.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\dhtrunner.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\infohash.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\network_engine.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\node.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\node_cache.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\routing_table.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\securedht.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\value.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\base64.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\dht_proxy_server.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\indexation\pht.cpp">
|
||||
<Filter>Source Files\indexation</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wingetopt.c" />
|
||||
<ClCompile Include="..\src\rng.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\op_cache.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\dht_proxy_client.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\peer_discovery.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\network_utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\thread_pool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\http.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\opendht.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\callbacks.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\crypto.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\default_types.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\dht.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\dht_proxy_server.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\dhtrunner.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\infohash.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\log.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\log_enable.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\network_engine.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\node.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\node_cache.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\rate_limiter.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\rng.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\routing_table.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\scheduler.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\securedht.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\utils.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\value.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\indexation\pht.h">
|
||||
<Filter>Header Files\opendht\indexation</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="unistd.h" />
|
||||
<ClInclude Include="wingetopt.h" />
|
||||
<ClInclude Include="..\include\opendht\def.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\net.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\parsed_message.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\sockaddr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\network_utils.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\thread_pool.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\listener.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\base64.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\search.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\request.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\storage.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\opendht\http.h">
|
||||
<Filter>Header Files\opendht</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{be73d179-6cf2-4c05-8d91-53c8499a7134}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{d1ab5bfe-3ab1-45ee-9324-b4b071887668}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\indexation">
|
||||
<UniqueIdentifier>{939134d3-d5a2-4458-bca8-a10ea9042ea2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\opendht">
|
||||
<UniqueIdentifier>{0b46e2d0-4874-404c-bae3-fae8d49b85b8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\opendht\indexation">
|
||||
<UniqueIdentifier>{03bd5139-2ae5-41b0-a77b-944814e1b2b6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -14,9 +14,9 @@ Values are distributed over the network, with redundancy.
|
||||
* High resilience to network disruption
|
||||
* Public key cryptography layer providing optional data signature and encryption (using GnuTLS)
|
||||
* IPv4 and IPv6 support
|
||||
* Clean and powerful C++14 map API
|
||||
* Python 3 bindings
|
||||
* REST API
|
||||
* Clean and powerful **C++14** map API
|
||||
* Bindings for **C, Rust & Python 3**
|
||||
* REST API with optional HTTP client+server with push notification support
|
||||
|
||||
## Documentation
|
||||
See the wiki: <https://github.com/savoirfairelinux/opendht/wiki>
|
||||
@@ -27,7 +27,7 @@ Build instructions: <https://github.com/savoirfairelinux/opendht/wiki/Build-the-
|
||||
|
||||
#### How-to build a simple client app
|
||||
```bash
|
||||
g++ main.cpp -std=c++14 -lopendht -lgnutls
|
||||
g++ main.cpp -std=c++14 -lopendht
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -51,7 +51,7 @@ int main()
|
||||
|
||||
// Join the network through any running node,
|
||||
// here using a known bootstrap node.
|
||||
node.bootstrap("bootstrap.ring.cx", "4222");
|
||||
node.bootstrap("bootstrap.jami.net", "4222");
|
||||
|
||||
// put some data on the dht
|
||||
std::vector<uint8_t> some_data(5, 10);
|
||||
@@ -82,7 +82,7 @@ node.run()
|
||||
|
||||
# Join the network through any running node,
|
||||
# here using a known bootstrap node.
|
||||
node.bootstrap("bootstrap.ring.cx", "4222")
|
||||
node.bootstrap("bootstrap.jami.net", "4222")
|
||||
|
||||
# blocking call (provide callback arguments to make the call non-blocking)
|
||||
node.put(dht.InfoHash.get("unique_key"), dht.Value(b'some binary data'))
|
||||
@@ -103,10 +103,10 @@ for r in results:
|
||||
|
||||
## Contact
|
||||
|
||||
IRC: join us on Freenode at [`#opendht`](https://webchat.freenode.net/?channels=%23opendht).
|
||||
IRC: join us on Libera.chat at [`#opendht`](https://web.libera.chat/#opendht).
|
||||
|
||||
## License
|
||||
Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
|
||||
OpenDHT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
-1
Submodule argon2 deleted from 62358ba212.
@@ -1,2 +1 @@
|
||||
git submodule update --init
|
||||
autoreconf --install --verbose -Wall
|
||||
+2
-2
@@ -124,7 +124,7 @@ void dht_publickey_delete(dht_publickey* pk) {
|
||||
|
||||
int dht_publickey_export(const dht_publickey* pk, char* out, size_t* outlen) {
|
||||
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
|
||||
return gnutls_pubkey_export(pkey->pk, GNUTLS_X509_FMT_DER, out, outlen);
|
||||
return pkey->pack((uint8_t*)out, outlen);
|
||||
}
|
||||
|
||||
dht_infohash dht_publickey_get_id(const dht_publickey* pk) {
|
||||
@@ -173,7 +173,7 @@ int dht_privatekey_export(const dht_privatekey* k, char* out, size_t* out_size,
|
||||
|
||||
dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
|
||||
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
|
||||
return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(key->getPublicKey())));
|
||||
return reinterpret_cast<dht_publickey*>(new PubkeySp(key->getSharedPublicKey()));
|
||||
}
|
||||
|
||||
void dht_privatekey_delete(dht_privatekey* pk) {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# University of Illinois/NCSA
|
||||
# Open Source License
|
||||
#
|
||||
# Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Developed by:
|
||||
#
|
||||
# LLVM Team
|
||||
#
|
||||
# University of Illinois at Urbana-Champaign
|
||||
#
|
||||
# http://llvm.org
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# this software and associated documentation files (the "Software"), to deal with
|
||||
# the Software without restriction, including without limitation the rights to
|
||||
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
# of the Software, and to permit persons to whom the Software is furnished to do
|
||||
# so, subject to the following conditions:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimers.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimers in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the names of the LLVM Team, University of Illinois at
|
||||
# Urbana-Champaign, nor the names of its contributors may be used to
|
||||
# endorse or promote products derived from this Software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
# SOFTWARE.
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
get_directory_property(compile_options COMPILE_OPTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS ${compile_options})
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<int64_t> v1;
|
||||
std::atomic<int64_t> v2;
|
||||
int main(int, char**) {
|
||||
return v1 + v2;
|
||||
}" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_working_cxx_atomics)
|
||||
|
||||
|
||||
if(NOT DEFINED PROXYGEN_COMPILER_IS_GCC_COMPATIBLE)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
|
||||
elseif(MSVC)
|
||||
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE OFF)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
|
||||
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This isn't necessary on MSVC, so avoid command-line switch annoyance
|
||||
# by only running on GCC-like hosts.
|
||||
if(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE)
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if(HAVE_LIBATOMIC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
list(APPEND CMAKE_CXX_STANDARD_LIBRARIES -latomic)
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -1,28 +0,0 @@
|
||||
INCLUDE(FindPkgConfig)
|
||||
PKG_CHECK_MODULES(PC_CPPUNIT "cppunit")
|
||||
|
||||
FIND_PATH(CPPUNIT_INCLUDE_DIRS
|
||||
NAMES cppunit/TestCase.h
|
||||
HINTS ${PC_CPPUNIT_INCLUDE_DIR}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(CPPUNIT_LIBRARIES
|
||||
NAMES cppunit
|
||||
HINTS ${PC_CPPUNIT_LIBDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
${CMAKE_INSTALL_PREFIX}/lib64
|
||||
PATHS
|
||||
${CPPUNIT_INCLUDE_DIRS}/../lib
|
||||
/usr/local/lib
|
||||
/usr/lib
|
||||
)
|
||||
|
||||
LIST(APPEND CPPUNIT_LIBRARIES ${CMAKE_DL_LIBS})
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CPPUNIT DEFAULT_MSG CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
|
||||
MARK_AS_ADVANCED(CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
|
||||
+7
-31
@@ -1,7 +1,7 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 2)
|
||||
m4_define([opendht_minor_version], 0)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_minor_version], 3)
|
||||
m4_define([opendht_patch_version], 2)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
|
||||
@@ -132,6 +132,8 @@ 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"],
|
||||
@@ -140,6 +142,7 @@ AS_IF([test "x$with_jsoncpp" != "xno"],
|
||||
AS_IF([test "x$have_jsoncpp" = "xyes"], [
|
||||
AC_MSG_NOTICE([Using JsonCpp])
|
||||
CPPFLAGS+=" -DOPENDHT_JSONCPP"
|
||||
AC_SUBST(jsoncpp_lib, [", jsoncpp"])
|
||||
], [
|
||||
AC_MSG_NOTICE([Not using JsonCpp])
|
||||
AM_COND_IF(PROXY_CLIENT_OR_SERVER, AC_MSG_ERROR(["JsonCpp is required for proxy/push notification support"]))
|
||||
@@ -151,18 +154,11 @@ AS_IF([test "x$with_openssl" != "xno"],
|
||||
[have_openssl=no])
|
||||
AS_IF([test "x$have_openssl" = "xyes"], [
|
||||
AC_MSG_NOTICE([Using OpenSSL])
|
||||
AC_SUBST(openssl_lib, [", openssl"])
|
||||
], [
|
||||
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"
|
||||
@@ -175,32 +171,12 @@ AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
# http_parser has no pkgconfig, instead we check with:
|
||||
AC_CHECK_LIB(http_parser, exit,, AC_MSG_ERROR([Missing HttpParser library files]))
|
||||
AC_CHECK_HEADERS([http_parser.h], [http_parser_headers=yes; break;])
|
||||
AC_SUBST(http_parser_lib, ["-lhttp_parser"])
|
||||
AS_IF([test "x$http_parser_headers" != "xyes"], AC_MSG_ERROR([Missing HttpParser headers files]))
|
||||
])
|
||||
|
||||
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], [
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ FROM aberaud/opendht-deps
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
RUN git clone https://github.com/savoirfairelinux/opendht.git \
|
||||
&& cd opendht && mkdir build && cd build \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On && make -j8 && make install \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
|
||||
&& cd ../.. && rm -rf opendht
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.0.0
|
||||
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.1.3
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
RUN git clone https://github.com/savoirfairelinux/opendht.git \
|
||||
|
||||
+17
-46
@@ -1,56 +1,27 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev \
|
||||
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
|
||||
autotools-dev autoconf libssl-dev \
|
||||
dialog apt-utils \
|
||||
&& apt-get clean \
|
||||
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential pkg-config cmake git wget \
|
||||
autotools-dev autoconf \
|
||||
cython3 python3-dev python3-setuptools \
|
||||
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
|
||||
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
|
||||
libssl-dev libfmt-dev libhttp-parser-dev libasio-dev libmsgpack-dev \
|
||||
&& apt-get clean
|
||||
|
||||
RUN echo "*** Installing libfmt ***" \
|
||||
&& wget https://github.com/fmtlib/fmt/archive/5.3.0.tar.gz \
|
||||
&& tar -xzf 5.3.0.tar.gz && cd fmt-5.3.0/ \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=On -DFMT_TEST=Off -DFMT_DOC=Off . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../ && rm -rf fmt*
|
||||
|
||||
# libhttp-parser-dev is 2.1-2 which is too old
|
||||
RUN echo "*** Building nodejs/http_parser dependency ***" \
|
||||
&& wget https://github.com/nodejs/http-parser/archive/v2.9.2.tar.gz \
|
||||
&& tar xvf v2.9.2.tar.gz && cd http-parser-2.9.2/ \
|
||||
&& PREFIX=/usr make -j8 install \
|
||||
&& cd ../ && rm -rf http-parser*
|
||||
|
||||
# libasio-dev (1.10.6-3) is too old
|
||||
RUN echo "** Building a recent version of asio ***" \
|
||||
&& wget https://github.com/aberaud/asio/archive/b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz \
|
||||
&& tar -xvf b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz && cd asio-b2b7a1c166390459e1c169c8ae9ef3234b361e3f/asio \
|
||||
&& ./autogen.sh && ./configure --prefix=/usr --without-boost --disable-examples --disable-tests \
|
||||
&& make install \
|
||||
&& cd ../../ && rm -rf asio*
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
|
||||
&& ls -l && tar -xzf a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
|
||||
&& cd restinio-a7a10e419d9089c5b8ee63f5e3098c892f22fae4/dev \
|
||||
&& wget https://github.com/aberaud/restinio/archive/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
|
||||
|
||||
# build restbed from sources
|
||||
RUN git clone --recursive https://github.com/corvusoft/restbed.git \
|
||||
&& cd restbed && mkdir build && cd build \
|
||||
&& cmake -DBUILD_TESTS=NO -DBUILD_EXAMPLES=NO -DBUILD_SSL=NO -DBUILD_SHARED=YES -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib .. \
|
||||
&& make -j8 install \
|
||||
&& cd .. && rm -rf restbed
|
||||
|
||||
#build msgpack from source
|
||||
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-2.1.5/msgpack-2.1.5.tar.gz \
|
||||
&& tar -xzf msgpack-2.1.5.tar.gz \
|
||||
&& cd msgpack-2.1.5 && mkdir build && cd build \
|
||||
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../.. && rm -rf msgpack-2.1.5 msgpack-2.1.5.tar.gz
|
||||
&& cd ../../.. && rm -rf restinio
|
||||
@@ -3,15 +3,17 @@ MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
RUN echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
|
||||
RUN apt-get update && apt-get install -y \
|
||||
apt-transport-https build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev \
|
||||
apt-transport-https build-essential pkg-config git wget libncurses5-dev libreadline-dev nettle-dev \
|
||||
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev \
|
||||
&& apt-get clean
|
||||
|
||||
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
|
||||
|
||||
# libasio-dev (1.10) is too old
|
||||
RUN echo "** Building a recent version of asio ***" \
|
||||
&& wget https://github.com/aberaud/asio/archive/b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz \
|
||||
&& tar -xvf b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz && cd asio-b2b7a1c166390459e1c169c8ae9ef3234b361e3f/asio \
|
||||
&& wget https://github.com/aberaud/asio/archive/a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz \
|
||||
&& tar -xvf a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz && cd asio-a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571/asio \
|
||||
&& ./autogen.sh && ./configure --prefix=/usr --without-boost --disable-examples --disable-tests \
|
||||
&& make install \
|
||||
&& cd ../../ && rm -rf asio*
|
||||
|
||||
+12
-46
@@ -1,62 +1,28 @@
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
RUN apt-get update && apt-get install -y \
|
||||
dialog apt-utils \
|
||||
&& apt-get clean \
|
||||
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y llvm llvm-dev clang make cmake git wget libncurses5-dev libreadline-dev \
|
||||
&& apt-get install -y llvm llvm-dev clang make cmake pkg-config git wget libncurses5-dev libreadline-dev \
|
||||
nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev cython3 python3-dev \
|
||||
python3-setuptools libcppunit-dev python3-pip \
|
||||
autotools-dev autoconf libssl-dev \
|
||||
autotools-dev autoconf libssl-dev libargon2-dev \
|
||||
libfmt-dev libhttp-parser-dev libasio-dev \
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
|
||||
|
||||
ENV CC cc
|
||||
ENV CXX c++
|
||||
|
||||
RUN echo "*** Installing libfmt ***" \
|
||||
&& wget https://github.com/fmtlib/fmt/archive/5.3.0.tar.gz \
|
||||
&& tar -xzf 5.3.0.tar.gz && cd fmt-5.3.0/ \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=On -DFMT_TEST=Off -DFMT_DOC=Off . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../ && rm -rf fmt*
|
||||
|
||||
# libhttp-parser-dev is 2.1-2 which is too old
|
||||
RUN echo "*** Building nodejs/http_parser dependency ***" \
|
||||
&& wget https://github.com/nodejs/http-parser/archive/v2.9.2.tar.gz \
|
||||
&& tar xvf v2.9.2.tar.gz && cd http-parser-2.9.2/ \
|
||||
&& PREFIX=/usr make -j8 install \
|
||||
&& cd ../ && rm -rf http-parser*
|
||||
|
||||
# libasio-dev (1.10.6-3) is too old
|
||||
RUN echo "** Building a recent version of asio ***" \
|
||||
&& wget https://github.com/aberaud/asio/archive/b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz \
|
||||
&& tar -xvf b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz && cd asio-b2b7a1c166390459e1c169c8ae9ef3234b361e3f/asio \
|
||||
&& ./autogen.sh && ./configure --prefix=/usr --without-boost --disable-examples --disable-tests \
|
||||
&& make install \
|
||||
&& cd ../../ && rm -rf asio*
|
||||
|
||||
#patch for https://github.com/Stiffstream/restinio-conan-example/issues/2
|
||||
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
|
||||
&& ls -l && tar -xzf a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
|
||||
&& cd restinio-a7a10e419d9089c5b8ee63f5e3098c892f22fae4/dev \
|
||||
&& wget https://github.com/aberaud/restinio/archive/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
|
||||
# build restbed from sources
|
||||
RUN git clone --recursive https://github.com/corvusoft/restbed.git \
|
||||
&& cd restbed && mkdir build && cd build \
|
||||
&& cmake -DBUILD_TESTS=NO -DBUILD_EXAMPLES=NO -DBUILD_SSL=NO -DBUILD_SHARED=YES -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib .. \
|
||||
&& make -j8 install \
|
||||
&& cd .. && rm -rf restbed
|
||||
|
||||
#build msgpack from source
|
||||
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-2.1.5/msgpack-2.1.5.tar.gz \
|
||||
&& tar -xzf msgpack-2.1.5.tar.gz \
|
||||
&& cd msgpack-2.1.5 && mkdir build && cd build \
|
||||
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../.. && rm -rf msgpack-2.1.5 msgpack-2.1.5.tar.gz
|
||||
@@ -0,0 +1,6 @@
|
||||
FROM aberaud/opendht-deps-llvm
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
RUN git clone https://github.com/savoirfairelinux/opendht.git \
|
||||
&& cd opendht && mkdir build && cd build \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
|
||||
&& cd ../.. && rm -rf opendht
|
||||
@@ -1,7 +1,9 @@
|
||||
FROM aberaud/opendht-deps
|
||||
FROM aberaud/opendht-deps-bionic
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
|
||||
|
||||
COPY . /root/opendht
|
||||
RUN cd /root/opendht && mkdir build && cd build \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_TESTS=ON .. \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_C=On -DOPENDHT_LTO=On -DOPENDHT_TESTS=ON .. \
|
||||
&& make -j8 && ./opendht_unit_tests && make install
|
||||
@@ -3,5 +3,5 @@ MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
COPY . /root/opendht
|
||||
RUN cd /root/opendht && mkdir build && cd build \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_TESTS=ON .. \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_C=On -DOPENDHT_TESTS=ON .. \
|
||||
&& make -j8 && ./opendht_unit_tests && make install
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+35
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#ifdef OPENDHT_JSONCPP
|
||||
#include <json/json.h>
|
||||
@@ -57,6 +58,8 @@ struct OPENDHT_PUBLIC NodeStats {
|
||||
cached_nodes {0},
|
||||
incoming_nodes {0};
|
||||
unsigned table_depth {0};
|
||||
unsigned searches {0};
|
||||
unsigned node_cache_size {0};
|
||||
unsigned getKnownNodes() const { return good_nodes + dubious_nodes; }
|
||||
unsigned long getNetworkSizeEstimation() const { return 8 * std::exp2(table_depth); }
|
||||
std::string toString() const;
|
||||
@@ -70,7 +73,7 @@ struct OPENDHT_PUBLIC NodeStats {
|
||||
explicit NodeStats(const Json::Value& v);
|
||||
#endif
|
||||
|
||||
MSGPACK_DEFINE_MAP(good_nodes, dubious_nodes, cached_nodes, incoming_nodes, table_depth)
|
||||
MSGPACK_DEFINE_MAP(good_nodes, dubious_nodes, cached_nodes, incoming_nodes, table_depth, searches, node_cache_size)
|
||||
};
|
||||
|
||||
struct OPENDHT_PUBLIC NodeInfo {
|
||||
@@ -79,6 +82,8 @@ struct OPENDHT_PUBLIC NodeInfo {
|
||||
NodeStats ipv4 {};
|
||||
NodeStats ipv6 {};
|
||||
size_t ongoing_ops {0};
|
||||
in_port_t bound4 {0};
|
||||
in_port_t bound6 {0};
|
||||
|
||||
#ifdef OPENDHT_JSONCPP
|
||||
/**
|
||||
@@ -115,11 +120,24 @@ struct OPENDHT_PUBLIC Config {
|
||||
/** If set, the dht will load its state from this file on start and save its state in this file on shutdown */
|
||||
std::string persist_path {};
|
||||
|
||||
/** If non-0, overrides the default global rate-limit.-1 means no limit. */
|
||||
/** If non-0, overrides the default global rate-limit. -1 means no limit. */
|
||||
ssize_t max_req_per_sec {0};
|
||||
|
||||
/** If non-0, overrides the default per-IP address rate-limit. -1 means no limit. */
|
||||
ssize_t max_peer_req_per_sec {0};
|
||||
|
||||
/* If non-0, overrides the default maximum number of searches. -1 means no limit. */
|
||||
ssize_t max_searches {0};
|
||||
|
||||
/* If non-0, overrides the default maximum store size. -1 means no limit. */
|
||||
ssize_t max_store_size {0};
|
||||
|
||||
/**
|
||||
* Use appropriate bahavior for a public IP, stable node:
|
||||
* - No connectivity change triggered when a search fails
|
||||
* - Larger listen refresh time
|
||||
*/
|
||||
bool public_stable {false};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -129,6 +147,12 @@ struct OPENDHT_PUBLIC SecureDhtConfig
|
||||
{
|
||||
Config node_config {};
|
||||
crypto::Identity id {};
|
||||
|
||||
/**
|
||||
* Cache all encountered public keys and certificates,
|
||||
* for use by the certificate store, putEncrypted and putSigned
|
||||
*/
|
||||
bool cert_cache_all {false};
|
||||
};
|
||||
|
||||
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
|
||||
@@ -140,6 +164,7 @@ using GetCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>
|
||||
using ValueCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>& values, bool expired)>;
|
||||
using GetCallbackSimple = std::function<bool(std::shared_ptr<Value> value)>;
|
||||
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)>;
|
||||
|
||||
@@ -154,13 +179,13 @@ typedef bool (*FilterRaw)(const Value&, void *user_data);
|
||||
|
||||
using DoneCallbackSimple = std::function<void(bool success)>;
|
||||
|
||||
OPENDHT_PUBLIC GetCallbackSimple bindGetCb(const GetCallbackRaw& raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC GetCallback bindGetCb(const GetCallbackSimple& cb);
|
||||
OPENDHT_PUBLIC ValueCallback bindValueCb(const ValueCallbackRaw& raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC ShutdownCallback bindShutdownCb(const ShutdownCallbackRaw& shutdown_cb_raw, void* user_data);
|
||||
OPENDHT_PUBLIC GetCallbackSimple bindGetCb(GetCallbackRaw raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC GetCallback bindGetCb(GetCallbackSimple cb);
|
||||
OPENDHT_PUBLIC ValueCallback bindValueCb(ValueCallbackRaw raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC ShutdownCallback bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data);
|
||||
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackSimple donecb);
|
||||
OPENDHT_PUBLIC DoneCallback bindDoneCb(const DoneCallbackRaw& raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC DoneCallbackSimple bindDoneCbSimple(const DoneCallbackSimpleRaw& raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC Value::Filter bindFilterRaw(const FilterRaw& raw_filter, void* user_data);
|
||||
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackRaw raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC DoneCallbackSimple bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data);
|
||||
OPENDHT_PUBLIC Value::Filter bindFilterRaw(FilterRaw raw_filter, void* user_data);
|
||||
|
||||
}
|
||||
+92
-15
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,6 +27,7 @@ extern "C" {
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/abstract.h>
|
||||
#include <gnutls/x509.h>
|
||||
#include <gnutls/ocsp.h>
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
@@ -78,6 +80,8 @@ struct OPENDHT_PUBLIC PublicKey
|
||||
* Takes ownership of an existing gnutls_pubkey.
|
||||
*/
|
||||
PublicKey(gnutls_pubkey_t k) : pk(k) {}
|
||||
|
||||
/** Import public key from serialized data */
|
||||
PublicKey(const uint8_t* dat, size_t dat_size);
|
||||
PublicKey(const Blob& pk) : PublicKey(pk.data(), pk.size()) {}
|
||||
PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; };
|
||||
@@ -104,16 +108,17 @@ struct OPENDHT_PUBLIC PublicKey
|
||||
PkId getLongId() const;
|
||||
|
||||
bool checkSignature(const uint8_t* data, size_t data_len, const uint8_t* signature, size_t signature_len) const;
|
||||
bool checkSignature(const Blob& data, const Blob& signature) const {
|
||||
inline bool checkSignature(const Blob& data, const Blob& signature) const {
|
||||
return checkSignature(data.data(), data.size(), signature.data(), signature.size());
|
||||
}
|
||||
|
||||
Blob encrypt(const uint8_t* data, size_t data_len) const;
|
||||
Blob encrypt(const Blob& data) const {
|
||||
inline Blob encrypt(const Blob& data) const {
|
||||
return encrypt(data.data(), data.size());
|
||||
}
|
||||
|
||||
void pack(Blob& b) const;
|
||||
int pack(uint8_t* out, size_t* out_len) const;
|
||||
void unpack(const uint8_t* dat, size_t dat_size);
|
||||
|
||||
std::string toString() const;
|
||||
@@ -127,7 +132,7 @@ struct OPENDHT_PUBLIC PublicKey
|
||||
p.pack_bin_body((const char*)b.data(), b.size());
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object o);
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
|
||||
gnutls_digest_algorithm_t getPreferredDigest() const;
|
||||
|
||||
@@ -159,7 +164,9 @@ struct OPENDHT_PUBLIC PrivateKey
|
||||
~PrivateKey();
|
||||
explicit operator bool() const { return key; }
|
||||
|
||||
PublicKey getPublicKey() const;
|
||||
const PublicKey& getPublicKey() const;
|
||||
const std::shared_ptr<PublicKey>& getSharedPublicKey() const;
|
||||
|
||||
int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const;
|
||||
Blob serialize(const std::string& password = {}) const;
|
||||
|
||||
@@ -167,14 +174,16 @@ struct OPENDHT_PUBLIC PrivateKey
|
||||
* Sign the provided binary object.
|
||||
* @returns the signature data.
|
||||
*/
|
||||
Blob sign(const Blob&) const;
|
||||
Blob sign(const uint8_t* data, size_t data_len) const;
|
||||
inline Blob sign(const Blob& dat) const { return sign(dat.data(), dat.size()); }
|
||||
|
||||
/**
|
||||
* Try to decrypt the provided cypher text.
|
||||
* In case of failure a CryptoException is thrown.
|
||||
* @returns the decrypted data.
|
||||
*/
|
||||
Blob decrypt(const Blob& cypher) const;
|
||||
Blob decrypt(const uint8_t* cypher, size_t cypher_len) const;
|
||||
Blob decrypt(const Blob& cypher) const { return decrypt(cypher.data(), cypher.size()); }
|
||||
|
||||
/**
|
||||
* Generate a new RSA key pair
|
||||
@@ -192,10 +201,9 @@ private:
|
||||
PrivateKey& operator=(const PrivateKey&) = delete;
|
||||
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
|
||||
|
||||
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
|
||||
mutable std::shared_ptr<PublicKey> publicKey_ {};
|
||||
};
|
||||
|
||||
|
||||
class OPENDHT_PUBLIC RevocationList
|
||||
{
|
||||
using clock = std::chrono::system_clock;
|
||||
@@ -225,7 +233,7 @@ public:
|
||||
p.pack_bin_body((const char*)b.data(), b.size());
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object o);
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
|
||||
void revoke(const Certificate& crt, time_point t = time_point::min());
|
||||
|
||||
@@ -308,6 +316,55 @@ private:
|
||||
gnutls_x509_crq_t request {nullptr};
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC OcspRequest
|
||||
{
|
||||
public:
|
||||
OcspRequest(gnutls_ocsp_req_t r) : request(r) {};
|
||||
OcspRequest(const uint8_t* dat_ptr, size_t dat_size);
|
||||
~OcspRequest();
|
||||
|
||||
/*
|
||||
* Get OCSP Request in readable format.
|
||||
*/
|
||||
std::string toString(const bool compact = true) const;
|
||||
|
||||
Blob pack() const;
|
||||
Blob getNonce() const;
|
||||
private:
|
||||
gnutls_ocsp_req_t request;
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC OcspResponse
|
||||
{
|
||||
public:
|
||||
OcspResponse(const uint8_t* dat_ptr, size_t dat_size);
|
||||
OcspResponse(const std::string& response) : OcspResponse((const uint8_t*)response.data(), response.size()) {};
|
||||
~OcspResponse();
|
||||
|
||||
Blob pack() const;
|
||||
/*
|
||||
* Get OCSP Response in readable format.
|
||||
*/
|
||||
std::string toString(const bool compact = true) const;
|
||||
|
||||
/*
|
||||
* Get OCSP response certificate status.
|
||||
* Return certificate status.
|
||||
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-cert-status-t
|
||||
*/
|
||||
gnutls_ocsp_cert_status_t getCertificateStatus() const;
|
||||
|
||||
/*
|
||||
* Verify OCSP response and return OCSP status.
|
||||
* Throws CryptoException in case of error in the response.
|
||||
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-verify-reason-t
|
||||
*/
|
||||
gnutls_ocsp_cert_status_t verifyDirect(const Certificate& crt, const Blob& nonce);
|
||||
|
||||
private:
|
||||
gnutls_ocsp_resp_t response;
|
||||
};
|
||||
|
||||
struct OPENDHT_PUBLIC Certificate {
|
||||
Certificate() noexcept {}
|
||||
|
||||
@@ -423,7 +480,7 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
p.pack_bin_body((const char*)b.data(), b.size());
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object o);
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
|
||||
explicit operator bool() const { return cert; }
|
||||
PublicKey getPublicKey() const;
|
||||
@@ -433,6 +490,8 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
/** Same as getPublicKey().getLongId() */
|
||||
PkId getLongId() const;
|
||||
|
||||
Blob getSerialNumber() const;
|
||||
|
||||
/** Read certificate Common Name (CN) */
|
||||
std::string getName() const;
|
||||
|
||||
@@ -482,8 +541,8 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
void addRevocationList(RevocationList&&);
|
||||
void addRevocationList(std::shared_ptr<RevocationList>);
|
||||
|
||||
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false);
|
||||
static Certificate generate(const CertificateRequest& request, const Identity& ca);
|
||||
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false, int64_t validity = 0);
|
||||
static Certificate generate(const CertificateRequest& request, const Identity& ca, int64_t validity = 0);
|
||||
|
||||
gnutls_x509_crt_t getCopy() const {
|
||||
if (not cert)
|
||||
@@ -526,11 +585,27 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
|
||||
gnutls_digest_algorithm_t getPreferredDigest() const;
|
||||
|
||||
/*
|
||||
* Generate OCSP request.
|
||||
* Return GnuTLS error code.
|
||||
* https://www.gnutls.org/manual/html_node/Error-codes.html
|
||||
*/
|
||||
std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
|
||||
|
||||
/**
|
||||
* Change certificate's expiration
|
||||
*/
|
||||
void setValidity(const Identity& ca, int64_t validity);
|
||||
void setValidity(const PrivateKey& key, int64_t validity);
|
||||
|
||||
gnutls_x509_crt_t cert {nullptr};
|
||||
std::shared_ptr<Certificate> issuer {};
|
||||
std::shared_ptr<OcspResponse> ocspResponse;
|
||||
private:
|
||||
Certificate(const Certificate&) = delete;
|
||||
Certificate& operator=(const Certificate&) = delete;
|
||||
mutable InfoHash cachedId_ {};
|
||||
mutable PkId cachedLongId_ {};
|
||||
|
||||
struct crlNumberCmp {
|
||||
bool operator() (const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const {
|
||||
@@ -706,8 +781,10 @@ OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, const std::string& password);
|
||||
/**
|
||||
* AES-GCM decryption.
|
||||
*/
|
||||
OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const Blob& key);
|
||||
OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const std::string& password);
|
||||
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t* data, size_t data_length, const Blob& key);
|
||||
OPENDHT_PUBLIC inline Blob aesDecrypt(const Blob& data, const Blob& key) { return aesDecrypt(data.data(), data.size(), key); }
|
||||
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t* data, size_t data_length, const std::string& password);
|
||||
OPENDHT_PUBLIC inline Blob aesDecrypt(const Blob& data, const std::string& password) { return aesDecrypt(data.data(), data.size(), password); }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -66,8 +66,10 @@ private:
|
||||
|
||||
public:
|
||||
virtual void unpackValue(const Value& v) override {
|
||||
if (v.owner)
|
||||
if (v.owner) {
|
||||
owner = v.owner;
|
||||
from = v.owner->getId();
|
||||
}
|
||||
BaseClass::unpackValue(v);
|
||||
}
|
||||
|
||||
@@ -75,6 +77,7 @@ public:
|
||||
return [](const Value& v){ return v.isSigned(); };
|
||||
}
|
||||
|
||||
Sp<crypto::PublicKey> owner;
|
||||
dht::InfoHash from;
|
||||
};
|
||||
|
||||
@@ -144,17 +147,18 @@ public:
|
||||
static const ValueType TYPE;
|
||||
|
||||
TrustRequest() {}
|
||||
TrustRequest(std::string s) : service(s) {}
|
||||
TrustRequest(std::string s, const Blob& d) : service(s), payload(d) {}
|
||||
TrustRequest(std::string s, std::string ci = {}) : service(s), conversationId(ci) {}
|
||||
TrustRequest(std::string s, std::string ci, const Blob& d) : service(s), conversationId(ci), payload(d) {}
|
||||
|
||||
static Value::Filter getFilter() {
|
||||
return EncryptedValue::getFilter();
|
||||
}
|
||||
|
||||
std::string service;
|
||||
std::string conversationId;
|
||||
Blob payload;
|
||||
bool confirm {false};
|
||||
MSGPACK_DEFINE_MAP(service, payload, confirm)
|
||||
MSGPACK_DEFINE_MAP(service, conversationId, payload, confirm)
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC IceCandidates : public EncryptedValue<IceCandidates>
|
||||
@@ -189,7 +193,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void msgpack_unpack(msgpack::object o)
|
||||
virtual void msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
|
||||
if (o.via.array.size < 2) throw msgpack::type_error();
|
||||
@@ -229,7 +233,7 @@ public:
|
||||
pk.pack_bin_body((const char*)addr.get(), addr.getLength());
|
||||
}
|
||||
|
||||
virtual void msgpack_unpack(msgpack::object o)
|
||||
virtual void msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (o.type == msgpack::type::BIN)
|
||||
addr = {(sockaddr*)o.via.bin.ptr, (socklen_t)o.via.bin.size};
|
||||
|
||||
+74
-33
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
@@ -61,14 +61,15 @@ struct LocalListener;
|
||||
*/
|
||||
class OPENDHT_PUBLIC Dht final : public DhtInterface {
|
||||
public:
|
||||
|
||||
Dht();
|
||||
|
||||
/**
|
||||
* Initialise the Dht with two open sockets (for IPv4 and IP6)
|
||||
* and an ID for the node.
|
||||
*/
|
||||
Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Logger& l = {});
|
||||
Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Sp<Logger>& l = {});
|
||||
|
||||
Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Logger& l = {})
|
||||
: Dht(std::move(sock), config, std::make_shared<Logger>(l)) {}
|
||||
|
||||
virtual ~Dht();
|
||||
|
||||
/**
|
||||
@@ -76,10 +77,14 @@ public:
|
||||
*/
|
||||
inline const InfoHash& getNodeId() const override { return myid; }
|
||||
|
||||
NodeStatus updateStatus(sa_family_t af) override;
|
||||
|
||||
/**
|
||||
* Get the current status of the node for the given family.
|
||||
*/
|
||||
NodeStatus getStatus(sa_family_t af) const override;
|
||||
NodeStatus getStatus(sa_family_t af) const override {
|
||||
return dht(af).status;
|
||||
}
|
||||
|
||||
NodeStatus getStatus() const override {
|
||||
return std::max(getStatus(AF_INET), getStatus(AF_INET6));
|
||||
@@ -90,7 +95,7 @@ public:
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb) override;
|
||||
void shutdown(ShutdownCallback cb, bool stop = false) override;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
@@ -107,6 +112,15 @@ public:
|
||||
return types.getType(type_id);
|
||||
}
|
||||
|
||||
void addBootstrap(const std::string& host, const std::string& service) override {
|
||||
bootstrap_nodes.emplace_back(host, service);
|
||||
startBootstrap();
|
||||
}
|
||||
|
||||
void clearBootstrap() override {
|
||||
bootstrap_nodes.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a node in the main routing table.
|
||||
* The node is not pinged, so this should be
|
||||
@@ -119,9 +133,9 @@ public:
|
||||
|
||||
void pingNode(SockAddr, DoneCallbackSimple&& cb={}) override;
|
||||
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, 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));
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, SockAddr, const time_point& now) override;
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
|
||||
return periodic(buf, buflen, SockAddr(from, fromlen), now);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,10 +340,10 @@ private:
|
||||
static constexpr unsigned LISTEN_NODES {4};
|
||||
|
||||
/* The maximum number of hashes we're willing to track. */
|
||||
static constexpr unsigned MAX_HASHES {64 * 1024};
|
||||
static constexpr unsigned MAX_HASHES {1024 * 1024};
|
||||
|
||||
/* The maximum number of searches we keep data about. */
|
||||
static constexpr unsigned MAX_SEARCHES {64 * 1024};
|
||||
static constexpr unsigned MAX_SEARCHES {1024 * 1024};
|
||||
|
||||
static constexpr std::chrono::minutes MAX_STORAGE_MAINTENANCE_EXPIRE_TIME {10};
|
||||
|
||||
@@ -337,9 +351,12 @@ private:
|
||||
static constexpr std::chrono::minutes SEARCH_EXPIRE_TIME {62};
|
||||
|
||||
/* Timeout for listen */
|
||||
static constexpr std::chrono::seconds LISTEN_EXPIRE_TIME {30};
|
||||
static constexpr duration LISTEN_EXPIRE_TIME {std::chrono::seconds(30)};
|
||||
static constexpr duration LISTEN_EXPIRE_TIME_PUBLIC {std::chrono::minutes(5)};
|
||||
|
||||
static constexpr std::chrono::seconds REANNOUNCE_MARGIN {10};
|
||||
static constexpr duration REANNOUNCE_MARGIN {std::chrono::seconds(10)};
|
||||
|
||||
static constexpr std::chrono::seconds BOOTSTRAP_PERIOD {10};
|
||||
|
||||
static constexpr size_t TOKEN_SIZE {32};
|
||||
|
||||
@@ -353,6 +370,8 @@ private:
|
||||
Dht(const Dht&) = delete;
|
||||
Dht& operator=(const Dht&) = delete;
|
||||
|
||||
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
|
||||
|
||||
InfoHash myid {};
|
||||
|
||||
uint64_t secret {};
|
||||
@@ -361,40 +380,49 @@ private:
|
||||
// registred types
|
||||
TypeStore types;
|
||||
|
||||
// the stuff
|
||||
RoutingTable buckets4 {};
|
||||
RoutingTable buckets6 {};
|
||||
using SearchMap = std::map<InfoHash, Sp<Search>>;
|
||||
struct Kad {
|
||||
RoutingTable buckets {};
|
||||
SearchMap searches {};
|
||||
unsigned pending_pings {0};
|
||||
NodeStatus status;
|
||||
|
||||
NodeStatus getStatus(time_point now) const;
|
||||
NodeStats getNodesStats(time_point now, const InfoHash& myid) const;
|
||||
};
|
||||
|
||||
Kad dht4 {};
|
||||
Kad dht6 {};
|
||||
|
||||
std::vector<std::pair<std::string,std::string>> bootstrap_nodes {};
|
||||
std::chrono::steady_clock::duration bootstrap_period {BOOTSTRAP_PERIOD};
|
||||
Sp<Scheduler::Job> bootstrapJob {};
|
||||
|
||||
std::map<InfoHash, Storage> store;
|
||||
std::map<SockAddr, StorageBucket, SockAddr::ipCmp> store_quota;
|
||||
size_t total_values {0};
|
||||
size_t total_store_size {0};
|
||||
size_t max_store_keys {MAX_HASHES};
|
||||
size_t max_store_size {DEFAULT_STORAGE_LIMIT};
|
||||
|
||||
using SearchMap = std::map<InfoHash, Sp<Search>>;
|
||||
SearchMap searches4 {};
|
||||
SearchMap searches6 {};
|
||||
uint16_t search_id {0};
|
||||
size_t max_searches {MAX_SEARCHES};
|
||||
size_t search_id {0};
|
||||
|
||||
// map a global listen token to IPv4, IPv6 specific listen tokens.
|
||||
// 0 is the invalid token.
|
||||
std::map<size_t, std::tuple<size_t, size_t, size_t>> listeners {};
|
||||
size_t listener_token {1};
|
||||
|
||||
|
||||
// timing
|
||||
Scheduler scheduler;
|
||||
Sp<Scheduler::Job> nextNodesConfirmation {};
|
||||
Sp<Scheduler::Job> nextStorageMaintenance {};
|
||||
|
||||
net::NetworkEngine network_engine;
|
||||
unsigned pending_pings4 {0};
|
||||
unsigned pending_pings6 {0};
|
||||
|
||||
using ReportedAddr = std::pair<unsigned, SockAddr>;
|
||||
std::vector<ReportedAddr> reported_addr;
|
||||
|
||||
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
|
||||
|
||||
std::string persistPath;
|
||||
|
||||
// are we a bootstrap node ?
|
||||
@@ -403,6 +431,11 @@ private:
|
||||
// be put in bootstrap mode.
|
||||
const bool is_bootstrap {false};
|
||||
const bool maintain_storage {false};
|
||||
const bool public_stable {false};
|
||||
|
||||
inline const duration& getListenExpiration() const {
|
||||
return public_stable ? LISTEN_EXPIRE_TIME_PUBLIC : LISTEN_EXPIRE_TIME;
|
||||
}
|
||||
|
||||
void rotateSecrets();
|
||||
|
||||
@@ -412,7 +445,7 @@ private:
|
||||
void reportedAddr(const SockAddr&);
|
||||
|
||||
// Storage
|
||||
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {});
|
||||
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {}, int version = 0);
|
||||
bool storageStore(const InfoHash& id, const Sp<Value>& value, time_point created, const SockAddr& sa = {}, bool permanent = false);
|
||||
bool storageErase(const InfoHash& id, Value::Id vid);
|
||||
bool storageRefresh(const InfoHash& id, Value::Id vid);
|
||||
@@ -432,8 +465,10 @@ private:
|
||||
size_t maintainStorage(decltype(store)::value_type&, bool force=false, const DoneCallback& donecb={});
|
||||
|
||||
// Buckets
|
||||
RoutingTable& buckets(sa_family_t af) { return af == AF_INET ? buckets4 : buckets6; }
|
||||
const RoutingTable& buckets(sa_family_t af) const { return af == AF_INET ? buckets4 : buckets6; }
|
||||
Kad& dht(sa_family_t af) { return af == AF_INET ? dht4 : dht6; }
|
||||
const Kad& dht(sa_family_t af) const { return af == AF_INET ? dht4 : dht6; }
|
||||
RoutingTable& buckets(sa_family_t af) { return dht(af).buckets; }
|
||||
const RoutingTable& buckets(sa_family_t af) const { return dht(af).buckets; }
|
||||
Bucket* findBucket(const InfoHash& id, sa_family_t af) {
|
||||
auto& b = buckets(af);
|
||||
auto it = b.findBucket(id);
|
||||
@@ -447,6 +482,9 @@ private:
|
||||
void sendCachedPing(Bucket& b);
|
||||
bool bucketMaintenance(RoutingTable&);
|
||||
void dumpBucket(const Bucket& b, std::ostream& out) const;
|
||||
void bootstrap();
|
||||
void startBootstrap();
|
||||
void stopBootstrap();
|
||||
|
||||
// Nodes
|
||||
void onNewNode(const Sp<Node>& node, int confirm);
|
||||
@@ -454,9 +492,8 @@ private:
|
||||
bool trySearchInsert(const Sp<Node>& node);
|
||||
|
||||
// Searches
|
||||
|
||||
inline SearchMap& searches(sa_family_t af) { return af == AF_INET ? searches4 : searches6; }
|
||||
inline const SearchMap& searches(sa_family_t af) const { return af == AF_INET ? searches4 : searches6; }
|
||||
inline SearchMap& searches(sa_family_t af) { return dht(af).searches; }
|
||||
inline const SearchMap& searches(sa_family_t af) const { return dht(af).searches; }
|
||||
|
||||
/**
|
||||
* Low-level method that will perform a search on the DHT for the specified
|
||||
@@ -480,6 +517,9 @@ private:
|
||||
void confirmNodes();
|
||||
void expire();
|
||||
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
|
||||
/**
|
||||
* Generic function to execute when a 'get' request has completed.
|
||||
*
|
||||
@@ -564,7 +604,8 @@ private:
|
||||
const InfoHash& hash,
|
||||
const Blob& token,
|
||||
size_t socket_id,
|
||||
const Query& query);
|
||||
const Query& query,
|
||||
int version = 0);
|
||||
void onListenDone(const Sp<Node>& status,
|
||||
net::RequestAnswer& a,
|
||||
Sp<Search>& sr);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "infohash.h"
|
||||
#include "log_enable.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace dht {
|
||||
|
||||
namespace net {
|
||||
@@ -30,7 +32,8 @@ namespace net {
|
||||
class OPENDHT_PUBLIC DhtInterface {
|
||||
public:
|
||||
DhtInterface() = default;
|
||||
DhtInterface(const Logger& l) : DHT_LOG(l) {};
|
||||
DhtInterface(const Logger& l) : logger_(std::make_shared<Logger>(l)) {};
|
||||
DhtInterface(const std::shared_ptr<Logger>& l) : logger_(l) {};
|
||||
virtual ~DhtInterface() = default;
|
||||
|
||||
// [[deprecated]]
|
||||
@@ -41,9 +44,14 @@ public:
|
||||
/**
|
||||
* Get the current status of the node for the given family.
|
||||
*/
|
||||
virtual NodeStatus updateStatus(sa_family_t af) { return getStatus(af); };
|
||||
virtual NodeStatus getStatus(sa_family_t af) const = 0;
|
||||
virtual NodeStatus getStatus() const = 0;
|
||||
|
||||
void addOnConnectedCallback(std::function<void()> cb) {
|
||||
onConnectCallbacks_.emplace(std::move(cb));
|
||||
}
|
||||
|
||||
virtual net::DatagramSocket* getSocket() const { return {}; };
|
||||
|
||||
/**
|
||||
@@ -53,8 +61,10 @@ public:
|
||||
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
* stop: if true, cancel ongoing operations and call their 'done'
|
||||
* callbacks synchronously.
|
||||
*/
|
||||
virtual void shutdown(ShutdownCallback cb) = 0;
|
||||
virtual void shutdown(ShutdownCallback cb, bool stop = false) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
@@ -68,6 +78,9 @@ public:
|
||||
|
||||
virtual const ValueType& getType(ValueType::Id type_id) const = 0;
|
||||
|
||||
virtual void addBootstrap(const std::string& /*host*/, const std::string& /*service*/) {};
|
||||
virtual void clearBootstrap() {};
|
||||
|
||||
/**
|
||||
* Insert a node in the main routing table.
|
||||
* The node is not pinged, so this should be
|
||||
@@ -78,8 +91,8 @@ public:
|
||||
|
||||
virtual void pingNode(SockAddr, DoneCallbackSimple&& cb={}) = 0;
|
||||
|
||||
virtual time_point periodic(const uint8_t *buf, size_t buflen, SockAddr) = 0;
|
||||
virtual time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) = 0;
|
||||
virtual time_point periodic(const uint8_t *buf, size_t buflen, SockAddr, const time_point& now) = 0;
|
||||
virtual time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) = 0;
|
||||
|
||||
/**
|
||||
* Get a value by searching on all available protocols (IPv4, IPv6),
|
||||
@@ -221,15 +234,23 @@ public:
|
||||
* Enable or disable logging of DHT internal messages
|
||||
*/
|
||||
virtual void setLoggers(LogMethod error = {}, LogMethod warn = {}, LogMethod debug = {}) {
|
||||
DHT_LOG.DBG = debug;
|
||||
DHT_LOG.WARN = warn;
|
||||
DHT_LOG.ERR = error;
|
||||
if (logger_) {
|
||||
logger_->DBG = std::move(debug);
|
||||
logger_->WARN = std::move(warn);
|
||||
logger_->ERR = std::move(error);
|
||||
} else
|
||||
logger_= std::make_shared<Logger>(std::move(error), std::move(warn), std::move(debug));
|
||||
}
|
||||
|
||||
virtual void setLogger(const Logger& l) {
|
||||
DHT_LOG.DBG = l.DBG;
|
||||
DHT_LOG.WARN = l.WARN;
|
||||
DHT_LOG.ERR = l.ERR;
|
||||
if (logger_)
|
||||
*logger_ = l;
|
||||
else
|
||||
logger_= std::make_shared<Logger>(l);
|
||||
}
|
||||
|
||||
virtual void setLogger(const std::shared_ptr<Logger>& l) {
|
||||
logger_ = l;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,7 +258,8 @@ public:
|
||||
*/
|
||||
virtual void setLogFilter(const InfoHash& f)
|
||||
{
|
||||
DHT_LOG.setFilter(f);
|
||||
if (logger_)
|
||||
logger_->setFilter(f);
|
||||
}
|
||||
|
||||
virtual void setPushNotificationToken(const std::string&) {};
|
||||
@@ -249,7 +271,8 @@ public:
|
||||
virtual void pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
|
||||
|
||||
protected:
|
||||
Logger DHT_LOG;
|
||||
std::shared_ptr<Logger> logger_ {};
|
||||
std::queue<std::function<void()>> onConnectCallbacks_ {};
|
||||
};
|
||||
|
||||
} // namespace dht
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb) override;
|
||||
void shutdown(ShutdownCallback cb, bool) override;
|
||||
|
||||
/**
|
||||
* Returns true if the node is running (have access to an open socket).
|
||||
@@ -107,13 +107,13 @@ public:
|
||||
*/
|
||||
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));
|
||||
get(key, cb, bindDoneCb(std::move(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 = {}) override {
|
||||
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
get(key, bindGetCb(cb), std::move(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 = {}) override {
|
||||
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
get(key, bindGetCb(cb), bindDoneCb(std::move(donecb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false) override
|
||||
{
|
||||
put(key, v, bindDoneCb(cb), created, permanent);
|
||||
put(key, v, bindDoneCb(std::move(cb)), created, permanent);
|
||||
}
|
||||
|
||||
void put(const InfoHash& key,
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false) override
|
||||
{
|
||||
put(key, std::make_shared<Value>(std::move(v)), cb, created, permanent);
|
||||
put(key, std::make_shared<Value>(std::move(v)), std::move(cb), created, permanent);
|
||||
}
|
||||
void put(const InfoHash& key,
|
||||
Value&& v,
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
time_point created=time_point::max(),
|
||||
bool permanent = false) override
|
||||
{
|
||||
put(key, std::forward<Value>(v), bindDoneCb(cb), created, permanent);
|
||||
put(key, std::forward<Value>(v), bindDoneCb(std::move(cb)), created, permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,14 +176,14 @@ public:
|
||||
virtual size_t listen(const InfoHash&, ValueCallback, Value::Filter={}, Where={}) override;
|
||||
|
||||
virtual 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){
|
||||
return listen(key, [cb=std::move(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={}) override {
|
||||
return listen(key, bindGetCb(cb), std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
return listen(key, bindGetCb(std::move(cb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
}
|
||||
/*
|
||||
* This function relies on the cache implementation.
|
||||
@@ -197,9 +197,9 @@ public:
|
||||
*/
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>& notification) override;
|
||||
|
||||
time_point periodic(const uint8_t*, size_t, 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));
|
||||
time_point periodic(const uint8_t*, size_t, SockAddr, const time_point& now) override;
|
||||
time_point periodic(const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
|
||||
return periodic(buf, buflen, SockAddr(from, fromlen), now);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
*/
|
||||
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));
|
||||
query(key, cb, bindDoneCb(std::move(done_cb)), std::forward<Query>(q));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,11 +264,10 @@ public:
|
||||
std::vector<unsigned> getNodeMessageStats(bool) override { return {}; }
|
||||
void setStorageLimit(size_t) override {}
|
||||
void connectivityChanged(sa_family_t) override {
|
||||
restartListeners();
|
||||
getProxyInfos();
|
||||
}
|
||||
void connectivityChanged() override {
|
||||
getProxyInfos();
|
||||
restartListeners();
|
||||
loopSignal_();
|
||||
}
|
||||
|
||||
@@ -285,7 +284,7 @@ private:
|
||||
*/
|
||||
struct InfoState;
|
||||
void getProxyInfos();
|
||||
void queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t family, std::shared_ptr<http::Resolver> resolver);
|
||||
void queryProxyInfo(const std::shared_ptr<InfoState>& infoState, const std::shared_ptr<http::Resolver>& resolver, sa_family_t family);
|
||||
void onProxyInfos(const Json::Value& val, const sa_family_t family);
|
||||
SockAddr parsePublicAddress(const Json::Value& val);
|
||||
|
||||
@@ -300,10 +299,12 @@ private:
|
||||
SUBSCRIBE,
|
||||
RESUBSCRIBE,
|
||||
};
|
||||
using CacheValueCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>& values, bool expired, system_clock::time_point)>;
|
||||
|
||||
/**
|
||||
* Send Listen with httpClient_
|
||||
*/
|
||||
void sendListen(const restinio::http_request_header_t header, const ValueCallback& cb,
|
||||
void sendListen(const restinio::http_request_header_t& header, const CacheValueCallback& cb,
|
||||
const Sp<OperationState>& opstate, Listener& listener, ListenMethod method = ListenMethod::LISTEN);
|
||||
void handleResubscribe(const asio::error_code& ec, const InfoHash& key,
|
||||
const size_t token, std::shared_ptr<OperationState> opstate);
|
||||
@@ -327,6 +328,7 @@ private:
|
||||
std::shared_ptr<dht::crypto::Certificate> serverCertificate_;
|
||||
//std::pair<std::string, std::string> serverHostService_;
|
||||
std::string pushClientId_;
|
||||
std::string pushSessionId_;
|
||||
|
||||
mutable std::mutex lockCurrentProxyInfos_;
|
||||
NodeStatus statusIpv4_ {NodeStatus::Disconnected};
|
||||
@@ -335,6 +337,7 @@ private:
|
||||
NodeStats stats6_ {};
|
||||
SockAddr publicAddressV4_;
|
||||
SockAddr publicAddressV6_;
|
||||
std::atomic_bool launchConnectedCbs_ {false};
|
||||
|
||||
InfoHash myid {};
|
||||
|
||||
@@ -376,13 +379,13 @@ private:
|
||||
* Retrieve if we can connect to the proxy (update statusIpvX_)
|
||||
*/
|
||||
void handleProxyConfirm(const asio::error_code &ec);
|
||||
Sp<asio::steady_timer> nextProxyConfirmationTimer_;
|
||||
Sp<asio::steady_timer> listenerRestartTimer_;
|
||||
std::unique_ptr<asio::steady_timer> nextProxyConfirmationTimer_;
|
||||
std::unique_ptr<asio::steady_timer> listenerRestartTimer_;
|
||||
|
||||
/**
|
||||
* Relaunch LISTEN requests if the client disconnect/reconnect.
|
||||
*/
|
||||
void restartListeners();
|
||||
void restartListeners(const asio::error_code &ec);
|
||||
|
||||
/**
|
||||
* Refresh a listen via a token
|
||||
@@ -405,7 +408,6 @@ private:
|
||||
|
||||
Json::StreamWriterBuilder jsonBuilder_;
|
||||
std::unique_ptr<Json::CharReader> jsonReader_;
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
|
||||
std::shared_ptr<http::Request> buildRequest(const std::string& target = {});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
@@ -36,6 +36,15 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace dht {
|
||||
enum class PushType {
|
||||
None = 0,
|
||||
Android,
|
||||
iOS
|
||||
};
|
||||
}
|
||||
MSGPACK_ADD_ENUM(dht::PushType)
|
||||
|
||||
namespace http {
|
||||
class Request;
|
||||
struct ListenerSession;
|
||||
@@ -52,6 +61,13 @@ class DhtRunner;
|
||||
using RestRouter = restinio::router::express_router_t<>;
|
||||
using RequestStatus = restinio::request_handling_status_t;
|
||||
|
||||
struct ProxyServerConfig {
|
||||
in_port_t port {8000};
|
||||
std::string pushServer {};
|
||||
std::string persistStatePath {};
|
||||
dht::crypto::Identity identity {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes the REST API
|
||||
*/
|
||||
@@ -66,10 +82,9 @@ public:
|
||||
* @note if the server fails to start (if port is already used or reserved),
|
||||
* it will fails silently
|
||||
*/
|
||||
DhtProxyServer(
|
||||
dht::crypto::Identity identity,
|
||||
std::shared_ptr<DhtRunner> dht, in_port_t port = 8000, const std::string& pushServer = "",
|
||||
std::shared_ptr<dht::Logger> logger = {});
|
||||
DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
|
||||
const ProxyServerConfig& config = {},
|
||||
const std::shared_ptr<dht::Logger>& logger = {});
|
||||
|
||||
virtual ~DhtProxyServer();
|
||||
|
||||
@@ -83,27 +98,28 @@ public:
|
||||
struct ServerStats {
|
||||
/** Current number of listen operations */
|
||||
size_t listenCount {0};
|
||||
/** Current number of permanent put operations */
|
||||
/** Current number of permanent put operations (hash used) */
|
||||
size_t putCount {0};
|
||||
/** Current number of permanent put values */
|
||||
size_t totalPermanentPuts {0};
|
||||
/** Current number of push tokens with at least one listen operation */
|
||||
size_t pushListenersCount {0};
|
||||
/** Average requests per second */
|
||||
double requestRate {0};
|
||||
/** Node Info **/
|
||||
NodeInfo nodeInfo {};
|
||||
std::shared_ptr<NodeInfo> nodeInfo {};
|
||||
|
||||
std::string toString() const {
|
||||
std::ostringstream ss;
|
||||
ss << "Listens: " << listenCount << " Puts: " << putCount << " PushListeners: " << pushListenersCount << std::endl;
|
||||
ss << "Requests: " << requestRate << " per second." << std::endl;
|
||||
auto& ni = nodeInfo;
|
||||
auto& ipv4 = ni.ipv4;
|
||||
if (ipv4.table_depth > 1) {
|
||||
ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
|
||||
}
|
||||
auto& ipv6 = ni.ipv6;
|
||||
if (ipv6.table_depth > 1) {
|
||||
ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
|
||||
if (nodeInfo) {
|
||||
auto& ipv4 = nodeInfo->ipv4;
|
||||
if (ipv4.table_depth > 1)
|
||||
ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
|
||||
auto& ipv6 = nodeInfo->ipv6;
|
||||
if (ipv6.table_depth > 1)
|
||||
ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
@@ -115,16 +131,18 @@ public:
|
||||
Json::Value result;
|
||||
result["listenCount"] = static_cast<Json::UInt64>(listenCount);
|
||||
result["putCount"] = static_cast<Json::UInt64>(putCount);
|
||||
result["totalPermanentPuts"] = static_cast<Json::UInt64>(totalPermanentPuts);
|
||||
result["pushListenersCount"] = static_cast<Json::UInt64>(pushListenersCount);
|
||||
result["requestRate"] = requestRate;
|
||||
result["nodeInfo"] = nodeInfo.toJson();
|
||||
if (nodeInfo)
|
||||
result["nodeInfo"] = nodeInfo->toJson();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
ServerStats stats() const { return stats_; }
|
||||
std::shared_ptr<ServerStats> stats() const { return stats_; }
|
||||
|
||||
void updateStats() const;
|
||||
std::shared_ptr<ServerStats> updateStats(std::shared_ptr<NodeInfo> info) const;
|
||||
|
||||
std::shared_ptr<DhtRunner> getNode() const { return dht_; }
|
||||
|
||||
@@ -134,7 +152,8 @@ private:
|
||||
struct RestRouterTraits;
|
||||
|
||||
template <typename HttpResponse>
|
||||
HttpResponse initHttpResponse(HttpResponse response) const;
|
||||
static HttpResponse initHttpResponse(HttpResponse response);
|
||||
static restinio::request_handling_status_t serverError(restinio::request_t& request);
|
||||
|
||||
template< typename ServerSettings >
|
||||
void addServerSettings(ServerSettings& serverSettings,
|
||||
@@ -281,17 +300,17 @@ private:
|
||||
* @param key of the device
|
||||
* @param json, the content to send
|
||||
*/
|
||||
void sendPushNotification(const std::string& key, Json::Value&& json, bool isAndroid);
|
||||
void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority);
|
||||
|
||||
/**
|
||||
* Send push notification with an expire timeout.
|
||||
* @param ec
|
||||
* @param pushToken
|
||||
* @param json
|
||||
* @param isAndroid
|
||||
* @param type
|
||||
*/
|
||||
void handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
|
||||
Json::Value json, const bool isAndroid);
|
||||
std::function<Json::Value()> json, PushType type);
|
||||
|
||||
/**
|
||||
* Remove a push listener between a client and a hash
|
||||
@@ -306,13 +325,24 @@ private:
|
||||
#endif //OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
void handlePrintStats(const asio::error_code &ec);
|
||||
void updateStats();
|
||||
|
||||
template <typename Os>
|
||||
void saveState(Os& stream);
|
||||
|
||||
template <typename Is>
|
||||
void loadState(Is& is, size_t size);
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
|
||||
std::shared_ptr<asio::io_context> ioContext_;
|
||||
std::shared_ptr<DhtRunner> dht_;
|
||||
Json::StreamWriterBuilder jsonBuilder_;
|
||||
Json::CharReaderBuilder jsonReaderBuilder_;
|
||||
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
|
||||
|
||||
std::string persistPath_;
|
||||
|
||||
// http server
|
||||
std::thread serverThread_;
|
||||
@@ -321,15 +351,14 @@ private:
|
||||
|
||||
// http client
|
||||
std::pair<std::string, std::string> pushHostPort_;
|
||||
|
||||
|
||||
mutable std::mutex requestLock_;
|
||||
std::map<unsigned int /*id*/, std::shared_ptr<http::Request>> requests_;
|
||||
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
|
||||
mutable std::mutex statsMutex_;
|
||||
mutable ServerStats stats_;
|
||||
mutable NodeInfo nodeInfo_ {};
|
||||
std::shared_ptr<ServerStats> stats_;
|
||||
std::shared_ptr<NodeInfo> nodeInfo_ {};
|
||||
std::unique_ptr<asio::steady_timer> printStatsTimer_;
|
||||
|
||||
// Thread-safe access to listeners map.
|
||||
@@ -339,15 +368,45 @@ private:
|
||||
// Connection Listener observing conn state changes.
|
||||
std::shared_ptr<ConnectionListener> connListener_;
|
||||
|
||||
struct PushSessionContext {
|
||||
std::mutex lock;
|
||||
std::string sessionId;
|
||||
PushSessionContext(const std::string& id) : sessionId(id) {}
|
||||
};
|
||||
struct PermanentPut {
|
||||
time_point expiration;
|
||||
std::string pushToken;
|
||||
std::string clientId;
|
||||
std::shared_ptr<PushSessionContext> sessionCtx;
|
||||
std::unique_ptr<asio::steady_timer> expireTimer;
|
||||
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
|
||||
Sp<Value> value;
|
||||
PushType type;
|
||||
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& p) const
|
||||
{
|
||||
p.pack_map(2 + (sessionCtx ? 1 : 0) + (clientId.empty() ? 0 : 1) + (type == PushType::None ? 0 : 2));
|
||||
p.pack("value"); p.pack(value);
|
||||
p.pack("exp"); p.pack(to_time_t(expiration));
|
||||
if (not clientId.empty()) {
|
||||
p.pack("cid"); p.pack(clientId);
|
||||
}
|
||||
if (sessionCtx) {
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
p.pack("sid"); p.pack(sessionCtx->sessionId);
|
||||
}
|
||||
if (type != PushType::None) {
|
||||
p.pack("t"); p.pack(type);
|
||||
p.pack("token"); p.pack(pushToken);
|
||||
}
|
||||
}
|
||||
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
};
|
||||
struct SearchPuts {
|
||||
std::map<dht::Value::Id, PermanentPut> puts;
|
||||
MSGPACK_DEFINE_ARRAY(puts)
|
||||
};
|
||||
std::mutex lockSearchPuts_;
|
||||
std::map<InfoHash, SearchPuts> puts_;
|
||||
@@ -359,15 +418,33 @@ private:
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
struct Listener {
|
||||
time_point expiration;
|
||||
std::string clientId;
|
||||
std::shared_ptr<PushSessionContext> sessionCtx;
|
||||
std::future<size_t> internalToken;
|
||||
std::unique_ptr<asio::steady_timer> expireTimer;
|
||||
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
|
||||
PushType type;
|
||||
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& p) const
|
||||
{
|
||||
p.pack_map(sessionCtx ? 4 : 3);
|
||||
p.pack("cid"); p.pack(clientId);
|
||||
p.pack("exp"); p.pack(to_time_t(expiration));
|
||||
if (sessionCtx) {
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
p.pack("sid"); p.pack(sessionCtx->sessionId);
|
||||
}
|
||||
p.pack("t"); p.pack(type);
|
||||
}
|
||||
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
};
|
||||
struct PushListener {
|
||||
std::map<InfoHash, std::vector<Listener>> listeners;
|
||||
MSGPACK_DEFINE_ARRAY(listeners)
|
||||
};
|
||||
std::mutex lockPushListeners_;
|
||||
std::map<std::string, PushListener> pushListeners_;
|
||||
proxy::ListenToken tokenPushNotif_ {0};
|
||||
#endif //OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
+34
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
bool peer_publish {false};
|
||||
std::shared_ptr<dht::crypto::Certificate> server_ca;
|
||||
dht::crypto::Identity client_identity;
|
||||
SockAddr bind4 {}, bind6 {};
|
||||
};
|
||||
|
||||
struct Context {
|
||||
@@ -73,6 +74,7 @@ public:
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery {};
|
||||
StatusCallback statusChangedCallback {};
|
||||
CertificateStoreQuery certificateStore {};
|
||||
IdentityAnnouncedCb identityAnnouncedCb {};
|
||||
Context() {}
|
||||
};
|
||||
|
||||
@@ -97,7 +99,7 @@ public:
|
||||
template <class T>
|
||||
void get(InfoHash hash, std::function<bool(std::vector<T>&&)> cb, DoneCallbackSimple dcb={})
|
||||
{
|
||||
get(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
get(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
return cb(unpackVector<T>(vals));
|
||||
},
|
||||
dcb,
|
||||
@@ -106,7 +108,7 @@ public:
|
||||
template <class T>
|
||||
void get(InfoHash hash, std::function<bool(T&&)> cb, DoneCallbackSimple dcb={})
|
||||
{
|
||||
get(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
get(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
for (const auto& v : vals) {
|
||||
try {
|
||||
if (not cb(Value::unpack<T>(*v)))
|
||||
@@ -155,7 +157,7 @@ public:
|
||||
std::future<size_t> listen(InfoHash key, ValueCallback vcb, Value::Filter f = {}, Where w = {});
|
||||
|
||||
std::future<size_t> listen(InfoHash key, GetCallback cb, Value::Filter f={}, Where w={}) {
|
||||
return listen(key, [cb](const std::vector<Sp<Value>>& vals, bool expired){
|
||||
return listen(key, [cb=std::move(cb)](const std::vector<Sp<Value>>& vals, bool expired){
|
||||
if (not expired)
|
||||
return cb(vals);
|
||||
return true;
|
||||
@@ -169,7 +171,7 @@ public:
|
||||
template <class T>
|
||||
std::future<size_t> listen(InfoHash hash, std::function<bool(std::vector<T>&&)> cb)
|
||||
{
|
||||
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
return listen(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
return cb(unpackVector<T>(vals));
|
||||
},
|
||||
getFilterSet<T>());
|
||||
@@ -177,7 +179,7 @@ public:
|
||||
template <class T>
|
||||
std::future<size_t> listen(InfoHash hash, std::function<bool(std::vector<T>&&, bool)> cb)
|
||||
{
|
||||
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
|
||||
return listen(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
|
||||
return cb(unpackVector<T>(vals), expired);
|
||||
},
|
||||
getFilterSet<T>());
|
||||
@@ -186,7 +188,7 @@ public:
|
||||
template <typename T>
|
||||
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&)> cb, Value::Filter f = {}, Where w = {})
|
||||
{
|
||||
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
return listen(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
|
||||
for (const auto& v : vals) {
|
||||
try {
|
||||
if (not cb(Value::unpack<T>(*v)))
|
||||
@@ -202,7 +204,7 @@ public:
|
||||
template <typename T>
|
||||
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&, bool)> cb, Value::Filter f = {}, Where w = {})
|
||||
{
|
||||
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
|
||||
return listen(hash, [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
|
||||
for (const auto& v : vals) {
|
||||
try {
|
||||
if (not cb(Value::unpack<T>(*v), expired))
|
||||
@@ -255,6 +257,17 @@ public:
|
||||
}
|
||||
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert known nodes to the routing table, without necessarly ping them.
|
||||
* Usefull to restart a node and get things running fast without putting load on the network.
|
||||
@@ -301,6 +314,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;
|
||||
|
||||
/**
|
||||
* Get the ID of the DHT node.
|
||||
@@ -327,7 +341,10 @@ public:
|
||||
|
||||
std::vector<ValuesExport> exportValues() const;
|
||||
|
||||
void setLogger(const Logger& logger = {});
|
||||
void setLogger(const Sp<Logger>& logger = {});
|
||||
void setLogger(const Logger& logger) {
|
||||
setLogger(std::make_shared<Logger>(logger));
|
||||
}
|
||||
void setLoggers(LogMethod err = {}, LogMethod warn = {}, LogMethod debug = {});
|
||||
|
||||
/**
|
||||
@@ -346,6 +363,7 @@ public:
|
||||
NodeStats getNodesStats(sa_family_t af) const;
|
||||
unsigned getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const;
|
||||
NodeInfo getNodeInfo() const;
|
||||
void getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)>);
|
||||
|
||||
std::vector<unsigned> getNodeMessageStats(bool in = false) const;
|
||||
std::string getStorageLog() const;
|
||||
@@ -355,6 +373,7 @@ public:
|
||||
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;
|
||||
std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC);
|
||||
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC);
|
||||
void getPublicAddress(std::function<void(std::vector<SockAddr>&&)>, sa_family_t af = AF_UNSPEC);
|
||||
|
||||
// securedht methods
|
||||
|
||||
@@ -375,22 +394,12 @@ public:
|
||||
config.threaded = threaded;
|
||||
run(port, config);
|
||||
}
|
||||
void run(in_port_t port, const Config& config, Context&& context = {});
|
||||
|
||||
/**
|
||||
* @param local4: Local IPv4 address and port to bind. Can be null.
|
||||
* @param local6: Local IPv6 address and port to bind. Can be null.
|
||||
* You should allways bind to a global IPv6 address.
|
||||
* @param identity: RSA key pair to use for cryptographic operations.
|
||||
* @param threaded: If false, loop() must be called periodically. Otherwise a thread is launched.
|
||||
* @param cb: Optional callback to receive general state information.
|
||||
*/
|
||||
void run(const SockAddr& local4, const SockAddr& local6, const Config& config, Context&& context = {});
|
||||
void run(in_port_t port, Config& config, Context&& context = {});
|
||||
|
||||
/**
|
||||
* Same as @run(sockaddr_in, sockaddr_in6, Identity, bool, StatusCallback), but with string IP addresses and service (port).
|
||||
*/
|
||||
void run(const char* ip4, const char* ip6, const char* service, const Config& config, Context&& context = {});
|
||||
void run(const char* ip4, const char* ip6, const char* service, Config& config, Context&& context = {});
|
||||
|
||||
void run(const Config& config, Context&& context);
|
||||
|
||||
@@ -411,7 +420,7 @@ public:
|
||||
/**
|
||||
* Gracefuly disconnect from network.
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb = {});
|
||||
void shutdown(ShutdownCallback cb = {}, bool stop = false);
|
||||
|
||||
/**
|
||||
* Quit and wait for all threads to terminate.
|
||||
@@ -447,22 +456,12 @@ public:
|
||||
void forwardAllMessages(bool forward);
|
||||
|
||||
private:
|
||||
static constexpr std::chrono::seconds BOOTSTRAP_PERIOD {10};
|
||||
|
||||
enum class State {
|
||||
Idle,
|
||||
Running,
|
||||
Stopping
|
||||
};
|
||||
|
||||
/**
|
||||
* Will try to resolve the list of hostnames `bootstrap_nodes` on seperate
|
||||
* thread and then queue ping requests. This list should contain reliable
|
||||
* nodes so that the DHT node can recover quickly from losing connection
|
||||
* with the network.
|
||||
*/
|
||||
void tryBootstrapContinuously();
|
||||
|
||||
time_point loop_();
|
||||
|
||||
NodeStatus getStatus() const {
|
||||
@@ -485,6 +484,7 @@ private:
|
||||
|
||||
/** Current configuration */
|
||||
Config config_;
|
||||
IdentityAnnouncedCb identityAnnouncedCb_;
|
||||
|
||||
/**
|
||||
* reset dht clients
|
||||
@@ -506,16 +506,8 @@ private:
|
||||
std::thread dht_thread {};
|
||||
std::condition_variable cv {};
|
||||
std::mutex sock_mtx {};
|
||||
std::queue<std::unique_ptr<net::ReceivedPacket>> rcv {};
|
||||
|
||||
/** true if currently actively boostraping */
|
||||
std::atomic_bool bootstraping {false};
|
||||
/* bootstrap nodes given as (host, service) pairs */
|
||||
std::vector<std::pair<std::string,std::string>> bootstrap_nodes_all {};
|
||||
std::vector<std::pair<std::string,std::string>> bootstrap_nodes {};
|
||||
std::thread bootstrap_thread {};
|
||||
std::mutex bootstrap_mtx {};
|
||||
std::condition_variable bootstrap_cv {};
|
||||
net::PacketList rcv {};
|
||||
decltype(rcv) rcv_free {};
|
||||
|
||||
std::queue<std::function<void(SecureDht&)>> pending_ops_prio {};
|
||||
std::queue<std::function<void(SecureDht&)>> pending_ops {};
|
||||
|
||||
+42
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
@@ -71,15 +72,17 @@ using socket_t = asio::ip::tcp::socket;
|
||||
class OPENDHT_PUBLIC Url
|
||||
{
|
||||
public:
|
||||
Url(){};
|
||||
Url() = default;
|
||||
Url(const std::string& url);
|
||||
std::string url;
|
||||
std::string protocol {"http"};
|
||||
std::string host;
|
||||
std::string service {"80"};
|
||||
std::string target {"/"};
|
||||
std::string service;
|
||||
std::string target;
|
||||
std::string query;
|
||||
std::string fragment;
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC Connection : public std::enable_shared_from_this<Connection>
|
||||
@@ -93,8 +96,9 @@ public:
|
||||
inline unsigned int id() const { return id_; };
|
||||
bool is_open() const;
|
||||
bool is_ssl() const;
|
||||
void checkOcsp(bool check = true) { checkOcsp_ = check; }
|
||||
|
||||
void set_ssl_verification(const asio::ip::tcp::endpoint& endpoint, const asio::ssl::verify_mode verify_mode);
|
||||
void set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode);
|
||||
|
||||
asio::streambuf& input();
|
||||
std::istream& data() { return istream_; }
|
||||
@@ -122,6 +126,8 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
unsigned int id_;
|
||||
static std::atomic_uint ids_;
|
||||
|
||||
@@ -138,6 +144,7 @@ private:
|
||||
|
||||
std::unique_ptr<asio::steady_timer> timeout_timer_;
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
bool checkOcsp_ {false};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -185,7 +192,7 @@ public:
|
||||
private:
|
||||
void resolve(const std::string& host, const std::string& service);
|
||||
|
||||
std::mutex mutex_;
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
Url url_;
|
||||
asio::error_code ec_;
|
||||
@@ -199,12 +206,15 @@ private:
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
};
|
||||
|
||||
class Request;
|
||||
|
||||
struct Response
|
||||
{
|
||||
unsigned int status_code {0};
|
||||
unsigned status_code {0};
|
||||
std::map<std::string, std::string> headers;
|
||||
std::string body;
|
||||
bool aborted {false};
|
||||
std::weak_ptr<Request> request;
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC Request : public std::enable_shared_from_this<Request>
|
||||
@@ -217,15 +227,18 @@ public:
|
||||
RECEIVING,
|
||||
DONE
|
||||
};
|
||||
using OnStatusCb = std::function<void(unsigned int status_code)>;
|
||||
using OnStatusCb = std::function<void(unsigned status_code)>;
|
||||
using OnDataCb = std::function<void(const char* at, size_t length)>;
|
||||
using OnStateChangeCb = std::function<void(State state, const Response& response)>;
|
||||
using OnJsonCb = std::function<void(Json::Value value, unsigned int status_code)>;
|
||||
using OnJsonCb = std::function<void(Json::Value value, const Response& response)>;
|
||||
using OnDoneCb = std::function<void(const Response& response)>;
|
||||
|
||||
// resolves implicitly
|
||||
Request(asio::io_context& ctx, const std::string& url, const Json::Value& json, OnJsonCb jsoncb,
|
||||
std::shared_ptr<dht::Logger> logger = {});
|
||||
Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb,
|
||||
std::shared_ptr<dht::Logger> logger = {});
|
||||
|
||||
Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger = {});
|
||||
Request(asio::io_context& ctx, const std::string& host, const std::string& service,
|
||||
const bool ssl = false, std::shared_ptr<dht::Logger> logger = {});
|
||||
@@ -247,6 +260,12 @@ public:
|
||||
inline const Url& get_url() const {
|
||||
return resolver_->get_url();
|
||||
};
|
||||
|
||||
/** The previous request in case of redirect following */
|
||||
std::shared_ptr<Request> getPrevious() const {
|
||||
return prev_.lock();
|
||||
}
|
||||
|
||||
inline std::string& to_string() {
|
||||
return request_;
|
||||
}
|
||||
@@ -273,10 +292,14 @@ public:
|
||||
|
||||
void send();
|
||||
|
||||
/** Send and block for response */
|
||||
const Response& await();
|
||||
|
||||
/**
|
||||
* User action to cancel the Request and call the completion callbacks.
|
||||
*/
|
||||
void cancel();
|
||||
void terminate(const asio::error_code& ec);
|
||||
|
||||
private:
|
||||
using OnCompleteCb = std::function<void()>;
|
||||
@@ -289,6 +312,8 @@ private:
|
||||
OnStateChangeCb on_state_change;
|
||||
};
|
||||
|
||||
static std::string getRelativePath(const Url& origin, const std::string& path);
|
||||
|
||||
void notify_state_change(State state);
|
||||
|
||||
void build();
|
||||
@@ -301,8 +326,6 @@ private:
|
||||
|
||||
void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
|
||||
|
||||
void terminate(const asio::error_code& ec);
|
||||
|
||||
void post();
|
||||
|
||||
void handle_request(const asio::error_code& ec);
|
||||
@@ -312,6 +335,8 @@ private:
|
||||
void onBody(const char* at, size_t length);
|
||||
void onComplete();
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
|
||||
restinio::http_request_header_t header_;
|
||||
@@ -339,20 +364,14 @@ private:
|
||||
std::atomic<bool> finishing_ {false};
|
||||
std::unique_ptr<http_parser> parser_;
|
||||
std::unique_ptr<http_parser_settings> parser_s_;
|
||||
|
||||
// Next request in case of redirect following
|
||||
std::shared_ptr<Request> next_;
|
||||
std::weak_ptr<Request> prev_;
|
||||
unsigned num_redirect {0};
|
||||
bool follow_redirect {true};
|
||||
};
|
||||
|
||||
} // 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
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Nicolas Reynaud <nicolas.reynaud@savoirfairelinux.com>
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
void lookup(Key k, LookupCallback cb = {}, DoneCallbackSimple done_cb = {}, bool exact_match = true);
|
||||
void lookup(Key k, LookupCallbackSimple cb = {}, DoneCallbackSimple done_cb = {}, bool exact_match = true)
|
||||
{
|
||||
lookup(k, [=](std::vector<std::shared_ptr<Value>>& values, Prefix) { cb(values); }, done_cb, exact_match);
|
||||
lookup(k, [cb=std::move(cb)](std::vector<std::shared_ptr<Value>>& values, Prefix) { cb(values); }, done_cb, exact_match);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+52
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -54,9 +54,9 @@ namespace crypto {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an InfoHash.
|
||||
* An InfoHash is a byte array of HASH_LEN bytes.
|
||||
* InfoHashes identify nodes and values in the Dht.
|
||||
* Represents an Hash,
|
||||
* a byte array of N bytes.
|
||||
* Hashes identify nodes and values in the Dht.
|
||||
*/
|
||||
template <size_t N>
|
||||
class OPENDHT_PUBLIC Hash {
|
||||
@@ -93,6 +93,8 @@ public:
|
||||
iterator end() { return data_.end(); }
|
||||
const_iterator cend() const { return data_.cend(); }
|
||||
|
||||
static constexpr inline Hash zero() noexcept { return Hash{}; }
|
||||
|
||||
bool operator==(const Hash& h) const {
|
||||
auto a = reinterpret_cast<const uint32_t*>(data_.data());
|
||||
auto b = reinterpret_cast<const uint32_t*>(h.data_.data());
|
||||
@@ -112,6 +114,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
Hash operator^(const Hash& o) const {
|
||||
Hash result;
|
||||
for(auto i = 0u; i < N; i++) {
|
||||
result[i] = data_[i] ^ o.data_[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
auto a = reinterpret_cast<const uint32_t*>(data_.data());
|
||||
auto b = reinterpret_cast<const uint32_t*>(data_.data() + N);
|
||||
@@ -142,10 +152,6 @@ public:
|
||||
return 8 * i + j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget about the ``XOR-metric''. An id is just a path from the
|
||||
* root of the tree, so bits are numbered from the start.
|
||||
*/
|
||||
static inline int cmp(const Hash& id1, const Hash& id2) {
|
||||
return std::memcmp(id1.data_.data(), id2.data_.data(), N);
|
||||
}
|
||||
@@ -179,16 +185,12 @@ public:
|
||||
int
|
||||
xorCmp(const Hash& id1, const Hash& id2) const
|
||||
{
|
||||
for(unsigned i = 0; i < N; i++) {
|
||||
uint8_t xor1, xor2;
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
if(id1.data_[i] == id2.data_[i])
|
||||
continue;
|
||||
xor1 = id1.data_[i] ^ data_[i];
|
||||
xor2 = id2.data_[i] ^ data_[i];
|
||||
if(xor1 < xor2)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
uint8_t xor1 = id1.data_[i] ^ data_[i];
|
||||
uint8_t xor2 = id2.data_[i] ^ data_[i];
|
||||
return (xor1 < xor2) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -237,6 +239,9 @@ public:
|
||||
|
||||
static Hash getRandom();
|
||||
|
||||
template <typename Rd>
|
||||
static Hash getRandom(Rd&);
|
||||
|
||||
template <size_t M>
|
||||
OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Hash<M>& h);
|
||||
|
||||
@@ -324,7 +329,20 @@ Hash<N>::getRandom()
|
||||
return h;
|
||||
}
|
||||
|
||||
struct HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
template <size_t N>
|
||||
template <typename Rd>
|
||||
Hash<N>
|
||||
Hash<N>::getRandom(Rd& rdev)
|
||||
{
|
||||
Hash h;
|
||||
std::uniform_int_distribution<uint32_t> rand_int;
|
||||
auto a = reinterpret_cast<uint32_t*>(h.data());
|
||||
auto b = reinterpret_cast<uint32_t*>(h.data() + h.size());
|
||||
std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
|
||||
return h;
|
||||
}
|
||||
|
||||
struct alignas(std::max_align_t) HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
HexMap() {
|
||||
for (size_t i=0; i<size(); i++) {
|
||||
auto& e = (*this)[i];
|
||||
@@ -338,11 +356,27 @@ private:
|
||||
|
||||
OPENDHT_PUBLIC extern const HexMap hex_map;
|
||||
|
||||
inline std::string
|
||||
toHex(const uint8_t* data, size_t size) {
|
||||
std::string ret(size * 2, '\0');
|
||||
for (size_t i=0; i<size; i++) {
|
||||
auto b = ret.data()+i*2;
|
||||
const auto& m = hex_map[data[i]];
|
||||
*((uint16_t*)b) = *((uint16_t*)&m);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
toHex(const std::vector<uint8_t>& data) {
|
||||
return toHex(data.data(), data.size());
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
const char*
|
||||
Hash<N>::to_c_str() const
|
||||
{
|
||||
thread_local std::array<char, N*2+1> buf;
|
||||
alignas(std::max_align_t) 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]];
|
||||
@@ -358,8 +392,6 @@ Hash<N>::toString() const
|
||||
return std::string(to_c_str(), N*2);
|
||||
}
|
||||
|
||||
const InfoHash zeroes {};
|
||||
|
||||
struct OPENDHT_PUBLIC NodeExport {
|
||||
InfoHash id;
|
||||
sockaddr_storage ss;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -64,7 +64,7 @@ struct LogMethod {
|
||||
func(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
void log(char const* format, va_list args) const {
|
||||
inline void log(char const* format, va_list args) const {
|
||||
func(format, args);
|
||||
}
|
||||
explicit operator bool() const {
|
||||
@@ -82,13 +82,13 @@ private:
|
||||
};
|
||||
|
||||
struct Logger {
|
||||
LogMethod DBG = {};
|
||||
LogMethod WARN = {};
|
||||
LogMethod ERR = {};
|
||||
LogMethod WARN = {};
|
||||
LogMethod DBG = {};
|
||||
|
||||
Logger() = default;
|
||||
Logger(LogMethod&& err, LogMethod&& warn, LogMethod&& dbg)
|
||||
: DBG(std::move(dbg)), WARN(std::move(warn)), ERR(std::move(err)) {}
|
||||
: ERR(std::move(err)), WARN(std::move(warn)), DBG(std::move(dbg)) {}
|
||||
void setFilter(const InfoHash& f) {
|
||||
filter_ = f;
|
||||
filterEnable_ = static_cast<bool>(filter_);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -180,7 +180,8 @@ private:
|
||||
const InfoHash&,
|
||||
const Blob&,
|
||||
Tid,
|
||||
const Query&)> onListen {};
|
||||
const Query&,
|
||||
int)> onListen {};
|
||||
/**
|
||||
* Called on announce request.
|
||||
*
|
||||
@@ -210,14 +211,15 @@ private:
|
||||
|
||||
public:
|
||||
using RequestCb = std::function<void(const Request&, RequestAnswer&&)>;
|
||||
using RequestErrorCb = std::function<bool(const Request&, DhtProtocolException&&)>;
|
||||
using RequestExpiredCb = std::function<void(const Request&, bool)>;
|
||||
|
||||
NetworkEngine(Logger& log, Scheduler& scheduler, std::unique_ptr<DatagramSocket>&& sock);
|
||||
NetworkEngine(
|
||||
InfoHash& myid,
|
||||
NetworkConfig config,
|
||||
std::unique_ptr<DatagramSocket>&& sock,
|
||||
Logger& log,
|
||||
const Sp<Logger>& log,
|
||||
std::mt19937_64& rd,
|
||||
Scheduler& scheduler,
|
||||
decltype(NetworkEngine::onError)&& onError,
|
||||
decltype(NetworkEngine::onNewNode)&& onNewNode,
|
||||
@@ -236,9 +238,10 @@ public:
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Sends values (with closest nodes) to a listenner.
|
||||
* Sends values (with closest nodes) to a listener.
|
||||
*
|
||||
* @param sa The address of the listenner.
|
||||
* @deprecated
|
||||
* @param sa The address of the listener.
|
||||
* @param sslen The length of the sockaddr structure.
|
||||
* @param socket_id The tid to use to write to the request socket.
|
||||
* @param hash The hash key of the value.
|
||||
@@ -247,13 +250,14 @@ public:
|
||||
* @param nodes The ipv4 closest nodes.
|
||||
* @param nodes6 The ipv6 closest nodes.
|
||||
* @param values The values to send.
|
||||
* @param version If version = 1, a request will be used to answer to the listener
|
||||
*/
|
||||
void tellListener(Sp<Node> n, Tid socket_id, const InfoHash& hash, want_t want, const Blob& ntoken,
|
||||
std::vector<Sp<Node>>&& nodes, std::vector<Sp<Node>>&& nodes6,
|
||||
std::vector<Sp<Value>>&& values, const Query& q);
|
||||
std::vector<Sp<Value>>&& values, const Query& q, int version);
|
||||
|
||||
void tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values);
|
||||
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values);
|
||||
void tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
|
||||
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
|
||||
|
||||
bool isRunning(sa_family_t af) const;
|
||||
inline want_t want () const { return dht_socket->hasIPv4() and dht_socket->hasIPv6() ? (WANT4 | WANT6) : -1; }
|
||||
@@ -274,7 +278,8 @@ public:
|
||||
* @return the request with information concerning its success.
|
||||
*/
|
||||
Sp<Request>
|
||||
sendPing(Sp<Node> n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
|
||||
sendPing(Sp<Node> n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
|
||||
|
||||
/**
|
||||
* Send a "ping" request to a given node.
|
||||
*
|
||||
@@ -286,11 +291,12 @@ public:
|
||||
* @return the request with information concerning its success.
|
||||
*/
|
||||
Sp<Request>
|
||||
sendPing(SockAddr&& sa, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
|
||||
return sendPing(std::make_shared<Node>(zeroes, std::move(sa)),
|
||||
std::forward<RequestCb>(on_done),
|
||||
std::forward<RequestExpiredCb>(on_expired));
|
||||
}
|
||||
sendPing(SockAddr&& sa, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
|
||||
return sendPing(std::make_shared<Node>(InfoHash::zero(), std::move(sa), rd),
|
||||
std::forward<RequestCb>(on_done),
|
||||
std::forward<RequestExpiredCb>(on_expired));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a "find node" request to a given node.
|
||||
*
|
||||
@@ -355,10 +361,9 @@ public:
|
||||
const InfoHash& hash,
|
||||
const Query& query,
|
||||
const Blob& token,
|
||||
Sp<Request> previous,
|
||||
Tid socketId,
|
||||
RequestCb&& on_done,
|
||||
RequestExpiredCb&& on_expired,
|
||||
SocketCb&& socket_cb);
|
||||
RequestExpiredCb&& on_expired);
|
||||
/**
|
||||
* Send a "announce" request to a given node.
|
||||
*
|
||||
@@ -397,7 +402,26 @@ public:
|
||||
const Value::Id& vid,
|
||||
const Blob& token,
|
||||
RequestCb&& on_done,
|
||||
RequestErrorCb&& on_error,
|
||||
RequestExpiredCb&& on_expired);
|
||||
/**
|
||||
* Send a "update" request to a given node. Used for Listen operations
|
||||
*
|
||||
* @param n The node.
|
||||
* @param hash The target hash.
|
||||
* @param values The values.
|
||||
* @param created Time id.
|
||||
* @param token A security token.
|
||||
* @param sid The socket id.
|
||||
*
|
||||
* @return the request with information concerning its success.
|
||||
*/
|
||||
Sp<Request> sendUpdateValues(Sp<Node> n,
|
||||
const InfoHash& infohash,
|
||||
const std::vector<Sp<Value>>& values,
|
||||
time_point created,
|
||||
const Blob& token,
|
||||
const size_t& sid);
|
||||
|
||||
/**
|
||||
* Parses a message and calls appropriate callbacks.
|
||||
@@ -410,8 +434,8 @@ public:
|
||||
*/
|
||||
void processMessage(const uint8_t *buf, size_t buflen, SockAddr addr);
|
||||
|
||||
Sp<Node> insertNode(const InfoHash& myid, const SockAddr& addr) {
|
||||
auto n = cache.getNode(myid, addr, scheduler.time(), 0);
|
||||
Sp<Node> insertNode(const InfoHash& id, const SockAddr& addr) {
|
||||
auto n = cache.getNode(id, addr, scheduler.time(), 0);
|
||||
onNewNode(n, 0);
|
||||
return n;
|
||||
}
|
||||
@@ -429,6 +453,21 @@ public:
|
||||
return cache.getCachedNodes(id, sa_f, count);
|
||||
}
|
||||
|
||||
size_t getNodeCacheSize() const {
|
||||
return cache.size();
|
||||
}
|
||||
size_t getNodeCacheSize(sa_family_t af) const {
|
||||
return cache.size(af);
|
||||
}
|
||||
|
||||
size_t getRateLimiterSize() const {
|
||||
return address_rate_limiter.size();
|
||||
}
|
||||
|
||||
size_t getPartialCount() const {
|
||||
return partial_messages.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct PartialMessage;
|
||||
@@ -472,19 +511,20 @@ private:
|
||||
void sendRequest(const Sp<Request>& request);
|
||||
|
||||
struct MessageStats {
|
||||
unsigned ping {0};
|
||||
unsigned find {0};
|
||||
unsigned get {0};
|
||||
unsigned put {0};
|
||||
unsigned listen {0};
|
||||
unsigned refresh {0};
|
||||
unsigned ping {0};
|
||||
unsigned find {0};
|
||||
unsigned get {0};
|
||||
unsigned put {0};
|
||||
unsigned listen {0};
|
||||
unsigned refresh {0};
|
||||
unsigned updateValue {0};
|
||||
};
|
||||
|
||||
|
||||
// basic wrapper for socket sendto function
|
||||
int send(const SockAddr& addr, const char *buf, size_t len, bool confirmed = false);
|
||||
|
||||
void sendValueParts(const TransId& tid, const std::vector<Blob>& svals, const SockAddr& addr);
|
||||
void sendValueParts(Tid tid, const std::vector<Blob>& svals, const SockAddr& addr);
|
||||
std::vector<Blob> packValueHeader(msgpack::sbuffer&, const std::vector<Sp<Value>>&);
|
||||
void maintainRxBuffer(Tid tid);
|
||||
|
||||
@@ -525,9 +565,10 @@ private:
|
||||
const InfoHash& myid;
|
||||
const NetworkConfig config {};
|
||||
const std::unique_ptr<DatagramSocket> dht_socket;
|
||||
const Logger& DHT_LOG;
|
||||
Sp<Logger> logger_;
|
||||
std::mt19937_64& rd;
|
||||
|
||||
NodeCache cache {};
|
||||
NodeCache cache;
|
||||
|
||||
// global limiting should be triggered by at least 8 different IPs
|
||||
using IpLimiter = RateLimiter;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -36,11 +36,14 @@
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <list>
|
||||
|
||||
namespace dht {
|
||||
namespace net {
|
||||
|
||||
static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
|
||||
static const constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 16;
|
||||
static const constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(650);
|
||||
|
||||
int bindSocket(const SockAddr& addr, SockAddr& bound);
|
||||
|
||||
@@ -54,10 +57,14 @@ struct ReceivedPacket {
|
||||
SockAddr from;
|
||||
time_point received;
|
||||
};
|
||||
using PacketList = std::list<ReceivedPacket>;
|
||||
|
||||
class OPENDHT_PUBLIC DatagramSocket {
|
||||
public:
|
||||
using OnReceive = std::function<void(std::unique_ptr<ReceivedPacket>&& packet)>;
|
||||
/** A function that takes a list of new received packets and
|
||||
* optionally returns consumed packets for recycling.
|
||||
**/
|
||||
using OnReceive = std::function<PacketList(PacketList&& packets)>;
|
||||
virtual ~DatagramSocket() {};
|
||||
|
||||
virtual int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) = 0;
|
||||
@@ -81,24 +88,45 @@ public:
|
||||
|
||||
virtual const SockAddr& getBoundRef(sa_family_t family = AF_UNSPEC) const = 0;
|
||||
|
||||
/** Virtual resolver mothod allows to implement custom resolver */
|
||||
virtual std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {}) {
|
||||
return SockAddr::resolve(host, service);
|
||||
}
|
||||
|
||||
virtual void stop() = 0;
|
||||
protected:
|
||||
|
||||
inline void onReceived(std::unique_ptr<ReceivedPacket>&& packet) {
|
||||
PacketList getNewPacket() {
|
||||
PacketList pkts;
|
||||
if (toRecycle_.empty()) {
|
||||
pkts.emplace_back();
|
||||
} else {
|
||||
auto begIt = toRecycle_.begin();
|
||||
auto begItNext = std::next(begIt);
|
||||
pkts.splice(pkts.end(), toRecycle_, begIt, begItNext);
|
||||
}
|
||||
return pkts;
|
||||
}
|
||||
|
||||
inline void onReceived(PacketList&& packets) {
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
if (rx_callback)
|
||||
rx_callback(std::move(packet));
|
||||
if (rx_callback) {
|
||||
auto r = rx_callback(std::move(packets));
|
||||
if (not r.empty() and toRecycle_.size() < RX_QUEUE_MAX_SIZE)
|
||||
toRecycle_.splice(toRecycle_.end(), std::move(r));
|
||||
}
|
||||
}
|
||||
protected:
|
||||
mutable std::mutex lock;
|
||||
private:
|
||||
OnReceive rx_callback;
|
||||
PacketList toRecycle_;
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC UdpSocket : public DatagramSocket {
|
||||
public:
|
||||
UdpSocket(in_port_t port, const Logger& l = {});
|
||||
UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const Logger& l = {});
|
||||
UdpSocket(in_port_t port, const std::shared_ptr<Logger>& l = {});
|
||||
UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const std::shared_ptr<Logger>& l = {});
|
||||
~UdpSocket();
|
||||
|
||||
int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) override;
|
||||
@@ -118,7 +146,7 @@ public:
|
||||
|
||||
void stop() override;
|
||||
private:
|
||||
Logger logger;
|
||||
std::shared_ptr<Logger> logger;
|
||||
int s4 {-1};
|
||||
int s6 {-1};
|
||||
int stopfd {-1};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -47,10 +47,10 @@ struct Socket {
|
||||
struct Node {
|
||||
const InfoHash id;
|
||||
|
||||
Node(const InfoHash& id, const SockAddr& addr, bool client=false);
|
||||
Node(const InfoHash& id, SockAddr&& addr, bool client=false);
|
||||
Node(const InfoHash& id, const sockaddr* sa, socklen_t salen)
|
||||
: Node(id, SockAddr(sa, salen)) {}
|
||||
Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client=false);
|
||||
Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client=false);
|
||||
Node(const InfoHash& id, const sockaddr* sa, socklen_t salen, std::mt19937_64& rd)
|
||||
: Node(id, SockAddr(sa, salen), rd) {}
|
||||
|
||||
InfoHash getId() const {
|
||||
return id;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -26,6 +26,13 @@
|
||||
namespace dht {
|
||||
|
||||
struct NodeCache {
|
||||
size_t size(sa_family_t family) const {
|
||||
return cache(family).count();
|
||||
}
|
||||
size_t size() const {
|
||||
return size(AF_INET) + size(AF_INET6);
|
||||
}
|
||||
|
||||
Sp<Node> getNode(const InfoHash& id, sa_family_t family);
|
||||
Sp<Node> getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client=false);
|
||||
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) const;
|
||||
@@ -37,17 +44,19 @@ struct NodeCache {
|
||||
*/
|
||||
void clearBadNodes(sa_family_t family = 0);
|
||||
|
||||
NodeCache(std::mt19937_64& r) : rd(r) {};
|
||||
~NodeCache();
|
||||
|
||||
private:
|
||||
class NodeMap : private std::map<InfoHash, std::weak_ptr<Node>> {
|
||||
public:
|
||||
Sp<Node> getNode(const InfoHash& id);
|
||||
Sp<Node> getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client);
|
||||
Sp<Node> getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client, std::mt19937_64& rd);
|
||||
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, size_t count) const;
|
||||
void clearBadNodes();
|
||||
void setExpired();
|
||||
void cleanup();
|
||||
size_t count() const { return size(); }
|
||||
private:
|
||||
size_t cleanup_counter {0};
|
||||
};
|
||||
@@ -56,6 +65,7 @@ private:
|
||||
NodeMap& cache(sa_family_t af) { return af == AF_INET ? cache_4 : cache_6; }
|
||||
NodeMap cache_4;
|
||||
NodeMap cache_6;
|
||||
std::mt19937_64& rd;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -82,6 +82,8 @@ public:
|
||||
bool stopPublish(const std::string &type);
|
||||
bool stopPublish(sa_family_t domain, const std::string &type);
|
||||
|
||||
void connectivityChanged();
|
||||
|
||||
private:
|
||||
class DomainPeerDiscovery;
|
||||
std::unique_ptr<DomainPeerDiscovery> peerDiscovery4_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -22,8 +22,8 @@
|
||||
namespace dht {
|
||||
namespace proxy {
|
||||
|
||||
constexpr const std::chrono::seconds OP_TIMEOUT {1 * 60 * 60}; // one hour
|
||||
constexpr const std::chrono::seconds OP_MARGIN {5 * 60}; // 5 minutes
|
||||
constexpr const std::chrono::hours OP_TIMEOUT {24}; // one day
|
||||
constexpr const std::chrono::hours OP_MARGIN {2}; // two hours
|
||||
constexpr const char* const HTTP_PROTO {"http://"};
|
||||
using ListenToken = uint64_t;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+15
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace dht {
|
||||
namespace crypto {
|
||||
@@ -111,11 +113,18 @@ using random_device = std::random_device;
|
||||
template<class T = std::mt19937, std::size_t N = T::state_size>
|
||||
auto getSeededRandomEngine () -> typename std::enable_if<!!N, T>::type {
|
||||
typename T::result_type random_data[N];
|
||||
random_device source;
|
||||
std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
|
||||
std::seed_seq seeds(std::begin(random_data), std::end(random_data));
|
||||
T seededEngine (seeds);
|
||||
return seededEngine;
|
||||
for (unsigned i=0; i<256; i++) {
|
||||
try {
|
||||
random_device source;
|
||||
std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
|
||||
std::seed_seq seeds(std::begin(random_data), std::end(random_data));
|
||||
T seededEngine (seeds);
|
||||
return seededEngine;
|
||||
} catch (...) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Can't seed random engine");
|
||||
}
|
||||
|
||||
}} // dht::crypto
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -39,7 +39,7 @@ struct Bucket {
|
||||
Sp<Node> cached; /* the address of a likely candidate */
|
||||
|
||||
/** Return a random node in a bucket. */
|
||||
Sp<Node> randomNode();
|
||||
Sp<Node> randomNode(std::mt19937_64& rd);
|
||||
|
||||
void sendCachedPing(net::NetworkEngine& ne);
|
||||
void connectivityChanged() {
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
/**
|
||||
* Return a random id in the bucket's range.
|
||||
*/
|
||||
InfoHash randomId(const RoutingTable::const_iterator& bucket) const;
|
||||
InfoHash randomId(const RoutingTable::const_iterator& bucket, std::mt19937_64& rd) const;
|
||||
|
||||
unsigned depth(const RoutingTable::const_iterator& bucket) const;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -84,7 +84,6 @@ public:
|
||||
* @return The time for the next job to run.
|
||||
*/
|
||||
time_point run() {
|
||||
syncTime();
|
||||
while (not timers.empty()) {
|
||||
auto timer = timers.begin();
|
||||
/*
|
||||
@@ -114,6 +113,7 @@ public:
|
||||
*/
|
||||
inline const time_point& time() const { return now; }
|
||||
inline time_point syncTime() { return (now = clock::now()); }
|
||||
inline void syncTime(const time_point& n) { now = n; }
|
||||
|
||||
private:
|
||||
time_point now {clock::now()};
|
||||
|
||||
+36
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
@@ -45,15 +45,13 @@ public:
|
||||
return c;
|
||||
}
|
||||
|
||||
SecureDht() {}
|
||||
|
||||
/**
|
||||
* s, s6: bound socket descriptors for IPv4 and IPv6, respectively.
|
||||
* For the Dht to be initialised, at least one of them must be >= 0.
|
||||
* id: the identity to use for the crypto layer and to compute
|
||||
* our own hash on the Dht.
|
||||
*/
|
||||
SecureDht(std::unique_ptr<DhtInterface> dht, Config config);
|
||||
SecureDht(std::unique_ptr<DhtInterface> dht, Config config, IdentityAnnouncedCb iacb = {}, const std::shared_ptr<Logger>& l = {});
|
||||
|
||||
virtual ~SecureDht();
|
||||
|
||||
@@ -63,6 +61,9 @@ 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);
|
||||
|
||||
@@ -117,6 +118,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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take ownership of the value and sign it using our private key.
|
||||
@@ -128,13 +133,13 @@ public:
|
||||
Value decrypt(const Value& v);
|
||||
|
||||
void findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
|
||||
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<const crypto::PublicKey>)>& cb);
|
||||
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
|
||||
|
||||
const Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
void registerCertificate(Sp<crypto::Certificate>& cert);
|
||||
|
||||
const Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
const Sp<const crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
|
||||
/**
|
||||
* Allows to set a custom callback called by the library to find a locally-stored certificate.
|
||||
@@ -148,8 +153,8 @@ public:
|
||||
/**
|
||||
* SecureDht to Dht proxy
|
||||
*/
|
||||
void shutdown(ShutdownCallback cb) override {
|
||||
dht_->shutdown(cb);
|
||||
void shutdown(ShutdownCallback cb, bool stop = false) override {
|
||||
dht_->shutdown(cb, stop);
|
||||
}
|
||||
void dumpTables() const override {
|
||||
dht_->dumpTables();
|
||||
@@ -195,11 +200,14 @@ public:
|
||||
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override {
|
||||
return dht_->getPublicAddress(family);
|
||||
}
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, SockAddr sa) override {
|
||||
return dht_->periodic(buf, buflen, std::move(sa));
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, SockAddr sa, const time_point& now) override {
|
||||
return dht_->periodic(buf, buflen, std::move(sa), now);
|
||||
}
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) override {
|
||||
return dht_->periodic(buf, buflen, from, fromlen);
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
|
||||
return dht_->periodic(buf, buflen, from, fromlen, now);
|
||||
}
|
||||
NodeStatus updateStatus(sa_family_t af) override {
|
||||
return dht_->updateStatus(af);
|
||||
}
|
||||
NodeStatus getStatus(sa_family_t af) const override {
|
||||
return dht_->getStatus(af);
|
||||
@@ -216,6 +224,12 @@ public:
|
||||
const ValueType& getType(ValueType::Id type_id) const override {
|
||||
return dht_->getType(type_id);
|
||||
}
|
||||
void addBootstrap(const std::string& host, const std::string& service) override {
|
||||
dht_->addBootstrap(host, service);
|
||||
}
|
||||
void clearBootstrap() override {
|
||||
dht_->clearBootstrap();
|
||||
}
|
||||
void insertNode(const InfoHash& id, const SockAddr& sa) override {
|
||||
dht_->insertNode(id, sa);
|
||||
}
|
||||
@@ -316,11 +330,16 @@ public:
|
||||
dht_->setLogger(logger);
|
||||
}
|
||||
|
||||
void setLogger(const std::shared_ptr<Logger>& logger) override {
|
||||
DhtInterface::setLogger(logger);
|
||||
dht_->setLogger(logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
|
||||
*/
|
||||
void setLogFilter(const InfoHash& f) override {
|
||||
DHT_LOG.setFilter(f);
|
||||
DhtInterface::setLogFilter(f);
|
||||
dht_->setLogFilter(f);
|
||||
}
|
||||
|
||||
@@ -342,9 +361,10 @@ private:
|
||||
|
||||
// our certificate cache
|
||||
std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
|
||||
std::map<InfoHash, Sp<const crypto::PublicKey>> nodesPubKeys_ {};
|
||||
std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
|
||||
|
||||
std::atomic_bool forward_all_ {false};
|
||||
bool enableCache_ {false};
|
||||
};
|
||||
|
||||
const ValueType CERTIFICATE_TYPE = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
* Build from existing address.
|
||||
*/
|
||||
SockAddr(const sockaddr* sa, socklen_t length) {
|
||||
if (length > sizeof(sockaddr_storage))
|
||||
if (length > static_cast<socklen_t>(sizeof(sockaddr_storage)))
|
||||
throw std::runtime_error("Socket address length is too large");
|
||||
set(sa, length);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
if (len) addr.reset((sockaddr*)::calloc(len, 1));
|
||||
else addr.reset();
|
||||
}
|
||||
if (len > sizeof(sa_family_t))
|
||||
if (len)
|
||||
addr->sa_family = af;
|
||||
}
|
||||
|
||||
@@ -223,16 +223,16 @@ public:
|
||||
*/
|
||||
sockaddr* get() { return addr.get(); }
|
||||
|
||||
const sockaddr_in& getIPv4() const {
|
||||
inline const sockaddr_in& getIPv4() const {
|
||||
return *reinterpret_cast<const sockaddr_in*>(get());
|
||||
}
|
||||
const sockaddr_in6& getIPv6() const {
|
||||
inline const sockaddr_in6& getIPv6() const {
|
||||
return *reinterpret_cast<const sockaddr_in6*>(get());
|
||||
}
|
||||
sockaddr_in& getIPv4() {
|
||||
inline sockaddr_in& getIPv4() {
|
||||
return *reinterpret_cast<sockaddr_in*>(get());
|
||||
}
|
||||
sockaddr_in6& getIPv6() {
|
||||
inline sockaddr_in6& getIPv6() {
|
||||
return *reinterpret_cast<sockaddr_in6*>(get());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <future>
|
||||
#include <functional>
|
||||
|
||||
#include <ciso646> // fix windows compiler bug
|
||||
|
||||
namespace dht {
|
||||
|
||||
class OPENDHT_PUBLIC ThreadPool {
|
||||
@@ -93,4 +95,71 @@ 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_;
|
||||
};
|
||||
|
||||
}
|
||||
+35
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -77,12 +77,20 @@ public:
|
||||
// Time related definitions and utility functions
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using system_clock = std::chrono::system_clock;
|
||||
using time_point = clock::time_point;
|
||||
using duration = clock::duration;
|
||||
|
||||
time_point from_time_t(std::time_t t);
|
||||
std::time_t to_time_t(time_point t);
|
||||
|
||||
inline std::string
|
||||
to_str(double d) {
|
||||
char buf[16];
|
||||
auto ret = snprintf(buf, sizeof(buf), "%.3g", d);
|
||||
return (ret < 0) ? std::to_string(d) : std::string(buf, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts std::chrono::duration to floating-point seconds.
|
||||
*/
|
||||
@@ -97,16 +105,28 @@ static std::string
|
||||
print_duration(DT d) {
|
||||
if (d < std::chrono::seconds(0)) {
|
||||
return "-" + print_duration(-d);
|
||||
}
|
||||
if (d < std::chrono::milliseconds(1)) {
|
||||
return std::to_string(std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count()) + " us";
|
||||
} else if (d < std::chrono::milliseconds(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count()) + " us";
|
||||
} else if (d < std::chrono::seconds(1)) {
|
||||
return std::to_string(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
|
||||
} else if (d < std::chrono::minutes(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double>>(d).count()) + " s";
|
||||
} else if (d < std::chrono::hours(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<60>>>(d).count()) + " min";
|
||||
} else {
|
||||
return std::to_string(print_dt(d)) + " s";
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<3600>>>(d).count()) + " h";
|
||||
}
|
||||
}
|
||||
|
||||
template <class TimePoint>
|
||||
static std::string
|
||||
print_time_relative(TimePoint now, TimePoint d) {
|
||||
if (d == TimePoint::min()) return "never";
|
||||
if (d == now) return "now";
|
||||
return (d > now) ? std::string("in ") + print_duration(d - now)
|
||||
: print_duration(now - d) + std::string(" ago");
|
||||
}
|
||||
|
||||
template <typename Duration = duration>
|
||||
class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep> {
|
||||
using Base = std::uniform_int_distribution<typename Duration::rep>;
|
||||
@@ -133,7 +153,7 @@ using Blob = std::vector<uint8_t>;
|
||||
/**
|
||||
* Provides backward compatibility with msgpack 1.0
|
||||
*/
|
||||
OPENDHT_PUBLIC Blob unpackBlob(msgpack::object& o);
|
||||
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object& o);
|
||||
|
||||
template <typename Type>
|
||||
Blob
|
||||
@@ -153,6 +173,13 @@ unpackMsg(Blob b) {
|
||||
|
||||
msgpack::unpacked unpackMsg(Blob b);
|
||||
|
||||
msgpack::object* findMapValue(msgpack::object& map, const std::string& key);
|
||||
msgpack::object* findMapValue(const msgpack::object& map, const char* key, size_t length);
|
||||
|
||||
inline msgpack::object* findMapValue(const msgpack::object& map, const char* key) {
|
||||
return findMapValue(map, key, strlen(key));
|
||||
}
|
||||
inline msgpack::object* findMapValue(const msgpack::object& map, const std::string& key) {
|
||||
return findMapValue(map, key.c_str(), key.size());
|
||||
}
|
||||
|
||||
} // namespace dht
|
||||
+64
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -43,6 +43,19 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
static const std::string VALUE_KEY_ID("id");
|
||||
static const std::string VALUE_KEY_DAT("dat");
|
||||
static const std::string VALUE_KEY_PRIO("p");
|
||||
static const std::string VALUE_KEY_SIGNATURE("sig");
|
||||
|
||||
static const std::string VALUE_KEY_SEQ("seq");
|
||||
static const std::string VALUE_KEY_DATA("data");
|
||||
static const std::string VALUE_KEY_OWNER("owner");
|
||||
static const std::string VALUE_KEY_TYPE("type");
|
||||
static const std::string VALUE_KEY_TO("to");
|
||||
static const std::string VALUE_KEY_BODY("body");
|
||||
static const std::string VALUE_KEY_USERTYPE("utype");
|
||||
|
||||
struct Value;
|
||||
struct Query;
|
||||
|
||||
@@ -192,7 +205,7 @@ struct OPENDHT_PUBLIC Value
|
||||
}
|
||||
static Filter chainOr(Filter&& f1, Filter&& f2) {
|
||||
if (not f1 or not f2) return {};
|
||||
return [f1,f2](const Value& v) {
|
||||
return [f1=std::move(f1),f2=std::move(f2)](const Value& v) {
|
||||
return f1(v) or f2(v);
|
||||
};
|
||||
}
|
||||
@@ -218,8 +231,7 @@ struct OPENDHT_PUBLIC Value
|
||||
}
|
||||
|
||||
static Filter TypeFilter(const ValueType& t) {
|
||||
const auto tid = t.id;
|
||||
return [tid](const Value& v) {
|
||||
return [tid = t.id](const Value& v) {
|
||||
return v.type == tid;
|
||||
};
|
||||
}
|
||||
@@ -344,7 +356,7 @@ struct OPENDHT_PUBLIC Value
|
||||
void sign(const crypto::PrivateKey& key) {
|
||||
if (isEncrypted())
|
||||
throw DhtException("Can't sign encrypted data.");
|
||||
owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
|
||||
owner = key.getSharedPublicKey();
|
||||
signature = key.sign(getToSign());
|
||||
}
|
||||
|
||||
@@ -356,8 +368,8 @@ struct OPENDHT_PUBLIC Value
|
||||
return isSigned() and owner->checkSignature(getToSign(), signature);
|
||||
}
|
||||
|
||||
std::shared_ptr<const crypto::PublicKey> getOwner() const {
|
||||
return std::static_pointer_cast<const crypto::PublicKey>(owner);
|
||||
std::shared_ptr<crypto::PublicKey> getOwner() const {
|
||||
return std::static_pointer_cast<crypto::PublicKey>(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,7 +402,7 @@ struct OPENDHT_PUBLIC Value
|
||||
* Build a value from a json object
|
||||
* @param json
|
||||
*/
|
||||
Value(Json::Value& json);
|
||||
Value(const Json::Value& json);
|
||||
#endif
|
||||
|
||||
template <typename Type>
|
||||
@@ -408,7 +420,9 @@ struct OPENDHT_PUBLIC Value
|
||||
|
||||
Value(Value&& o) noexcept
|
||||
: id(o.id), owner(std::move(o.owner)), recipient(o.recipient),
|
||||
type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq), signature(std::move(o.signature)), cypher(std::move(o.cypher)) {}
|
||||
type(o.type), data(std::move(o.data)), user_type(std::move(o.user_type)), seq(o.seq)
|
||||
, signature(std::move(o.signature)), cypher(std::move(o.cypher))
|
||||
, priority(o.priority) {}
|
||||
|
||||
template <typename Type>
|
||||
Value(const Type& vs)
|
||||
@@ -421,10 +435,20 @@ struct OPENDHT_PUBLIC Value
|
||||
msgpack_unpack(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if value contents are equals (not considering the value ID)
|
||||
*/
|
||||
inline bool contentEquals(const Value& o) {
|
||||
return isEncrypted() ? cypher == o.cypher :
|
||||
((owner == o.owner || (owner and o.owner and *owner == *o.owner))
|
||||
&& type == o.type
|
||||
&& data == o.data
|
||||
&& user_type == o.user_type
|
||||
&& signature == o.signature);
|
||||
}
|
||||
|
||||
inline bool operator== (const Value& o) {
|
||||
return id == o.id &&
|
||||
(isEncrypted() ? cypher == o.cypher :
|
||||
((owner == o.owner || *owner == *o.owner) && type == o.type && data == o.data && user_type == o.user_type && signature == o.signature));
|
||||
return id == o.id and contentEquals(o);
|
||||
}
|
||||
|
||||
void setRecipient(const InfoHash& r) {
|
||||
@@ -485,17 +509,17 @@ struct OPENDHT_PUBLIC Value
|
||||
bool has_owner = owner && *owner;
|
||||
pk.pack_map((user_type.empty()?0:1) + (has_owner?(recipient ? 5 : 4):2));
|
||||
if (has_owner) { // isSigned
|
||||
pk.pack(std::string("seq")); pk.pack(seq);
|
||||
pk.pack(std::string("owner")); owner->msgpack_pack(pk);
|
||||
pk.pack(VALUE_KEY_SEQ); pk.pack(seq);
|
||||
pk.pack(VALUE_KEY_OWNER); owner->msgpack_pack(pk);
|
||||
if (recipient) {
|
||||
pk.pack(std::string("to")); pk.pack(recipient);
|
||||
pk.pack(VALUE_KEY_TO); pk.pack(recipient);
|
||||
}
|
||||
}
|
||||
pk.pack(std::string("type")); pk.pack(type);
|
||||
pk.pack(std::string("data")); pk.pack_bin(data.size());
|
||||
pk.pack_bin_body((const char*)data.data(), data.size());
|
||||
pk.pack(VALUE_KEY_TYPE); pk.pack(type);
|
||||
pk.pack(VALUE_KEY_DATA); pk.pack_bin(data.size());
|
||||
pk.pack_bin_body((const char*)data.data(), data.size());
|
||||
if (not user_type.empty()) {
|
||||
pk.pack(std::string("utype")); pk.pack(user_type);
|
||||
pk.pack(VALUE_KEY_USERTYPE); pk.pack(user_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,10 +531,10 @@ struct OPENDHT_PUBLIC Value
|
||||
pk.pack_bin_body((const char*)cypher.data(), cypher.size());
|
||||
} else {
|
||||
pk.pack_map(isSigned() ? 2 : 1);
|
||||
pk.pack(std::string("body")); msgpack_pack_to_sign(pk);
|
||||
pk.pack(VALUE_KEY_BODY); msgpack_pack_to_sign(pk);
|
||||
if (isSigned()) {
|
||||
pk.pack(std::string("sig")); pk.pack_bin(signature.size());
|
||||
pk.pack_bin_body((const char*)signature.data(), signature.size());
|
||||
pk.pack(VALUE_KEY_SIGNATURE); pk.pack_bin(signature.size());
|
||||
pk.pack_bin_body((const char*)signature.data(), signature.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -518,9 +542,12 @@ struct OPENDHT_PUBLIC Value
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_map(2);
|
||||
pk.pack(std::string("id")); pk.pack(id);
|
||||
pk.pack(std::string("dat")); msgpack_pack_to_encrypt(pk);
|
||||
pk.pack_map(2 + (priority?1:0));
|
||||
pk.pack(VALUE_KEY_ID); pk.pack(id);
|
||||
pk.pack(VALUE_KEY_DAT); msgpack_pack_to_encrypt(pk);
|
||||
if (priority) {
|
||||
pk.pack(VALUE_KEY_PRIO); pk.pack(priority);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Packer>
|
||||
@@ -551,7 +578,7 @@ struct OPENDHT_PUBLIC Value
|
||||
}
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object o);
|
||||
void msgpack_unpack(const msgpack::object& o);
|
||||
void msgpack_unpack_body(const msgpack::object& o);
|
||||
Blob getPacked() const {
|
||||
msgpack::sbuffer buffer;
|
||||
@@ -567,7 +594,7 @@ struct OPENDHT_PUBLIC Value
|
||||
/**
|
||||
* Public key of the signer.
|
||||
*/
|
||||
std::shared_ptr<const crypto::PublicKey> owner {};
|
||||
std::shared_ptr<crypto::PublicKey> owner {};
|
||||
|
||||
/**
|
||||
* Hash of the recipient (optional).
|
||||
@@ -602,6 +629,13 @@ struct OPENDHT_PUBLIC Value
|
||||
*/
|
||||
Blob cypher {};
|
||||
|
||||
/**
|
||||
* Priority of this value (used for push notifications)
|
||||
* 0 = high priority
|
||||
* 1 = normal priority
|
||||
*/
|
||||
unsigned priority {0};
|
||||
|
||||
private:
|
||||
friend class SecureDht;
|
||||
/* Cache for crypto ops */
|
||||
@@ -658,7 +692,7 @@ struct OPENDHT_PUBLIC FieldValue
|
||||
}
|
||||
}
|
||||
|
||||
void msgpack_unpack(msgpack::object msg) {
|
||||
void msgpack_unpack(const msgpack::object& msg) {
|
||||
hashValue = {};
|
||||
blobValue.clear();
|
||||
|
||||
@@ -745,6 +779,8 @@ struct OPENDHT_PUBLIC Select
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool empty() const { return fieldSelection_.empty(); }
|
||||
|
||||
OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const dht::Select& q);
|
||||
private:
|
||||
std::vector<Value::Field> fieldSelection_ {};
|
||||
|
||||
+3
-3
@@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
Name: OpenDHT
|
||||
Description: C++ Distributed Hash Table library
|
||||
Description: C++14 Distributed Hash Table library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lopendht
|
||||
Libs.private: -lpthread
|
||||
Requires.private: gnutls >= 3.1@argon2_lib@
|
||||
Libs.private: @http_parser_lib@ -pthread
|
||||
Requires.private: gnutls >= 3.3, nettle >= 2.4@argon2_lib@@jsoncpp_lib@@openssl_lib@
|
||||
Cflags: -I${includedir}
|
||||
+20
-8
@@ -36,6 +36,7 @@ from libcpp.memory cimport shared_ptr
|
||||
from cython.parallel import parallel, prange
|
||||
from cython.operator cimport dereference as deref, preincrement as inc, predecrement as dec
|
||||
from cpython cimport ref
|
||||
from datetime import timedelta
|
||||
|
||||
cimport opendht_cpp as cpp
|
||||
|
||||
@@ -235,8 +236,9 @@ cdef class Where(object):
|
||||
|
||||
cdef class Value(object):
|
||||
cdef shared_ptr[cpp.Value] _value
|
||||
def __init__(self, bytes val=b''):
|
||||
self._value.reset(new cpp.Value(val, len(val)))
|
||||
def __init__(self, bytes val=b'', cpp.uint16_t id=0):
|
||||
self._value.reset(new cpp.Value(id, val, len(val)))
|
||||
|
||||
def __str__(self):
|
||||
return self._value.get().toString().decode()
|
||||
property owner:
|
||||
@@ -270,6 +272,14 @@ cdef class Value(object):
|
||||
def __get__(self):
|
||||
return self._value.get().size()
|
||||
|
||||
cdef class ValueType(object):
|
||||
cdef cpp.ValueType * _value
|
||||
def __init__(self, cpp.uint16_t id, str name, expiration: timedelta):
|
||||
if not isinstance(expiration, timedelta):
|
||||
raise TypeError("expiration argument must be of type timedelta")
|
||||
cdef cpp.seconds duration = cpp.seconds(int(expiration.total_seconds()))
|
||||
self._value = new cpp.ValueType(id, name.encode(), duration)
|
||||
|
||||
cdef class NodeSetIter(object):
|
||||
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]]* _nodes
|
||||
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]].iterator _curIter
|
||||
@@ -319,11 +329,11 @@ cdef class PrivateKey(_WithID):
|
||||
cdef shared_ptr[cpp.PrivateKey] _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.get().getPublicKey().getId()
|
||||
h._infohash = self._key.get().getSharedPublicKey().get().getId()
|
||||
return h
|
||||
def getPublicKey(self):
|
||||
pk = PublicKey()
|
||||
pk._key = self._key.get().getPublicKey()
|
||||
pk._key = self._key.get().getSharedPublicKey()
|
||||
return pk
|
||||
def decrypt(self, bytes dat):
|
||||
cdef size_t d_len = len(dat)
|
||||
@@ -348,17 +358,17 @@ cdef class PrivateKey(_WithID):
|
||||
return k
|
||||
|
||||
cdef class PublicKey(_WithID):
|
||||
cdef cpp.PublicKey _key
|
||||
cdef cpp.shared_ptr[cpp.PublicKey] _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.getId()
|
||||
h._infohash = self._key.get().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.encrypt(indat)
|
||||
cdef cpp.Blob encrypted = self._key.get().encrypt(indat)
|
||||
cdef char* encrypted_c_str = <char *>encrypted.data()
|
||||
cdef Py_ssize_t length = encrypted.size()
|
||||
return encrypted_c_str[:length]
|
||||
@@ -430,7 +440,7 @@ cdef class Identity(object):
|
||||
property publickey:
|
||||
def __get__(self):
|
||||
k = PublicKey()
|
||||
k._key = self._id.first.get().getPublicKey()
|
||||
k._key = self._id.first.get().getSharedPublicKey()
|
||||
return k
|
||||
property certificate:
|
||||
def __get__(self):
|
||||
@@ -513,6 +523,8 @@ cdef class DhtRunner(_WithID):
|
||||
cb_obj = {'shutdown':shutdown_cb}
|
||||
ref.Py_INCREF(cb_obj)
|
||||
self.thisptr.get().shutdown(cpp.bindShutdownCb(shutdown_callback, <void*>cb_obj))
|
||||
def registerType(self, ValueType type):
|
||||
self.thisptr.get().registerType(deref(type._value))
|
||||
def enableLogging(self):
|
||||
cpp.enableLogging(self.thisptr.get()[0])
|
||||
def disableLogging(self):
|
||||
|
||||
+17
-3
@@ -26,6 +26,14 @@ from libc.string cimport const_char, const_uchar
|
||||
ctypedef uint16_t in_port_t
|
||||
ctypedef unsigned short int sa_family_t;
|
||||
|
||||
cdef extern from "<iostream>" namespace "std::chrono" nogil:
|
||||
cdef cppclass duration[ulong]:
|
||||
duration() except +
|
||||
|
||||
cdef cppclass seconds:
|
||||
duration seconds(uint64_t) except +
|
||||
duration seconds()
|
||||
|
||||
cdef extern from "<memory>" namespace "std" nogil:
|
||||
cdef cppclass shared_ptr[T]:
|
||||
shared_ptr() except +
|
||||
@@ -89,7 +97,7 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto":
|
||||
|
||||
cdef cppclass PrivateKey:
|
||||
PrivateKey()
|
||||
PublicKey getPublicKey() const
|
||||
shared_ptr[PublicKey] getSharedPublicKey() const
|
||||
Blob decrypt(Blob data) const
|
||||
@staticmethod
|
||||
PrivateKey generate()
|
||||
@@ -131,7 +139,6 @@ cdef extern from "opendht/value.h" namespace "dht::Value":
|
||||
cdef extern from "opendht/value.h" namespace "dht::Value::Field":
|
||||
cdef Field None
|
||||
cdef Field Id
|
||||
cdef Field ValueType
|
||||
cdef Field OwnerPk
|
||||
cdef Field SeqNum
|
||||
cdef Field UserType
|
||||
@@ -141,7 +148,7 @@ cdef extern from "opendht/value.h" namespace "dht":
|
||||
cdef cppclass Value:
|
||||
Value() except +
|
||||
Value(vector[uint8_t]) except +
|
||||
Value(const uint8_t* dat_ptr, size_t dat_len) except +
|
||||
Value(const uint16_t t, const uint8_t* dat_ptr, size_t dat_len) except +
|
||||
string toString() const
|
||||
size_t size() const
|
||||
uint64_t id
|
||||
@@ -150,6 +157,12 @@ cdef extern from "opendht/value.h" namespace "dht":
|
||||
vector[uint8_t] data
|
||||
string user_type
|
||||
|
||||
cdef cppclass ValueType:
|
||||
ValueType(uint16_t id, string name, seconds expiration) except +
|
||||
uint16_t id
|
||||
string name
|
||||
seconds expiration
|
||||
|
||||
cdef cppclass Query:
|
||||
Query() except +
|
||||
Query(Select s, Where w) except +
|
||||
@@ -234,6 +247,7 @@ cdef extern from "opendht/dhtrunner.h" namespace "dht":
|
||||
void run(const_char*, const_char*, const_char*, Config config)
|
||||
void join()
|
||||
void shutdown(ShutdownCallback)
|
||||
void registerType(ValueType& value);
|
||||
bool isRunning()
|
||||
SockAddr getBound(sa_family_t af) const
|
||||
string getStorageLog() const
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
|
||||
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
# Simon Désaulniers <sim.desaulniers@gmail.com>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -35,13 +35,21 @@ pong_node.ping(ping_node.getBound())
|
||||
loc_ping = dht.InfoHash.get("toto99")
|
||||
loc_pong = dht.InfoHash.get(str(loc_ping))
|
||||
|
||||
net = []
|
||||
for i in range(1,10):
|
||||
node = dht.DhtRunner()
|
||||
node.run(config=config)
|
||||
node.ping(ping_node.getBound())
|
||||
net.append(node)
|
||||
|
||||
i = 0
|
||||
MAX = 2048
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
def done(h, ok):
|
||||
print(h, "over", ok)
|
||||
pass
|
||||
#print(h, "over", ok)
|
||||
|
||||
def ping(node, h):
|
||||
global i
|
||||
@@ -52,13 +60,20 @@ def ping(node, h):
|
||||
loop.stop()
|
||||
|
||||
def pong(node, h):
|
||||
print(node.getNodeId().decode(), "got ping", h, i)
|
||||
#print(node.getNodeId().decode(), "got ping", h, i)
|
||||
loop.call_soon_threadsafe(ping, node, h)
|
||||
return True
|
||||
|
||||
t1 = time.time()
|
||||
|
||||
ping_node.listen(loc_ping, lambda v, e: pong(pong_node, loc_pong) if not e else True)
|
||||
pong_node.listen(loc_pong, lambda v, e: pong(ping_node, loc_ping) if not e else True)
|
||||
|
||||
ping(pong_node, loc_ping)
|
||||
|
||||
loop.run_forever()
|
||||
|
||||
t2 = time.time()
|
||||
|
||||
print(MAX, "ping-pong done, took", t2 - t1, "s")
|
||||
print(1000 * (t2 - t1)/MAX, "ms per rt", MAX/(t2 - t1), "rt per s")
|
||||
+11
-26
@@ -21,6 +21,7 @@ from math import cos, sin, pi
|
||||
import urllib3
|
||||
import gzip
|
||||
import queue
|
||||
from geoip import geolite2
|
||||
|
||||
sys.path.append('..')
|
||||
from opendht import *
|
||||
@@ -55,7 +56,7 @@ plt.ion()
|
||||
plt.figaspect(2.)
|
||||
|
||||
fig, axes = plt.subplots(2, 1)
|
||||
fig.set_size_inches(8,16,forward=True)
|
||||
#fig.set_size_inches(8,16,forward=True)
|
||||
fig.tight_layout()
|
||||
fig.canvas.set_window_title('OpenDHT scanner')
|
||||
|
||||
@@ -90,27 +91,12 @@ def exitcb(arg):
|
||||
run = False
|
||||
exitbtn.on_clicked(exitcb)
|
||||
|
||||
def check_dl(fname, url):
|
||||
if os.path.isfile(fname):
|
||||
return
|
||||
print('downloading', url)
|
||||
ghandle = gzip.GzipFile(fileobj=http.request('GET', url, headers={'User-Agent': 'Mozilla/5.0'}, preload_content=False))
|
||||
with open(fname, 'wb') as out:
|
||||
for line in ghandle:
|
||||
out.write(line)
|
||||
|
||||
check_dl("GeoLiteCity.dat", "http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz")
|
||||
check_dl("GeoLiteCityv6.dat", "http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz")
|
||||
|
||||
gi = GeoIP.open("GeoLiteCity.dat", GeoIP.GEOIP_INDEX_CACHE | GeoIP.GEOIP_CHECK_CACHE)
|
||||
gi6 = GeoIP.open("GeoLiteCityv6.dat", GeoIP.GEOIP_INDEX_CACHE | GeoIP.GEOIP_CHECK_CACHE)
|
||||
|
||||
def gcb(v):
|
||||
return True
|
||||
|
||||
r = DhtRunner()
|
||||
r.run(port=4112)
|
||||
r.bootstrap("bootstrap.ring.cx", "4222")
|
||||
r.bootstrap("bootstrap.jami.net", "4222")
|
||||
|
||||
plt.pause(1)
|
||||
|
||||
@@ -143,9 +129,9 @@ def nextstep(cur_h, cur_depth, ok, nodes):
|
||||
depth = min(8, commonBits+6)
|
||||
if cur_depth < depth:
|
||||
for b in range(cur_depth, depth):
|
||||
new_h = InfoHash(cur_h.toString());
|
||||
new_h.setBit(b, 1);
|
||||
step(new_h, b+1);
|
||||
new_h = InfoHash(cur_h.toString())
|
||||
new_h.setBit(b, 1)
|
||||
step(new_h, b+1)
|
||||
else:
|
||||
print("step done with no nodes", ok, cur_h.toString().decode())
|
||||
done -= 1
|
||||
@@ -186,23 +172,22 @@ def appendNewNode(n):
|
||||
if addr in nodes_ip6s:
|
||||
nodes_ip6s[addr][1] += 1
|
||||
else:
|
||||
georecord = gi6.record_by_name_v6(addr)
|
||||
georecord = geolite2.lookup(addr)
|
||||
nodes_ip6s[addr] = [n, 1, georecord]
|
||||
else:
|
||||
if addr in nodes_ip4s:
|
||||
nodes_ip4s[addr][1] += 1
|
||||
else:
|
||||
georecord = gi.record_by_name(addr)
|
||||
georecord = geolite2.lookup(addr)
|
||||
nodes_ip4s[addr] = [n, 1, georecord]
|
||||
if georecord:
|
||||
appendMapPoint(georecord)
|
||||
|
||||
def appendMapPoint(res):
|
||||
global lons, lats, cities
|
||||
lons.append(res['longitude'])
|
||||
lats.append(res['latitude'])
|
||||
cities.append(res['city'] if res['city'] else (str(int(res['latitude']))+'-'+str(int(res['longitude']))))
|
||||
|
||||
lons.append(res.location[1])
|
||||
lats.append(res.location[0])
|
||||
cities.append(res.city if res.city else (str(int(res.location[0]))+'-'+str(int(res.location[1]))))
|
||||
|
||||
def restart(arg):
|
||||
global collection, all_lines, all_nodes, points, done, nodes_ip4s, nodes_ip6s, lats, lons, cities, xys, colors
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+3
-30
@@ -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@ @Argon2_LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_SOURCES = \
|
||||
dht.cpp \
|
||||
storage.h \
|
||||
@@ -71,8 +71,8 @@ endif
|
||||
|
||||
libopendht_la_SOURCES += base64.h base64.cpp
|
||||
if PROXY_CLIENT_OR_SERVER
|
||||
libopendht_la_SOURCES += http.cpp
|
||||
nobase_include_HEADERS += ../include/opendht/proxy.h ../include/opendht/http.h
|
||||
libopendht_la_SOURCES += http.cpp compat/os_cert.cpp
|
||||
nobase_include_HEADERS += ../include/opendht/proxy.h ../include/opendht/http.h compat/os_cert.h
|
||||
endif
|
||||
|
||||
if ENABLE_PEER_DISCOVERY
|
||||
@@ -87,30 +87,3 @@ 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
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -131,7 +131,7 @@ base64_encode(const std::vector<unsigned char>& str)
|
||||
return base64_encode(str.cbegin(), str.cend());
|
||||
}
|
||||
|
||||
std::string
|
||||
std::vector<unsigned char>
|
||||
base64_decode(const std::string& str)
|
||||
{
|
||||
size_t output_length = str.length() / 4 * 3 + 2;
|
||||
@@ -139,5 +139,5 @@ base64_decode(const std::string& str)
|
||||
output.resize(output_length);
|
||||
base64_decode(str.data(), str.size(), output.data(), &output_length);
|
||||
output.resize(output_length);
|
||||
return std::string(output.begin(), output.end());
|
||||
return output;
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -33,4 +33,4 @@ std::string base64_encode(const std::vector<unsigned char>& str);
|
||||
* @param str the input buffer
|
||||
* @return a base64-decoded buffer
|
||||
*/
|
||||
std::string base64_decode(const std::string& str);
|
||||
std::vector<unsigned char> base64_decode(const std::string& str);
|
||||
+10
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -26,7 +26,7 @@ namespace dht {
|
||||
|
||||
|
||||
GetCallbackSimple
|
||||
bindGetCb(const GetCallbackRaw& raw_cb, void* user_data)
|
||||
bindGetCb(GetCallbackRaw raw_cb, void* user_data)
|
||||
{
|
||||
if (not raw_cb) return {};
|
||||
return [=](const std::shared_ptr<Value>& value) {
|
||||
@@ -35,10 +35,10 @@ bindGetCb(const GetCallbackRaw& raw_cb, void* user_data)
|
||||
}
|
||||
|
||||
GetCallback
|
||||
bindGetCb(const GetCallbackSimple& cb)
|
||||
bindGetCb(GetCallbackSimple cb)
|
||||
{
|
||||
if (not cb) return {};
|
||||
return [=](const std::vector<std::shared_ptr<Value>>& values) {
|
||||
return [cb=std::move(cb)](const std::vector<std::shared_ptr<Value>>& values) {
|
||||
for (const auto& v : values)
|
||||
if (not cb(v))
|
||||
return false;
|
||||
@@ -47,7 +47,7 @@ bindGetCb(const GetCallbackSimple& cb)
|
||||
}
|
||||
|
||||
ValueCallback
|
||||
bindValueCb(const ValueCallbackRaw& raw_cb, void* user_data)
|
||||
bindValueCb(ValueCallbackRaw raw_cb, void* user_data)
|
||||
{
|
||||
if (not raw_cb) return {};
|
||||
return [=](const std::vector<std::shared_ptr<Value>>& values, bool expired) {
|
||||
@@ -59,7 +59,7 @@ bindValueCb(const ValueCallbackRaw& raw_cb, void* user_data)
|
||||
}
|
||||
|
||||
ShutdownCallback
|
||||
bindShutdownCb(const ShutdownCallbackRaw& shutdown_cb_raw, void* user_data)
|
||||
bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data)
|
||||
{
|
||||
return [=]() { shutdown_cb_raw(user_data); };
|
||||
}
|
||||
@@ -69,11 +69,11 @@ bindDoneCb(DoneCallbackSimple donecb)
|
||||
{
|
||||
if (not donecb) return {};
|
||||
using namespace std::placeholders;
|
||||
return std::bind(donecb, _1);
|
||||
return std::bind(std::move(donecb), _1);
|
||||
}
|
||||
|
||||
DoneCallback
|
||||
bindDoneCb(const DoneCallbackRaw& raw_cb, void* user_data)
|
||||
bindDoneCb(DoneCallbackRaw raw_cb, void* user_data)
|
||||
{
|
||||
if (not raw_cb) return {};
|
||||
return [=](bool success, const std::vector<std::shared_ptr<Node>>& nodes) {
|
||||
@@ -82,7 +82,7 @@ bindDoneCb(const DoneCallbackRaw& raw_cb, void* user_data)
|
||||
}
|
||||
|
||||
DoneCallbackSimple
|
||||
bindDoneCbSimple(const DoneCallbackSimpleRaw& raw_cb, void* user_data) {
|
||||
bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data) {
|
||||
if (not raw_cb) return {};
|
||||
return [=](bool success) {
|
||||
raw_cb(success, user_data);
|
||||
@@ -94,6 +94,7 @@ NodeStats::toString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Known nodes: " << good_nodes << " good, " << dubious_nodes << " dubious, " << incoming_nodes << " incoming." << std::endl;
|
||||
ss << searches << " searches, " << node_cache_size << " total cached nodes" << std::endl;
|
||||
if (table_depth > 1) {
|
||||
ss << "Routing table depth: " << table_depth << std::endl;
|
||||
ss << "Network size estimation: " << getNetworkSizeEstimation() << " nodes" << std::endl;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "os_cert.h"
|
||||
|
||||
#include "log_enable.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#pragma comment(lib, "crypt32.lib")
|
||||
#endif
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#ifdef TARGET_OS_OSX
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#endif /*TARGET_OS_OSX*/
|
||||
|
||||
#if EMBEDDED_ASN1_TIME_PARSE
|
||||
#undef X509_NAME
|
||||
#undef OCSP_REQUEST
|
||||
#undef OCSP_RESPONSE
|
||||
#define GENTIME_LENGTH 15
|
||||
#define UTCTIME_LENGTH 13
|
||||
#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
|
||||
extern "C" {
|
||||
// Taken from libressl/src/crypto/asn1/a_time_tm.c
|
||||
int
|
||||
ASN1_time_parse(const char* bytes, size_t len, struct tm* tm, int mode)
|
||||
{
|
||||
size_t i;
|
||||
int type = 0;
|
||||
struct tm ltm;
|
||||
struct tm* lt;
|
||||
const char* p;
|
||||
|
||||
if (bytes == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Constrain to valid lengths. */
|
||||
if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH)
|
||||
return (-1);
|
||||
|
||||
lt = tm;
|
||||
if (lt == NULL) {
|
||||
memset(<m, 0, sizeof(ltm));
|
||||
lt = <m;
|
||||
}
|
||||
|
||||
/* Timezone is required and must be GMT (Zulu). */
|
||||
if (bytes[len - 1] != 'Z')
|
||||
return (-1);
|
||||
|
||||
/* Make sure everything else is digits. */
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
if (isdigit((unsigned char) bytes[i]))
|
||||
continue;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate and convert the time
|
||||
*/
|
||||
p = bytes;
|
||||
switch (len) {
|
||||
case GENTIME_LENGTH:
|
||||
if (mode == V_ASN1_UTCTIME)
|
||||
return (-1);
|
||||
lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
|
||||
type = V_ASN1_GENERALIZEDTIME;
|
||||
/* FALLTHROUGH */
|
||||
case UTCTIME_LENGTH:
|
||||
if (type == 0) {
|
||||
if (mode == V_ASN1_GENERALIZEDTIME)
|
||||
return (-1);
|
||||
type = V_ASN1_UTCTIME;
|
||||
}
|
||||
lt->tm_year += ATOI2(p); /* yy */
|
||||
if (type == V_ASN1_UTCTIME) {
|
||||
if (lt->tm_year < 50)
|
||||
lt->tm_year += 100;
|
||||
}
|
||||
lt->tm_mon = ATOI2(p) - 1; /* mm */
|
||||
if (lt->tm_mon < 0 || lt->tm_mon > 11)
|
||||
return (-1);
|
||||
lt->tm_mday = ATOI2(p); /* dd */
|
||||
if (lt->tm_mday < 1 || lt->tm_mday > 31)
|
||||
return (-1);
|
||||
lt->tm_hour = ATOI2(p); /* HH */
|
||||
if (lt->tm_hour < 0 || lt->tm_hour > 23)
|
||||
return (-1);
|
||||
lt->tm_min = ATOI2(p); /* MM */
|
||||
if (lt->tm_min < 0 || lt->tm_min > 59)
|
||||
return (-1);
|
||||
lt->tm_sec = ATOI2(p); /* SS */
|
||||
/* Leap second 60 is not accepted. Reconsider later? */
|
||||
if (lt->tm_sec < 0 || lt->tm_sec > 59)
|
||||
return (-1);
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
#endif /* EMBEDDED_ASN1_TIME_PARSE */
|
||||
|
||||
namespace dht {
|
||||
namespace http {
|
||||
|
||||
PEMCache::PEMCache(const std::shared_ptr<Logger>& l)
|
||||
: logger(l)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
PCCERT_CONTEXT pContext = NULL;
|
||||
HCERTSTORE hSystemStore;
|
||||
hSystemStore = CertOpenSystemStore(NULL, "ROOT");
|
||||
if (!hSystemStore) {
|
||||
if (logger)
|
||||
logger->e("couldn't open the system cert store");
|
||||
return;
|
||||
}
|
||||
while (pContext = CertEnumCertificatesInStore(hSystemStore, pContext)) {
|
||||
const uint8_t* encoded_cert = pContext->pbCertEncoded;
|
||||
X509Ptr x509cert(d2i_X509(nullptr, &encoded_cert, pContext->cbCertEncoded), &X509_free);
|
||||
if (x509cert)
|
||||
pems_.emplace_back(std::move(x509cert));
|
||||
}
|
||||
CertCloseStore(hSystemStore, 0);
|
||||
#elif TARGET_OS_OSX
|
||||
CFArrayRef result = NULL;
|
||||
OSStatus osStatus;
|
||||
|
||||
if ((osStatus = SecTrustCopyAnchorCertificates(&result)) != 0) {
|
||||
if (logger) {
|
||||
CFStringRef statusString = SecCopyErrorMessageString(osStatus, NULL);
|
||||
logger->d("Error enumerating certificates: %s",
|
||||
CFStringGetCStringPtr(statusString, kCFStringEncodingASCII));
|
||||
CFRelease(statusString);
|
||||
}
|
||||
if (result != NULL) {
|
||||
CFRelease(result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
CFDataRef rawData = NULL;
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(result); i++) {
|
||||
SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(result, i);
|
||||
rawData = SecCertificateCopyData(cert);
|
||||
if (!rawData) {
|
||||
if (logger)
|
||||
logger->e("couldn't copy raw certificate data");
|
||||
break;
|
||||
}
|
||||
const uint8_t* rawDataPtr = CFDataGetBytePtr(rawData);
|
||||
X509Ptr x509cert(d2i_X509(nullptr, &rawDataPtr, CFDataGetLength(rawData)), &X509_free);
|
||||
if (x509cert)
|
||||
pems_.emplace_back(std::move(x509cert));
|
||||
CFRelease(rawData);
|
||||
rawData = NULL;
|
||||
}
|
||||
if (result != NULL) {
|
||||
CFRelease(result);
|
||||
}
|
||||
if (rawData != NULL) {
|
||||
CFRelease(rawData);
|
||||
}
|
||||
#endif /*TARGET_OS_OSX, _WIN32*/
|
||||
}
|
||||
|
||||
void
|
||||
PEMCache::fillX509Store(SSL_CTX* ctx)
|
||||
{
|
||||
if (logger)
|
||||
logger->d("adding %d decoded certs to X509 store", pems_.size());
|
||||
if (X509_STORE* store = SSL_CTX_get_cert_store(ctx)) {
|
||||
for (const auto& pem : pems_) {
|
||||
if (X509_STORE_add_cert(store, pem.get()) != 1)
|
||||
if (logger)
|
||||
logger->w("couldn't add local certificate");
|
||||
}
|
||||
} else if (logger)
|
||||
logger->e("couldn't get the context cert store");
|
||||
}
|
||||
|
||||
} /*namespace http*/
|
||||
} /*namespace dht*/
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "log_enable.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER > 0x20501000L))
|
||||
#define EMBEDDED_ASN1_TIME_PARSE 0
|
||||
#else
|
||||
#define EMBEDDED_ASN1_TIME_PARSE 1
|
||||
#endif
|
||||
|
||||
#if EMBEDDED_ASN1_TIME_PARSE
|
||||
#define V_ASN1_UTCTIME 23
|
||||
#define V_ASN1_GENERALIZEDTIME 24
|
||||
|
||||
extern "C" {
|
||||
/*
|
||||
* Parse an RFC 5280 format ASN.1 time string.
|
||||
*
|
||||
* mode must be:
|
||||
* 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
|
||||
* V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
|
||||
* V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
|
||||
*
|
||||
* Returns:
|
||||
* -1 if the string was invalid.
|
||||
* V_ASN1_UTCTIME if the string validated as a UTC time string.
|
||||
* V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
|
||||
*
|
||||
* Fills in *tm with the corresponding time if tm is non NULL.
|
||||
*/
|
||||
int ASN1_time_parse(const char* bytes, size_t len, struct tm* tm, int mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
namespace http {
|
||||
|
||||
// A singleton class used to cache the decoded certificates
|
||||
// loaded from local cert stores that need to be added to the
|
||||
// ssl context prior to each request.
|
||||
class PEMCache
|
||||
{
|
||||
PEMCache(const std::shared_ptr<Logger>& l);
|
||||
|
||||
using X509Ptr = std::unique_ptr<X509, void(*)(X509*)>;
|
||||
std::vector<X509Ptr> pems_;
|
||||
std::shared_ptr<Logger> logger;
|
||||
|
||||
public:
|
||||
static PEMCache& instance(const std::shared_ptr<Logger>& l)
|
||||
{
|
||||
static PEMCache instance_(l);
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void fillX509Store(SSL_CTX* ctx);
|
||||
};
|
||||
}
|
||||
} // namespace dht
|
||||
+322
-64
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,6 +26,7 @@ extern "C" {
|
||||
#include <gnutls/x509.h>
|
||||
#include <nettle/gcm.h>
|
||||
#include <nettle/aes.h>
|
||||
#include <gnutls/crypto.h>
|
||||
|
||||
#include <argon2.h>
|
||||
}
|
||||
@@ -52,7 +54,7 @@ static std::uniform_int_distribution<uint8_t> rand_byte;
|
||||
#define GNUTLS_PKCS_PBES2_AES_256 GNUTLS_PKCS_USE_PBES2_AES_256
|
||||
#endif
|
||||
|
||||
#define DHT_AES_LEGACY_ENCRYPT 1
|
||||
#define DHT_AES_LEGACY_ENCRYPT 0
|
||||
#define DHT_AES_LEGACY_DECRYPT 1
|
||||
|
||||
namespace dht {
|
||||
@@ -67,7 +69,7 @@ constexpr gnutls_digest_algorithm_t gnutlsHashAlgo(size_t min_res) {
|
||||
GNUTLS_DIG_SHA1));
|
||||
}
|
||||
|
||||
constexpr size_t gnutlsHashSize(int algo) {
|
||||
constexpr size_t gnutlsHashSize(gnutls_digest_algorithm_t algo) {
|
||||
return (algo == GNUTLS_DIG_SHA512) ? 512/8 : (
|
||||
(algo == GNUTLS_DIG_SHA256) ? 256/8 : (
|
||||
(algo == GNUTLS_DIG_SHA1) ? 160/8 : 0 ));
|
||||
@@ -126,37 +128,37 @@ Blob aesEncrypt(const Blob& data, const std::string& password)
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
Blob aesDecrypt(const Blob& data, const Blob& key)
|
||||
Blob aesDecrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
{
|
||||
if (not aesKeySizeGood(key.size()))
|
||||
throw DecryptError("Wrong key size");
|
||||
|
||||
if (data.size() <= GCM_IV_SIZE + GCM_DIGEST_SIZE)
|
||||
if (data_length <= GCM_IV_SIZE + GCM_DIGEST_SIZE)
|
||||
throw DecryptError("Wrong data size");
|
||||
|
||||
std::array<uint8_t, GCM_DIGEST_SIZE> digest;
|
||||
|
||||
struct gcm_aes_ctx aes;
|
||||
gcm_aes_set_key(&aes, key.size(), key.data());
|
||||
gcm_aes_set_iv(&aes, GCM_IV_SIZE, data.data());
|
||||
gcm_aes_set_iv(&aes, GCM_IV_SIZE, data);
|
||||
|
||||
size_t data_sz = data.size() - GCM_IV_SIZE - GCM_DIGEST_SIZE;
|
||||
size_t data_sz = data_length - GCM_IV_SIZE - GCM_DIGEST_SIZE;
|
||||
Blob ret(data_sz);
|
||||
gcm_aes_decrypt(&aes, data_sz, ret.data(), data.data() + GCM_IV_SIZE);
|
||||
gcm_aes_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
|
||||
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE)) {
|
||||
if (not std::equal(digest.begin(), digest.end(), data + data_length - GCM_DIGEST_SIZE)) {
|
||||
#if DHT_AES_LEGACY_DECRYPT
|
||||
//gcm_aes_decrypt(&aes, data_sz, ret.data(), data.data() + GCM_IV_SIZE);
|
||||
//gcm_aes_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
Blob ret_tmp(data_sz);
|
||||
struct gcm_aes_ctx aes_d;
|
||||
gcm_aes_set_key(&aes_d, key.size(), key.data());
|
||||
gcm_aes_set_iv(&aes_d, GCM_IV_SIZE, data.data());
|
||||
gcm_aes_set_iv(&aes_d, GCM_IV_SIZE, data);
|
||||
gcm_aes_update(&aes_d, ret.size(), ret.data());
|
||||
gcm_aes_encrypt(&aes_d, ret.size(), ret_tmp.data(), ret.data());
|
||||
gcm_aes_digest(&aes_d, GCM_DIGEST_SIZE, digest.data());
|
||||
|
||||
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE))
|
||||
if (not std::equal(digest.begin(), digest.end(), data + data_length - GCM_DIGEST_SIZE))
|
||||
throw DecryptError("Can't decrypt data");
|
||||
#else
|
||||
throw DecryptError("Can't decrypt data");
|
||||
@@ -166,14 +168,13 @@ Blob aesDecrypt(const Blob& data, const Blob& key)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blob aesDecrypt(const Blob& data, const std::string& password)
|
||||
Blob aesDecrypt(const uint8_t* data, size_t data_len, const std::string& password)
|
||||
{
|
||||
if (data.size() <= PASSWORD_SALT_LENGTH)
|
||||
if (data_len <= PASSWORD_SALT_LENGTH)
|
||||
throw DecryptError("Wrong data size");
|
||||
Blob salt {data.begin(), data.begin()+PASSWORD_SALT_LENGTH};
|
||||
Blob salt {data, data+PASSWORD_SALT_LENGTH};
|
||||
Blob key = stretchKey(password, salt, 256/8);
|
||||
Blob encrypted {data.begin()+PASSWORD_SALT_LENGTH, data.end()};
|
||||
return aesDecrypt(encrypted, key);
|
||||
return aesDecrypt(data+PASSWORD_SALT_LENGTH, data_len - PASSWORD_SALT_LENGTH, key);
|
||||
}
|
||||
|
||||
Blob stretchKey(const std::string& password, Blob& salt, size_t key_length)
|
||||
@@ -290,14 +291,14 @@ PrivateKey::operator=(PrivateKey&& o) noexcept
|
||||
}
|
||||
|
||||
Blob
|
||||
PrivateKey::sign(const Blob& data) const
|
||||
PrivateKey::sign(const uint8_t* data, size_t data_length) const
|
||||
{
|
||||
if (!key)
|
||||
throw CryptoException("Can't sign data: no private key set !");
|
||||
if (std::numeric_limits<unsigned>::max() < data.size())
|
||||
if (std::numeric_limits<unsigned>::max() < data_length)
|
||||
throw CryptoException("Can't sign data: too large !");
|
||||
gnutls_datum_t sig;
|
||||
const gnutls_datum_t dat {(unsigned char*)data.data(), (unsigned)data.size()};
|
||||
const gnutls_datum_t dat {(unsigned char*)data, (unsigned)data_length};
|
||||
if (gnutls_privkey_sign_data(key, GNUTLS_DIG_SHA512, 0, &dat, &sig) != GNUTLS_E_SUCCESS)
|
||||
throw CryptoException("Can't sign data !");
|
||||
Blob ret(sig.data, sig.data+sig.size);
|
||||
@@ -319,7 +320,7 @@ PrivateKey::decryptBloc(const uint8_t* src, size_t src_size) const
|
||||
}
|
||||
|
||||
Blob
|
||||
PrivateKey::decrypt(const Blob& cipher) const
|
||||
PrivateKey::decrypt(const uint8_t* cypher, size_t cypher_len) const
|
||||
{
|
||||
if (!key)
|
||||
throw CryptoException("Can't decrypt data without private key !");
|
||||
@@ -332,12 +333,12 @@ PrivateKey::decrypt(const Blob& cipher) const
|
||||
throw CryptoException("Must be an RSA key");
|
||||
|
||||
unsigned cypher_block_sz = key_len / 8;
|
||||
if (cipher.size() < cypher_block_sz)
|
||||
if (cypher_len < cypher_block_sz)
|
||||
throw DecryptError("Unexpected cipher length");
|
||||
else if (cipher.size() == cypher_block_sz)
|
||||
return decryptBloc(cipher.data(), cypher_block_sz);
|
||||
else if (cypher_len == cypher_block_sz)
|
||||
return decryptBloc(cypher, cypher_block_sz);
|
||||
|
||||
return aesDecrypt(Blob {cipher.begin() + cypher_block_sz, cipher.end()}, decryptBloc(cipher.data(), cypher_block_sz));
|
||||
return aesDecrypt(cypher + cypher_block_sz, cypher_len - cypher_block_sz, decryptBloc(cypher, cypher_block_sz));
|
||||
}
|
||||
|
||||
Blob
|
||||
@@ -367,13 +368,22 @@ 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);
|
||||
}
|
||||
|
||||
PublicKey
|
||||
const PublicKey&
|
||||
PrivateKey::getPublicKey() const
|
||||
{
|
||||
PublicKey pk;
|
||||
if (auto err = gnutls_pubkey_import_privkey(pk.pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
|
||||
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))
|
||||
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
|
||||
return pk;
|
||||
publicKey_ = pk;
|
||||
return publicKey_;
|
||||
}
|
||||
|
||||
PublicKey::PublicKey()
|
||||
@@ -412,12 +422,18 @@ PublicKey::pack(Blob& b) const
|
||||
throw CryptoException(std::string("Could not export public key: null key"));
|
||||
std::vector<uint8_t> tmp(2048);
|
||||
size_t sz = tmp.size();
|
||||
if (int err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_DER, tmp.data(), &sz))
|
||||
if (int err = pack(tmp.data(), &sz))
|
||||
throw CryptoException(std::string("Could not export public key: ") + gnutls_strerror(err));
|
||||
tmp.resize(sz);
|
||||
b.insert(b.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
int
|
||||
PublicKey::pack(uint8_t* out, size_t* out_len) const
|
||||
{
|
||||
return gnutls_pubkey_export(pk, GNUTLS_X509_FMT_DER, out, out_len);
|
||||
}
|
||||
|
||||
void
|
||||
PublicKey::unpack(const uint8_t* data, size_t data_size)
|
||||
{
|
||||
@@ -447,7 +463,7 @@ PublicKey::toString() const
|
||||
}
|
||||
|
||||
void
|
||||
PublicKey::msgpack_unpack(msgpack::object o)
|
||||
PublicKey::msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (o.type == msgpack::type::BIN)
|
||||
unpack((const uint8_t*)o.via.bin.ptr, o.via.bin.size);
|
||||
@@ -533,12 +549,7 @@ PublicKey::getId() const
|
||||
return {};
|
||||
InfoHash id;
|
||||
size_t sz = id.size();
|
||||
#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))
|
||||
if (auto err = gnutls_pubkey_get_key_id(pk, 0, 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.");
|
||||
@@ -703,13 +714,13 @@ CertificateRequest::sign(const PrivateKey& key, const std::string& password)
|
||||
}
|
||||
|
||||
bool
|
||||
CertificateRequest::verify() const
|
||||
CertificateRequest::verify() const
|
||||
{
|
||||
return gnutls_x509_crq_verify(request, 0) >= 0;
|
||||
}
|
||||
|
||||
Blob
|
||||
CertificateRequest::pack() const
|
||||
Blob
|
||||
CertificateRequest::pack() const
|
||||
{
|
||||
gnutls_datum_t dat {nullptr, 0};
|
||||
if (auto err = gnutls_x509_crq_export2(request, GNUTLS_X509_FMT_PEM, &dat))
|
||||
@@ -720,7 +731,7 @@ CertificateRequest::pack() const
|
||||
}
|
||||
|
||||
std::string
|
||||
CertificateRequest::toString() const
|
||||
CertificateRequest::toString() const
|
||||
{
|
||||
gnutls_datum_t dat {nullptr, 0};
|
||||
if (auto err = gnutls_x509_crq_export2(request, GNUTLS_X509_FMT_PEM, &dat))
|
||||
@@ -792,7 +803,7 @@ Certificate::unpack(const uint8_t* dat, size_t dat_size)
|
||||
}
|
||||
|
||||
void
|
||||
Certificate::msgpack_unpack(msgpack::object o)
|
||||
Certificate::msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (o.type == msgpack::type::BIN)
|
||||
unpack((const uint8_t*)o.via.bin.ptr, o.via.bin.size);
|
||||
@@ -842,12 +853,15 @@ Certificate::getId() const
|
||||
{
|
||||
if (not cert)
|
||||
return {};
|
||||
if (cachedId_)
|
||||
return cachedId_;
|
||||
InfoHash id;
|
||||
size_t sz = id.size();
|
||||
if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz))
|
||||
throw CryptoException(std::string("Can't get certificate public key ID: ") + gnutls_strerror(err));
|
||||
if (sz != id.size())
|
||||
throw CryptoException("Can't get certificate public key ID: wrong output length.");
|
||||
cachedId_ = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -856,6 +870,8 @@ Certificate::getLongId() const
|
||||
{
|
||||
if (not cert)
|
||||
return {};
|
||||
if (cachedLongId_)
|
||||
return cachedLongId_;
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030401
|
||||
throw CryptoException("Can't get certificate 256 bits public key ID: GnuTLS 3.4.1 or higher required.");
|
||||
#else
|
||||
@@ -865,10 +881,23 @@ Certificate::getLongId() const
|
||||
throw CryptoException(std::string("Can't get certificate 256 bits public key ID: ") + gnutls_strerror(err));
|
||||
if (sz != id.size())
|
||||
throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length.");
|
||||
cachedLongId_ = id;
|
||||
return id;
|
||||
#endif
|
||||
}
|
||||
|
||||
Blob
|
||||
Certificate::getSerialNumber() const
|
||||
{
|
||||
if (not cert)
|
||||
return {};
|
||||
// extract from certificate
|
||||
unsigned char serial[64];
|
||||
auto size = sizeof(serial);
|
||||
gnutls_x509_crt_get_serial(cert, &serial, &size);
|
||||
return {serial, serial + size};
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getName() const
|
||||
{
|
||||
@@ -1014,6 +1043,32 @@ Certificate::getPreferredDigest() const
|
||||
return getPublicKey().getPreferredDigest();
|
||||
}
|
||||
|
||||
std::pair<std::string, Blob>
|
||||
Certificate::generateOcspRequest(gnutls_x509_crt_t& issuer)
|
||||
{
|
||||
gnutls_ocsp_req_t rreq;
|
||||
int err = gnutls_ocsp_req_init(&rreq);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
std::unique_ptr<struct gnutls_ocsp_req_int, decltype(&gnutls_ocsp_req_deinit)> req(rreq, &gnutls_ocsp_req_deinit);
|
||||
err = gnutls_ocsp_req_add_cert(req.get(), GNUTLS_DIG_SHA1, issuer, cert);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
Blob noncebuf(32);
|
||||
gnutls_datum_t nonce = { noncebuf.data(), (unsigned)noncebuf.size() };
|
||||
err = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
|
||||
err = gnutls_ocsp_req_set_nonce(req.get(), 0, &nonce);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
gnutls_datum_t rdata;
|
||||
err = gnutls_ocsp_req_export(req.get(), &rdata);
|
||||
if (err != 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
std::string ret((char*)rdata.data, (char*)rdata.data + rdata.size);
|
||||
gnutls_free(rdata.data);
|
||||
return std::make_pair<std::string, Blob>(std::move(ret), std::move(noncebuf));
|
||||
}
|
||||
|
||||
// PrivateKey
|
||||
|
||||
PrivateKey
|
||||
@@ -1102,31 +1157,29 @@ void
|
||||
setRandomSerial(gnutls_x509_crt_t cert)
|
||||
{
|
||||
random_device rdev;
|
||||
std::uniform_int_distribution<uint64_t> dist{};
|
||||
uint64_t cert_serial = dist(rdev);
|
||||
std::uniform_int_distribution<int64_t> dist{1};
|
||||
int64_t cert_serial = dist(rdev);
|
||||
gnutls_x509_crt_set_serial(cert, &cert_serial, sizeof(cert_serial));
|
||||
}
|
||||
|
||||
Certificate
|
||||
Certificate::generate(const PrivateKey& key, const std::string& name, const Identity& ca, bool is_ca)
|
||||
Certificate::generate(const PrivateKey& key, const std::string& name, const Identity& ca, bool is_ca, int64_t validity)
|
||||
{
|
||||
gnutls_x509_crt_t cert;
|
||||
if (not key.x509_key or gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
|
||||
return {};
|
||||
Certificate ret {cert};
|
||||
|
||||
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
|
||||
if (gnutls_x509_crt_set_key(cert, key.x509_key) != GNUTLS_E_SUCCESS) {
|
||||
std::cerr << "Error when setting certificate key" << std::endl;
|
||||
return {};
|
||||
setValidityPeriod(cert, validity <= 0 ? 10 * 365 * 24 * 60 * 60 : validity);
|
||||
if (int err = gnutls_x509_crt_set_key(cert, key.x509_key)) {
|
||||
throw CryptoException(std::string("Error when setting certificate key ") + gnutls_strerror(err));
|
||||
}
|
||||
if (gnutls_x509_crt_set_version(cert, 3) != GNUTLS_E_SUCCESS) {
|
||||
std::cerr << "Error when setting certificate version" << std::endl;
|
||||
return {};
|
||||
if (int err = gnutls_x509_crt_set_version(cert, 3)) {
|
||||
throw CryptoException(std::string("Error when setting certificate version ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
// TODO: compute the subject key using the recommended RFC method
|
||||
auto pk = key.getPublicKey();
|
||||
const auto& pk = key.getPublicKey();
|
||||
auto pk_id = pk.getId();
|
||||
const std::string uid_str = pk_id.toString();
|
||||
|
||||
@@ -1147,18 +1200,15 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
|
||||
if (ca.first && ca.second) {
|
||||
if (not ca.second->isCA()) {
|
||||
// Signing certificate must be CA.
|
||||
return {};
|
||||
throw CryptoException("Signing certificate must be CA");
|
||||
}
|
||||
if (gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, pk.getPreferredDigest(), 0) != GNUTLS_E_SUCCESS) {
|
||||
std::cerr << "Error when signing certificate" << std::endl;
|
||||
return {};
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, pk.getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
ret.issuer = ca.second;
|
||||
} else {
|
||||
if (gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0) != GNUTLS_E_SUCCESS) {
|
||||
std::cerr << "Error when signing certificate" << std::endl;
|
||||
return {};
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1166,7 +1216,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
}
|
||||
|
||||
Certificate
|
||||
Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
Certificate::generate(const CertificateRequest& request, const Identity& ca, int64_t validity)
|
||||
{
|
||||
gnutls_x509_crt_t cert;
|
||||
if (auto err = gnutls_x509_crt_init(&cert))
|
||||
@@ -1179,7 +1229,7 @@ Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
throw CryptoException(std::string("Can't set certificate version: ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
|
||||
setValidityPeriod(cert, validity <= 0 ? 10 * 365 * 24 * 60 * 60 : validity);
|
||||
setRandomSerial(cert);
|
||||
|
||||
if (auto err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, ca.second->getPreferredDigest(), 0)) {
|
||||
@@ -1190,6 +1240,32 @@ Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
return ret.getPacked();
|
||||
}
|
||||
|
||||
void
|
||||
Certificate::setValidity(const Identity& ca, int64_t validity)
|
||||
{
|
||||
setValidityPeriod(cert, validity);
|
||||
setRandomSerial(cert);
|
||||
if (ca.first && ca.second) {
|
||||
if (not ca.second->isCA()) {
|
||||
throw CryptoException("Signing certificate must be CA");
|
||||
}
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, ca.second->getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Certificate::setValidity(const PrivateKey& key, int64_t validity)
|
||||
{
|
||||
setValidityPeriod(cert, validity);
|
||||
setRandomSerial(cert);
|
||||
const auto& pk = key.getPublicKey();
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RevocationList>>
|
||||
Certificate::getRevocationLists() const
|
||||
{
|
||||
@@ -1200,6 +1276,188 @@ Certificate::getRevocationLists() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
// OcspRequest
|
||||
|
||||
OcspRequest::OcspRequest(const uint8_t* dat_ptr, size_t dat_size)
|
||||
{
|
||||
int ret = gnutls_ocsp_req_init(&request);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
gnutls_datum_t dat = {(unsigned char*)dat_ptr,(unsigned int)dat_size};
|
||||
ret = gnutls_ocsp_req_import(request, &dat);
|
||||
if (ret < 0){
|
||||
gnutls_ocsp_req_deinit(request);
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
}
|
||||
}
|
||||
|
||||
OcspRequest::~OcspRequest()
|
||||
{
|
||||
if (request) {
|
||||
gnutls_ocsp_req_deinit(request);
|
||||
request = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
OcspRequest::toString(const bool compact) const
|
||||
{
|
||||
int ret;
|
||||
gnutls_datum_t dat;
|
||||
ret = gnutls_ocsp_req_print(request, compact ? GNUTLS_OCSP_PRINT_COMPACT : GNUTLS_OCSP_PRINT_FULL, &dat);
|
||||
|
||||
std::string str;
|
||||
if (ret == 0) {
|
||||
str = std::string((const char*)dat.data, (size_t)dat.size);
|
||||
gnutls_free(dat.data);
|
||||
} else
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return str;
|
||||
}
|
||||
|
||||
Blob
|
||||
OcspRequest::pack() const
|
||||
{
|
||||
gnutls_datum_t dat;
|
||||
int err = gnutls_ocsp_req_export(request, &dat);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
Blob ret {dat.data, dat.data + dat.size};
|
||||
gnutls_free(dat.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Blob
|
||||
OcspRequest::getNonce() const
|
||||
{
|
||||
gnutls_datum_t dat;
|
||||
unsigned critical;
|
||||
int err = gnutls_ocsp_req_get_nonce(request, &critical, &dat);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
Blob ret {dat.data, dat.data + dat.size};
|
||||
gnutls_free(dat.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// OcspResponse
|
||||
|
||||
OcspResponse::OcspResponse(const uint8_t* dat_ptr, size_t dat_size)
|
||||
{
|
||||
int ret = gnutls_ocsp_resp_init(&response);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
gnutls_datum_t dat = {(unsigned char*)dat_ptr,(unsigned int)dat_size};
|
||||
ret = gnutls_ocsp_resp_import(response, &dat);
|
||||
if (ret < 0){
|
||||
gnutls_ocsp_resp_deinit(response);
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
}
|
||||
}
|
||||
|
||||
OcspResponse::~OcspResponse()
|
||||
{
|
||||
gnutls_ocsp_resp_deinit(response);
|
||||
}
|
||||
|
||||
Blob
|
||||
OcspResponse::pack() const
|
||||
{
|
||||
gnutls_datum_t dat;
|
||||
int err = gnutls_ocsp_resp_export(response, &dat);
|
||||
if (err < 0)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
Blob ret {dat.data, dat.data + dat.size};
|
||||
gnutls_free(dat.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string
|
||||
OcspResponse::toString(const bool compact) const
|
||||
{
|
||||
int ret;
|
||||
std::string str;
|
||||
gnutls_datum_t dat;
|
||||
ret = gnutls_ocsp_resp_print(response, compact ? GNUTLS_OCSP_PRINT_COMPACT : GNUTLS_OCSP_PRINT_FULL, &dat);
|
||||
if (ret == 0)
|
||||
str = std::string((const char*)dat.data, (size_t)dat.size);
|
||||
gnutls_free(dat.data);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
gnutls_ocsp_cert_status_t
|
||||
OcspResponse::getCertificateStatus() const
|
||||
{
|
||||
int ret;
|
||||
unsigned int status;
|
||||
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status, NULL, NULL, NULL, NULL);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return (gnutls_ocsp_cert_status_t) status;
|
||||
}
|
||||
|
||||
gnutls_ocsp_cert_status_t
|
||||
OcspResponse::verifyDirect(const Certificate& crt, const Blob& nonce)
|
||||
{
|
||||
// Check OCSP response
|
||||
int ret = gnutls_ocsp_resp_get_status(response);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
gnutls_ocsp_resp_status_t status = (gnutls_ocsp_resp_status_t)ret;
|
||||
if (status != GNUTLS_OCSP_RESP_SUCCESSFUL)
|
||||
throw CryptoException("OCSP request unsuccessful: " + std::to_string(ret));
|
||||
|
||||
if (not nonce.empty()) {
|
||||
// Ensure no replay attack has been done
|
||||
gnutls_datum_t rnonce;
|
||||
ret = gnutls_ocsp_resp_get_nonce(response, NULL, &rnonce);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
if (rnonce.size != nonce.size() || memcmp(nonce.data(), rnonce.data, nonce.size()) != 0){
|
||||
gnutls_free(rnonce.data);
|
||||
throw CryptoException(gnutls_strerror(GNUTLS_E_OCSP_RESPONSE_ERROR));
|
||||
}
|
||||
gnutls_free(rnonce.data);
|
||||
}
|
||||
|
||||
// Verify signature of the Basic OCSP response against the public key in the issuer certificate.
|
||||
unsigned int verify = 0;
|
||||
ret = gnutls_ocsp_resp_verify_direct(response, crt.issuer->cert, &verify, 0);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
if (verify) {
|
||||
if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
|
||||
throw CryptoException("Signer cert not found");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
|
||||
throw CryptoException("Signer cert keyusage error");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
|
||||
throw CryptoException("Signer cert is not trusted");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
|
||||
throw CryptoException("Insecure algorithm");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
|
||||
throw CryptoException("Signature failure");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
|
||||
throw CryptoException("Signer cert not yet activated");
|
||||
if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
|
||||
throw CryptoException("Signer cert expired");
|
||||
throw CryptoException(gnutls_strerror(GNUTLS_E_OCSP_RESPONSE_ERROR));
|
||||
}
|
||||
|
||||
// Check whether the OCSP response is about the provided certificate.
|
||||
if ((ret = gnutls_ocsp_resp_check_crt(response, 0, crt.cert)) < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
|
||||
// Check certificate revocation status
|
||||
unsigned status_ocsp;
|
||||
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status_ocsp, NULL, NULL, NULL, NULL);
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return (gnutls_ocsp_cert_status_t)status_ocsp;
|
||||
}
|
||||
|
||||
// RevocationList
|
||||
|
||||
RevocationList::RevocationList()
|
||||
@@ -1252,7 +1510,7 @@ RevocationList::unpack(const uint8_t* dat, size_t dat_size)
|
||||
}
|
||||
|
||||
void
|
||||
RevocationList::msgpack_unpack(msgpack::object o)
|
||||
RevocationList::msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
try {
|
||||
if (o.type == msgpack::type::BIN)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+536
-352
File diff suppressed because it is too large.
Load diff
+150
-90
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
@@ -46,7 +46,7 @@ struct DhtProxyClient::Listener
|
||||
|
||||
unsigned callbackId;
|
||||
OpValueCache cache;
|
||||
ValueCallback cb;
|
||||
CacheValueCallback cb;
|
||||
Sp<OperationState> opstate;
|
||||
std::shared_ptr<http::Request> request;
|
||||
std::unique_ptr<asio::steady_timer> refreshSubscriberTimer;
|
||||
@@ -68,6 +68,7 @@ struct DhtProxyClient::ProxySearch {
|
||||
std::unique_ptr<asio::steady_timer> opExpirationTimer;
|
||||
std::map<size_t, Listener> listeners {};
|
||||
std::map<Value::Id, PermanentPut> puts {};
|
||||
std::set<Sp<Value>> pendingPuts {};
|
||||
};
|
||||
|
||||
struct LineSplit {
|
||||
@@ -77,13 +78,12 @@ struct LineSplit {
|
||||
bool getLine(char c) {
|
||||
auto it = buf_.begin();
|
||||
while (it != buf_.end()) {
|
||||
if (*it == c) {
|
||||
if (*(it++) == c) {
|
||||
line_.clear();
|
||||
line_.insert(line_.end(), buf_.begin(), ++it);
|
||||
line_.insert(line_.end(), buf_.begin(), it);
|
||||
buf_.erase(buf_.begin(), it);
|
||||
return true;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -93,17 +93,28 @@ private:
|
||||
std::string line_ {};
|
||||
};
|
||||
|
||||
std::string
|
||||
getRandomSessionId(size_t length = 8) {
|
||||
static constexpr const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~";
|
||||
std::string str(length, 0);
|
||||
crypto::random_device rdev;
|
||||
std::uniform_int_distribution<> dist(0, (sizeof(chars)/sizeof(char)) - 2);
|
||||
std::generate_n( str.begin(), length, [&]{ return chars[dist(rdev)]; } );
|
||||
return str;
|
||||
}
|
||||
|
||||
DhtProxyClient::DhtProxyClient() {}
|
||||
|
||||
DhtProxyClient::DhtProxyClient(
|
||||
std::shared_ptr<dht::crypto::Certificate> serverCA, dht::crypto::Identity clientIdentity,
|
||||
std::function<void()> signal, const std::string& serverHost,
|
||||
const std::string& pushClientId, std::shared_ptr<dht::Logger> logger)
|
||||
: proxyUrl_(serverHost)
|
||||
: DhtInterface(logger)
|
||||
, proxyUrl_(serverHost)
|
||||
, clientIdentity_(clientIdentity), serverCertificate_(serverCA)
|
||||
, pushClientId_(pushClientId), loopSignal_(signal)
|
||||
, pushClientId_(pushClientId), pushSessionId_(getRandomSessionId())
|
||||
, loopSignal_(signal)
|
||||
, jsonReader_(Json::CharReaderBuilder{}.newCharReader())
|
||||
, logger_(logger)
|
||||
{
|
||||
jsonBuilder_["commentStyle"] = "None";
|
||||
jsonBuilder_["indentation"] = "";
|
||||
@@ -144,10 +155,10 @@ DhtProxyClient::startProxy()
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] start proxy with %s", proxyUrl_.c_str());
|
||||
|
||||
nextProxyConfirmationTimer_ = std::make_shared<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now());
|
||||
nextProxyConfirmationTimer_ = std::make_unique<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now());
|
||||
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
|
||||
|
||||
listenerRestartTimer_ = std::make_shared<asio::steady_timer>(httpContext_);
|
||||
listenerRestartTimer_ = std::make_unique<asio::steady_timer>(httpContext_);
|
||||
|
||||
loopSignal_();
|
||||
}
|
||||
@@ -231,7 +242,7 @@ DhtProxyClient::cancelAllListeners()
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClient::shutdown(ShutdownCallback cb)
|
||||
DhtProxyClient::shutdown(ShutdownCallback cb, bool)
|
||||
{
|
||||
stop();
|
||||
if (cb)
|
||||
@@ -269,7 +280,7 @@ DhtProxyClient::isRunning(sa_family_t af) const
|
||||
}
|
||||
|
||||
time_point
|
||||
DhtProxyClient::periodic(const uint8_t*, size_t, SockAddr)
|
||||
DhtProxyClient::periodic(const uint8_t*, size_t, SockAddr, const time_point& /*now*/)
|
||||
{
|
||||
// Exec all currently stored callbacks
|
||||
decltype(callbacks_) callbacks;
|
||||
@@ -315,7 +326,8 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
|
||||
auto& b = *rxBuf;
|
||||
b.append(at, length);
|
||||
// one value per body line
|
||||
while (b.getLine('\n') and !opstate->stop){
|
||||
std::vector<Sp<Value>> values;
|
||||
while (b.getLine('\n') and !opstate->stop) {
|
||||
std::string err;
|
||||
Json::Value json;
|
||||
const auto& line = b.line();
|
||||
@@ -324,17 +336,19 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
|
||||
return;
|
||||
}
|
||||
auto value = std::make_shared<Value>(json);
|
||||
if ((not filter or filter(*value)) and cb){
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([opstate, cb, value](){
|
||||
if (not opstate->stop.load() and not cb({value})){
|
||||
opstate->stop.store(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
loopSignal_();
|
||||
if ((not filter or filter(*value)) and cb)
|
||||
values.emplace_back(std::move(value));
|
||||
}
|
||||
if (not values.empty() and cb) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([opstate, cb, values = std::move(values)](){
|
||||
if (not opstate->stop.load() and not cb(values)){
|
||||
opstate->stop.store(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
loopSignal_();
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
if (logger_)
|
||||
@@ -387,23 +401,22 @@ DhtProxyClient::put(const InfoHash& key, Sp<Value> val, DoneCallback cb, time_po
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [put] [search %s]", key.to_c_str());
|
||||
|
||||
if (val->id == Value::INVALID_ID) {
|
||||
crypto::random_device rdev;
|
||||
val->id = std::uniform_int_distribution<Value::Id>{1}(rdev);
|
||||
}
|
||||
std::shared_ptr<std::atomic_bool> ok;
|
||||
if (permanent) {
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
auto id = val->id;
|
||||
auto& search = searches_[key];
|
||||
auto refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now() +
|
||||
proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
|
||||
search.puts.erase(id);
|
||||
ok = std::make_shared<std::atomic_bool>(true);
|
||||
search.puts.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(id),
|
||||
std::forward_as_tuple(val, std::move(refreshPutTimer), ok));
|
||||
auto& search = searches_[key];
|
||||
if (val->id) {
|
||||
auto id = val->id;
|
||||
auto refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_, proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
|
||||
search.puts.erase(id);
|
||||
search.puts.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(id),
|
||||
std::forward_as_tuple(val, std::move(refreshPutTimer), ok));
|
||||
} else {
|
||||
search.pendingPuts.emplace(val);
|
||||
}
|
||||
}
|
||||
doPut(key, val, [this, cb, ok](bool result){
|
||||
if (ok)
|
||||
@@ -438,7 +451,7 @@ DhtProxyClient::handleRefreshPut(const asio::error_code &ec, InfoHash key, Value
|
||||
doPut(key, p->second.value, [ok = p->second.ok](bool result){
|
||||
*ok = result;
|
||||
}, time_point::max(), true);
|
||||
p->second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() + proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
p->second.refreshPutTimer->expires_after(proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
p->second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
|
||||
}
|
||||
}
|
||||
@@ -450,7 +463,7 @@ DhtProxyClient::buildRequest(const std::string& target)
|
||||
auto resolver = resolver_;
|
||||
if (not resolver)
|
||||
resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
|
||||
auto request = target.empty()
|
||||
auto request = target.empty()
|
||||
? std::make_shared<http::Request>(httpContext_, resolver)
|
||||
: std::make_shared<http::Request>(httpContext_, resolver, target);
|
||||
if (serverCertificate_)
|
||||
@@ -488,9 +501,35 @@ DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb,
|
||||
}
|
||||
}
|
||||
request->set_body(Json::writeString(jsonBuilder_, json));
|
||||
request->add_on_done_callback([this, reqid, cb] (const http::Response& response){
|
||||
request->add_on_done_callback([this, reqid, cb, val, key, permanent] (const http::Response& response){
|
||||
bool ok = response.status_code == 200;
|
||||
if (not ok) {
|
||||
if (ok) {
|
||||
if (val->id == Value::INVALID_ID) {
|
||||
std::string err;
|
||||
Json::Value parsedValue;
|
||||
if (jsonReader_->parse(response.body.data(), response.body.data() + response.body.size(), &parsedValue, &err)){
|
||||
auto id = dht::Value(parsedValue).id;
|
||||
val->id = id;
|
||||
if (permanent) {
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
auto& search = searches_[key];
|
||||
auto it = search.pendingPuts.find(val);
|
||||
if (it != search.pendingPuts.end()) {
|
||||
auto sok = std::make_shared<std::atomic_bool>(ok);
|
||||
auto refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_, proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
|
||||
search.puts.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(id),
|
||||
std::forward_as_tuple(val, std::move(refreshPutTimer), sok));
|
||||
search.pendingPuts.erase(it);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->e("[proxy:client] [status] failed to parse value from server", response.status_code);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->e("[proxy:client] [status] failed with code=%i", response.status_code);
|
||||
if (not response.aborted and response.status_code == 0)
|
||||
@@ -585,20 +624,22 @@ DhtProxyClient::getProxyInfos()
|
||||
logger_->d("[proxy:client] [status] sending request");
|
||||
|
||||
auto resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
|
||||
queryProxyInfo(infoState, AF_INET, resolver);
|
||||
queryProxyInfo(infoState, AF_INET6, resolver);
|
||||
queryProxyInfo(infoState, resolver, AF_INET);
|
||||
queryProxyInfo(infoState, resolver, AF_INET6);
|
||||
resolver_ = resolver;
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClient::queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t family, std::shared_ptr<http::Resolver> resolver)
|
||||
DhtProxyClient::queryProxyInfo(const Sp<InfoState>& infoState, const Sp<http::Resolver>& resolver, sa_family_t family)
|
||||
{
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [status] query ipv%i info", family == AF_INET ? 4 : 6);
|
||||
try {
|
||||
auto request = std::make_shared<http::Request>(httpContext_, resolver, family);
|
||||
if (serverCertificate_)
|
||||
request->set_certificate_authority(serverCertificate_);
|
||||
auto reqid = request->id();
|
||||
request->set_method(restinio::http_method_get());
|
||||
request->set_method(restinio::http_method_get());
|
||||
setHeaderFields(*request);
|
||||
request->add_on_done_callback([this, reqid, family, infoState] (const http::Response& response){
|
||||
if (infoState->cancel.load())
|
||||
@@ -615,10 +656,9 @@ DhtProxyClient::queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t
|
||||
Json::Value proxyInfos;
|
||||
if (!jsonReader_->parse(response.body.data(), response.body.data() + response.body.size(), &proxyInfos, &err)){
|
||||
onProxyInfos(Json::Value{}, family);
|
||||
return;
|
||||
}
|
||||
if (not infoState->cancel)
|
||||
} else if (not infoState->cancel) {
|
||||
onProxyInfos(proxyInfos, family);
|
||||
}
|
||||
}
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
@@ -645,7 +685,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
{
|
||||
if (isDestroying_)
|
||||
return;
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
|
||||
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
auto& status = family == AF_INET ? statusIpv4_ : statusIpv6_;
|
||||
if (not proxyInfos.isMember("node_id")) {
|
||||
@@ -680,9 +720,19 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
}
|
||||
auto newStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
if (newStatus == NodeStatus::Connected) {
|
||||
if (oldStatus == NodeStatus::Disconnected || oldStatus == NodeStatus::Connecting) {
|
||||
if (oldStatus == NodeStatus::Disconnected || oldStatus == NodeStatus::Connecting || launchConnectedCbs_) {
|
||||
launchConnectedCbs_ = false;
|
||||
listenerRestartTimer_->expires_at(std::chrono::steady_clock::now());
|
||||
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this));
|
||||
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this, std::placeholders::_1));
|
||||
if (not onConnectCallbacks_.empty()) {
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([cbs = std::move(onConnectCallbacks_)]() mutable {
|
||||
while (not cbs.empty()) {
|
||||
cbs.front()();
|
||||
cbs.pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
nextProxyConfirmationTimer_->expires_at(std::chrono::steady_clock::now() + std::chrono::minutes(15));
|
||||
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
|
||||
@@ -691,6 +741,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
nextProxyConfirmationTimer_->expires_at(std::chrono::steady_clock::now() + std::chrono::minutes(1));
|
||||
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
|
||||
}
|
||||
l.unlock();
|
||||
loopSignal_();
|
||||
}
|
||||
|
||||
@@ -750,7 +801,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
|
||||
// Add cache callback
|
||||
auto opstate = std::make_shared<OperationState>();
|
||||
l->second.opstate = opstate;
|
||||
l->second.cb = [this,key,token,opstate](const std::vector<Sp<Value>>& values, bool expired){
|
||||
l->second.cb = [this,key,token,opstate](const std::vector<Sp<Value>>& values, bool expired, system_clock::time_point t){
|
||||
if (opstate->stop)
|
||||
return false;
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
@@ -758,7 +809,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
|
||||
if (s != searches_.end()) {
|
||||
auto l = s->second.listeners.find(token);
|
||||
if (l != s->second.listeners.end()) {
|
||||
return l->second.cache.onValue(values, expired);
|
||||
return l->second.cache.onValue(values, expired, t);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -779,13 +830,8 @@ 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;
|
||||
@@ -929,8 +975,8 @@ DhtProxyClient::handleExpireListener(const asio::error_code &ec, const InfoHash&
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClient::sendListen(const restinio::http_request_header_t header,
|
||||
const ValueCallback& cb,
|
||||
DhtProxyClient::sendListen(const restinio::http_request_header_t& header,
|
||||
const CacheValueCallback& cb,
|
||||
const Sp<OperationState>& opstate,
|
||||
Listener& listener, ListenMethod method)
|
||||
{
|
||||
@@ -957,7 +1003,7 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
|
||||
b.append(at, length);
|
||||
|
||||
// one value per body line
|
||||
while (b.getLine('\n') and !opstate->stop){
|
||||
while (b.getLine('\n') and !opstate->stop) {
|
||||
std::string err;
|
||||
Json::Value json;
|
||||
const auto& line = b.line();
|
||||
@@ -975,7 +1021,7 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([cb, value, opstate, expired]() {
|
||||
if (not opstate->stop.load() and not cb({value}, expired))
|
||||
if (not opstate->stop.load() and not cb({value}, expired, system_clock::time_point::min()))
|
||||
opstate->stop.store(true);
|
||||
});
|
||||
}
|
||||
@@ -1040,8 +1086,16 @@ DhtProxyClient::getConnectivityStatus()
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClient::restartListeners()
|
||||
DhtProxyClient::restartListeners(const asio::error_code &ec)
|
||||
{
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
else if (ec){
|
||||
if (logger_)
|
||||
logger_->e("[proxy:client] restart error: %s", ec.message().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDestroying_)
|
||||
return;
|
||||
if (logger_)
|
||||
@@ -1051,17 +1105,15 @@ DhtProxyClient::restartListeners()
|
||||
for (auto& search : searches_) {
|
||||
auto key = search.first;
|
||||
for (auto& put : search.second.puts) {
|
||||
if (!*put.second.ok) {
|
||||
doPut(key, put.second.value, [ok = put.second.ok](bool result){
|
||||
*ok = result;
|
||||
}, time_point::max(), true);
|
||||
if (!put.second.refreshPutTimer){
|
||||
put.second.refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_);
|
||||
}
|
||||
put.second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() + proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
put.second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this,
|
||||
std::placeholders::_1, key, put.first));
|
||||
doPut(key, put.second.value, [ok = put.second.ok](bool result){
|
||||
*ok = result;
|
||||
}, time_point::max(), true);
|
||||
if (!put.second.refreshPutTimer) {
|
||||
put.second.refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_);
|
||||
}
|
||||
put.second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() + proxy::OP_TIMEOUT - proxy::OP_MARGIN);
|
||||
put.second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this,
|
||||
std::placeholders::_1, key, put.first));
|
||||
}
|
||||
}
|
||||
if (not deviceKey_.empty()) {
|
||||
@@ -1095,13 +1147,8 @@ DhtProxyClient::restartListeners()
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1114,10 +1161,20 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
{
|
||||
// If a push notification is received, the proxy is up and running
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
if (oldStatus != NodeStatus::Connected)
|
||||
launchConnectedCbs_ = true;
|
||||
statusIpv4_ = NodeStatus::Connected;
|
||||
statusIpv6_ = NodeStatus::Connected;
|
||||
}
|
||||
auto launchLoop = false;
|
||||
try {
|
||||
auto sessionId = notification.find("s");
|
||||
if (sessionId != notification.end() and sessionId->second != pushSessionId_) {
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [push] ignoring push for other session");
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
auto timeout = notification.find("timeout");
|
||||
if (timeout != notification.cend()) {
|
||||
@@ -1140,6 +1197,10 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
}
|
||||
} else {
|
||||
auto key = InfoHash(notification.at("key"));
|
||||
system_clock::time_point sendTime = system_clock::time_point::min();
|
||||
try {
|
||||
sendTime = system_clock::time_point(std::chrono::milliseconds(std::stoull(notification.at("t"))));
|
||||
} catch (...) {}
|
||||
auto& search = searches_.at(key);
|
||||
for (auto& list : search.listeners) {
|
||||
if (list.second.opstate->stop)
|
||||
@@ -1152,24 +1213,24 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
if (expired == notification.end()) {
|
||||
auto cb = list.second.cb;
|
||||
auto oldValues = list.second.cache.getValues();
|
||||
get(key, [cb](const std::vector<Sp<Value>>& vals) {
|
||||
return cb(vals, false);
|
||||
}, [cb, oldValues](bool /*ok*/) {
|
||||
get(key, [cb, sendTime](const std::vector<Sp<Value>>& vals) {
|
||||
return cb(vals, false, sendTime);
|
||||
}, [cb, oldValues, sendTime](bool /*ok*/) {
|
||||
// Decrement old values refcount to expire values not
|
||||
// present in the new list
|
||||
cb(oldValues, true);
|
||||
cb(oldValues, true, sendTime);
|
||||
});
|
||||
} else {
|
||||
std::stringstream ss(expired->second);
|
||||
std::vector<Value::Id> ids;
|
||||
while(ss.good()){
|
||||
while(ss.good()) {
|
||||
std::string substr;
|
||||
getline(ss, substr, ',');
|
||||
ids.emplace_back(std::stoull(substr));
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([this, key, token, opstate, ids]() {
|
||||
callbacks_.emplace_back([this, key, token, opstate, ids, sendTime]() {
|
||||
if (opstate->stop)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
@@ -1179,11 +1240,11 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
auto l = s->second.listeners.find(token);
|
||||
if (l == s->second.listeners.end())
|
||||
return;
|
||||
if (not opstate->stop and not l->second.cache.onValuesExpired(ids))
|
||||
if (not opstate->stop and not l->second.cache.onValuesExpired(ids, sendTime))
|
||||
opstate->stop = true;
|
||||
});
|
||||
}
|
||||
loopSignal_();
|
||||
launchLoop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1191,6 +1252,8 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
if (logger_)
|
||||
logger_->e("[proxy:client] [push] receive error: %s", e.what());
|
||||
}
|
||||
if (launchLoop)
|
||||
loopSignal_();
|
||||
#else
|
||||
(void) notification;
|
||||
#endif
|
||||
@@ -1206,11 +1269,7 @@ DhtProxyClient::resubscribe(const InfoHash& key, const size_t token, Listener& l
|
||||
logger_->d("[proxy:client] [resubscribe] [search %s]", key.to_c_str());
|
||||
|
||||
auto opstate = listener.opstate;
|
||||
opstate->stop = true;
|
||||
if (listener.request){
|
||||
listener.request.reset();
|
||||
}
|
||||
opstate->stop = false;
|
||||
listener.request.reset(); // This will update ok to false
|
||||
opstate->ok = true;
|
||||
|
||||
restinio::http_request_header_t header;
|
||||
@@ -1237,6 +1296,7 @@ DhtProxyClient::getPushRequest(Json::Value& body) const
|
||||
{
|
||||
body["key"] = deviceKey_;
|
||||
body["client_id"] = pushClientId_;
|
||||
body["session_id"] = pushSessionId_;
|
||||
#ifdef __ANDROID__
|
||||
body["platform"] = "android";
|
||||
#endif
|
||||
|
||||
+515
-377
File diff suppressed because it is too large.
Load diff
+226
-157
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
@@ -32,17 +32,10 @@
|
||||
#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
|
||||
#include <fstream>
|
||||
|
||||
namespace dht {
|
||||
|
||||
constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD;
|
||||
static constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 16;
|
||||
static constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(500);
|
||||
static const std::string PEER_DISCOVERY_DHT_SERVICE = "dht";
|
||||
|
||||
struct DhtRunner::Listener {
|
||||
@@ -82,34 +75,27 @@ DhtRunner::~DhtRunner()
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(in_port_t port, const Config& config, Context&& context)
|
||||
DhtRunner::run(in_port_t port, Config& config, Context&& context)
|
||||
{
|
||||
SockAddr sin4;
|
||||
sin4.setFamily(AF_INET);
|
||||
sin4.setPort(port);
|
||||
SockAddr sin6;
|
||||
sin6.setFamily(AF_INET6);
|
||||
sin6.setPort(port);
|
||||
run(sin4, sin6, config, std::move(context));
|
||||
config.bind4.setFamily(AF_INET);
|
||||
config.bind4.setPort(port);
|
||||
config.bind6.setFamily(AF_INET6);
|
||||
config.bind6.setPort(port);
|
||||
run(config, std::move(context));
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(const char* ip4, const char* ip6, const char* service, const Config& config, Context&& context)
|
||||
DhtRunner::run(const char* ip4, const char* ip6, const char* service, Config& config, Context&& context)
|
||||
{
|
||||
auto res4 = SockAddr::resolve(ip4, service);
|
||||
auto res6 = SockAddr::resolve(ip6, service);
|
||||
run(res4.empty() ? SockAddr() : res4.front(),
|
||||
res6.empty() ? SockAddr() : res6.front(), config, std::move(context));
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const Config& config, Context&& context)
|
||||
{
|
||||
if (running == State::Idle) {
|
||||
if (not context.sock)
|
||||
context.sock.reset(new net::UdpSocket(local4, local6, context.logger ? *context.logger : Logger{}));
|
||||
run(config, std::move(context));
|
||||
}
|
||||
if (res4.empty())
|
||||
res4.emplace_back();
|
||||
if (res6.empty())
|
||||
res6.emplace_back();
|
||||
config.bind4 = std::move(res4.front());
|
||||
config.bind6 = std::move(res6.front());
|
||||
run(config, std::move(context));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -117,36 +103,85 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
auto expected = State::Idle;
|
||||
if (not running.compare_exchange_strong(expected, State::Running))
|
||||
if (not running.compare_exchange_strong(expected, State::Running)) {
|
||||
if (context.logger)
|
||||
context.logger->w("[runner %p] Node is already running. Call join() first before calling run() again.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto local4 = config.bind4;
|
||||
auto local6 = config.bind6;
|
||||
if (not local4 and not local6) {
|
||||
if (context.logger)
|
||||
context.logger->w("[runner %p] No address to bind specified in the configuration, using default addresses");
|
||||
local4.setFamily(AF_INET);
|
||||
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)) {
|
||||
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);
|
||||
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);
|
||||
local6.setPort(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (not context.sock)
|
||||
context.sock.reset(new net::UdpSocket(local4, local6, context.logger));
|
||||
|
||||
if (not state_path.empty()) {
|
||||
std::ofstream outConfig(state_path);
|
||||
outConfig << context.sock->getBoundRef(AF_INET).getPort() << std::endl;
|
||||
outConfig << context.sock->getBoundRef(AF_INET6).getPort() << std::endl;
|
||||
}
|
||||
|
||||
if (context.logger) {
|
||||
logger_ = context.logger;
|
||||
logger_->d("[runner %p] state changed to Running", this);
|
||||
}
|
||||
|
||||
context.sock->setOnReceive([&] (std::unique_ptr<net::ReceivedPacket>&& pkt) {
|
||||
context.sock->setOnReceive([&] (net::PacketList&& pkts) {
|
||||
net::PacketList ret;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
if (rcv.size() >= RX_QUEUE_MAX_SIZE) {
|
||||
auto maxSize = net::RX_QUEUE_MAX_SIZE - pkts.size();
|
||||
while (rcv.size() > maxSize) {
|
||||
if (logger_)
|
||||
logger_->e("Dropping packet: queue is full!");
|
||||
rcv.pop();
|
||||
rcv.pop_front();
|
||||
}
|
||||
rcv.emplace(std::move(pkt));
|
||||
|
||||
rcv.splice(rcv.end(), std::move(pkts));
|
||||
ret = std::move(rcv_free);
|
||||
}
|
||||
cv.notify_all();
|
||||
return ret;
|
||||
});
|
||||
|
||||
auto dht = std::unique_ptr<DhtInterface>(new Dht(std::move(context.sock), SecureDht::getConfig(config.dht_config), context.logger ? *context.logger : Logger{}));
|
||||
dht_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht), config.dht_config));
|
||||
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
config_ = config;
|
||||
identityAnnouncedCb_ = context.identityAnnouncedCb;
|
||||
#endif
|
||||
auto dht = std::unique_ptr<DhtInterface>(new Dht(std::move(context.sock), SecureDht::getConfig(config.dht_config), context.logger));
|
||||
dht_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht), config.dht_config, std::move(context.identityAnnouncedCb), context.logger));
|
||||
|
||||
enableProxy(not config.proxy_server.empty());
|
||||
if (context.logger and dht_via_proxy_) {
|
||||
dht_via_proxy_->setLogger(*context.logger);
|
||||
dht_via_proxy_->setLogger(context.logger);
|
||||
}
|
||||
if (context.statusChangedCallback) {
|
||||
statusCb = std::move(context.statusChangedCallback);
|
||||
@@ -177,7 +212,7 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
if (not pending_ops_prio.empty())
|
||||
return true;
|
||||
auto s = getStatus();
|
||||
if (not pending_ops.empty() and (s == NodeStatus::Connected or (s == NodeStatus::Disconnected and not bootstraping)))
|
||||
if (not pending_ops.empty() and (s == NodeStatus::Connected or s == NodeStatus::Disconnected))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -215,13 +250,13 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
adc.net = netId;
|
||||
adc.nodeId = dht_->getNodeId();
|
||||
// IPv4
|
||||
if (auto bound4 = dht_->getSocket()->getBound(AF_INET)) {
|
||||
if (const auto& bound4 = dht_->getSocket()->getBoundRef(AF_INET)) {
|
||||
adc.port = bound4.getPort();
|
||||
msgpack::pack(sbuf_node, adc);
|
||||
peerDiscovery_->startPublish(AF_INET, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
|
||||
}
|
||||
// IPv6
|
||||
if (auto bound6 = dht_->getSocket()->getBound(AF_INET6)) {
|
||||
if (const auto& bound6 = dht_->getSocket()->getBoundRef(AF_INET6)) {
|
||||
adc.port = bound6.getPort();
|
||||
sbuf_node.clear();
|
||||
msgpack::pack(sbuf_node, adc);
|
||||
@@ -232,29 +267,31 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::shutdown(ShutdownCallback cb) {
|
||||
DhtRunner::shutdown(ShutdownCallback cb, bool stop) {
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
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) cb();
|
||||
else if (cb) {
|
||||
lck.unlock();
|
||||
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_prio.emplace([=](SecureDht&) mutable {
|
||||
pending_ops.emplace([=](SecureDht&) mutable {
|
||||
auto onShutdown = [this]{ opEnded(); };
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->shutdown(onShutdown);
|
||||
dht_via_proxy_->shutdown(onShutdown, stop);
|
||||
#endif
|
||||
if (dht_)
|
||||
dht_->shutdown(onShutdown);
|
||||
dht_->shutdown(onShutdown, stop);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -283,11 +320,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)
|
||||
@@ -303,7 +340,6 @@ DhtRunner::join()
|
||||
if (running.exchange(State::Idle) == State::Idle)
|
||||
return;
|
||||
cv.notify_all();
|
||||
bootstrap_cv.notify_all();
|
||||
#ifdef OPENDHT_PEER_DISCOVERY
|
||||
if (peerDiscovery_)
|
||||
peerDiscovery_->stop();
|
||||
@@ -318,14 +354,15 @@ DhtRunner::join()
|
||||
if (dht_thread.joinable())
|
||||
dht_thread.join();
|
||||
|
||||
if (bootstrap_thread.joinable())
|
||||
bootstrap_thread.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);
|
||||
@@ -368,6 +405,14 @@ DhtRunner::getId() const
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<crypto::PublicKey>
|
||||
DhtRunner::getPublicKey() const
|
||||
{
|
||||
if (auto dht = activeDht())
|
||||
return dht->getPublicKey();
|
||||
return {};
|
||||
}
|
||||
|
||||
InfoHash
|
||||
DhtRunner::getNodeId() const
|
||||
{
|
||||
@@ -410,8 +455,9 @@ DhtRunner::exportValues() const {
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLogger(const Logger& logger) {
|
||||
DhtRunner::setLogger(const Sp<Logger>& logger) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
logger_ = logger;
|
||||
if (dht_)
|
||||
dht_->setLogger(logger);
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
@@ -429,7 +475,6 @@ DhtRunner::setLoggers(LogMethod error, LogMethod warn, LogMethod debug) {
|
||||
void
|
||||
DhtRunner::setLogFilter(const InfoHash& f) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
activeDht()->setLogFilter(f);
|
||||
if (dht_)
|
||||
dht_->setLogFilter(f);
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
@@ -482,11 +527,38 @@ DhtRunner::getNodeInfo() const {
|
||||
info.node_id = dht->getNodeId();
|
||||
info.ipv4 = dht->getNodesStats(AF_INET);
|
||||
info.ipv6 = dht->getNodesStats(AF_INET6);
|
||||
if (auto sock = dht->getSocket()) {
|
||||
info.bound4 = sock->getBoundRef(AF_INET).getPort();
|
||||
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
|
||||
}
|
||||
}
|
||||
info.ongoing_ops = ongoing_ops;
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([cb = std::move(cb), this](SecureDht& dht){
|
||||
auto sinfo = std::make_shared<NodeInfo>();
|
||||
auto& info = *sinfo;
|
||||
info.id = dht.getId();
|
||||
info.node_id = dht.getNodeId();
|
||||
info.ipv4 = dht.getNodesStats(AF_INET);
|
||||
info.ipv6 = dht.getNodesStats(AF_INET6);
|
||||
if (auto sock = dht.getSocket()) {
|
||||
info.bound4 = sock->getBoundRef(AF_INET).getPort();
|
||||
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
|
||||
}
|
||||
info.ongoing_ops = ongoing_ops;
|
||||
cb(std::move(sinfo));
|
||||
opEnded();
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
std::vector<unsigned>
|
||||
DhtRunner::getNodeMessageStats(bool in) const
|
||||
{
|
||||
@@ -541,6 +613,18 @@ DhtRunner::getPublicAddressStr(sa_family_t af)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::getPublicAddress(std::function<void(std::vector<SockAddr>&&)> cb, sa_family_t af)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([cb = std::move(cb), this, af](SecureDht& dht){
|
||||
cb(dht.getPublicAddress(af));
|
||||
opEnded();
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::registerCertificate(std::shared_ptr<crypto::Certificate> cert) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
@@ -568,7 +652,7 @@ DhtRunner::loop_()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
auto s = getStatus();
|
||||
ops = (pending_ops_prio.empty() && (s == NodeStatus::Connected or (s == NodeStatus::Disconnected and not bootstraping))) ?
|
||||
ops = (pending_ops_prio.empty() && (s == NodeStatus::Connected or s == NodeStatus::Disconnected)) ?
|
||||
std::move(pending_ops) : std::move(pending_ops_prio);
|
||||
}
|
||||
while (not ops.empty()) {
|
||||
@@ -578,6 +662,7 @@ DhtRunner::loop_()
|
||||
|
||||
time_point wakeup {};
|
||||
decltype(rcv) received {};
|
||||
decltype(rcv) received_treated {};
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
// move to stack
|
||||
@@ -587,45 +672,46 @@ DhtRunner::loop_()
|
||||
// Discard old packets
|
||||
size_t dropped {0};
|
||||
if (not received.empty()) {
|
||||
auto now = clock::now();
|
||||
while (not received.empty() and now - received.front()->received > RX_QUEUE_MAX_DELAY) {
|
||||
received.pop();
|
||||
auto limit = clock::now() - net::RX_QUEUE_MAX_DELAY;
|
||||
auto it = received.begin();
|
||||
while (it != received.end() and it->received < limit) {
|
||||
it->data.clear();
|
||||
++it;
|
||||
dropped++;
|
||||
}
|
||||
received_treated.splice(received_treated.end(), received, received.begin(), it);
|
||||
}
|
||||
|
||||
// Handle packets
|
||||
if (not received.empty()) {
|
||||
while (not received.empty()) {
|
||||
auto& pck = received.front();
|
||||
if (clock::now() - pck->received > RX_QUEUE_MAX_DELAY)
|
||||
for (auto& pkt : received) {
|
||||
auto now = clock::now();
|
||||
if (now - pkt.received > net::RX_QUEUE_MAX_DELAY)
|
||||
dropped++;
|
||||
else
|
||||
wakeup = dht->periodic(pck->data.data(), pck->data.size(), std::move(pck->from));
|
||||
received.pop();
|
||||
wakeup = dht->periodic(pkt.data.data(), pkt.data.size(), std::move(pkt.from), now);
|
||||
pkt.data.clear();
|
||||
}
|
||||
received_treated.splice(received_treated.end(), std::move(received));
|
||||
} else {
|
||||
// Or just run the scheduler
|
||||
wakeup = dht->periodic(nullptr, 0, nullptr, 0);
|
||||
wakeup = dht->periodic(nullptr, 0, nullptr, 0, clock::now());
|
||||
}
|
||||
|
||||
if (dropped)
|
||||
std::cerr << "Dropped " << dropped << " packets with high delay" << std::endl;
|
||||
if (not received_treated.empty()) {
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
if (rcv_free.size() < net::RX_QUEUE_MAX_SIZE)
|
||||
rcv_free.splice(rcv_free.end(), std::move(received_treated));
|
||||
}
|
||||
|
||||
NodeStatus nstatus4 = dht->getStatus(AF_INET);
|
||||
NodeStatus nstatus6 = dht->getStatus(AF_INET6);
|
||||
if (dropped && logger_)
|
||||
logger_->e("[runner %p] Dropped %zu packets with high delay.", this, dropped);
|
||||
|
||||
NodeStatus nstatus4 = dht->updateStatus(AF_INET);
|
||||
NodeStatus nstatus6 = dht->updateStatus(AF_INET6);
|
||||
if (nstatus4 != status4 || nstatus6 != status6) {
|
||||
status4 = nstatus4;
|
||||
status6 = nstatus6;
|
||||
if (status4 == NodeStatus::Disconnected and status6 == NodeStatus::Disconnected) {
|
||||
// We have lost connection with the DHT. Try to recover using bootstrap nodes.
|
||||
std::unique_lock<std::mutex> lck(bootstrap_mtx);
|
||||
bootstrap_nodes = bootstrap_nodes_all;
|
||||
tryBootstrapContinuously();
|
||||
} else {
|
||||
std::unique_lock<std::mutex> lck(bootstrap_mtx);
|
||||
bootstrap_nodes.clear();
|
||||
}
|
||||
if (statusCb)
|
||||
statusCb(status4, status6);
|
||||
}
|
||||
@@ -636,11 +722,12 @@ 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));
|
||||
@@ -655,11 +742,12 @@ 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));
|
||||
@@ -671,11 +759,12 @@ 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_++;
|
||||
@@ -756,11 +845,12 @@ 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),
|
||||
@@ -774,11 +864,12 @@ 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);
|
||||
@@ -815,11 +906,12 @@ 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),
|
||||
@@ -845,11 +937,12 @@ 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),
|
||||
@@ -873,88 +966,58 @@ DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, Done
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::tryBootstrapContinuously()
|
||||
DhtRunner::putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
if (bootstrap_thread.joinable()) {
|
||||
if (bootstraping)
|
||||
return; // already running
|
||||
else
|
||||
bootstrap_thread.join();
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
bootstraping = true;
|
||||
bootstrap_thread = std::thread([this]() {
|
||||
auto next = clock::now();
|
||||
do {
|
||||
decltype(bootstrap_nodes) nodes;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(bootstrap_mtx);
|
||||
nodes = bootstrap_nodes;
|
||||
}
|
||||
|
||||
next += BOOTSTRAP_PERIOD;
|
||||
{
|
||||
std::mutex mtx;
|
||||
std::unique_lock<std::mutex> blck(mtx);
|
||||
unsigned ping_count(0);
|
||||
// Reverse: try last inserted bootstrap nodes first
|
||||
for (auto it = nodes.rbegin(); it != nodes.rend(); it++) {
|
||||
++ping_count;
|
||||
try {
|
||||
bootstrap(SockAddr::resolve(it->first, it->second), [&](bool) {
|
||||
if (running != State::Running)
|
||||
return;
|
||||
{
|
||||
std::unique_lock<std::mutex> blck(mtx);
|
||||
--ping_count;
|
||||
}
|
||||
bootstrap_cv.notify_all();
|
||||
});
|
||||
} catch (std::invalid_argument& e) {
|
||||
--ping_count;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
// wait at least until the next BOOTSTRAP_PERIOD
|
||||
bootstrap_cv.wait_until(blck, next, [&]() { return running != State::Running; });
|
||||
// wait for bootstrap requests to end.
|
||||
if (running != State::Running)
|
||||
bootstrap_cv.wait(blck, [&]() { return running != State::Running or ping_count == 0; });
|
||||
}
|
||||
// update state
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
bootstraping = running == State::Running and
|
||||
status4 == NodeStatus::Disconnected and
|
||||
status6 == NodeStatus::Disconnected;
|
||||
}
|
||||
} while (bootstraping);
|
||||
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, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::bootstrap(const std::string& host, const std::string& service)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(bootstrap_mtx);
|
||||
bootstrap_nodes_all.emplace_back(host, service);
|
||||
bootstrap_nodes.emplace_back(host, service);
|
||||
tryBootstrapContinuously();
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([host, service] (SecureDht& dht) mutable {
|
||||
dht.addBootstrap(host, service);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::bootstrap(const std::string& hostService)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(bootstrap_mtx);
|
||||
auto host_service = splitPort(hostService);
|
||||
bootstrap_nodes_all.emplace_back(host_service.first, host_service.second);
|
||||
bootstrap_nodes.emplace_back(std::move(host_service.first), std::move(host_service.second));
|
||||
tryBootstrapContinuously();
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([host_service = splitPort(hostService)] (SecureDht& dht) mutable {
|
||||
dht.addBootstrap(host_service.first, host_service.second);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::clearBootstrap()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(bootstrap_mtx);
|
||||
bootstrap_nodes_all.clear();
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([] (SecureDht& dht) mutable {
|
||||
dht.clearBootstrap();
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -990,11 +1053,12 @@ 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));
|
||||
@@ -1005,9 +1069,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);
|
||||
});
|
||||
@@ -1017,9 +1081,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);
|
||||
@@ -1033,17 +1097,22 @@ DhtRunner::connectivityChanged()
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht& dht) {
|
||||
dht.connectivityChanged();
|
||||
#ifdef OPENDHT_PEER_DISCOVERY
|
||||
if (peerDiscovery_)
|
||||
peerDiscovery_->connectivityChanged();
|
||||
#endif
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
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){
|
||||
@@ -1115,11 +1184,11 @@ DhtRunner::enableProxy(bool proxify)
|
||||
},
|
||||
config_.proxy_server, config_.push_node_id, logger_)
|
||||
);
|
||||
dht_via_proxy_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht_via_proxy), config_.dht_config));
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
if (not config_.push_token.empty())
|
||||
dht_via_proxy_->setPushNotificationToken(config_.push_token);
|
||||
dht_via_proxy->setPushNotificationToken(config_.push_token);
|
||||
#endif
|
||||
dht_via_proxy_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_));
|
||||
// add current listeners
|
||||
for (auto& l: listeners_)
|
||||
l.second.tokenProxyDht = dht_via_proxy_->listen(l.second.hash, l.second.gcb, l.second.f, l.second.w);
|
||||
|
||||
+599
-85
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -20,17 +20,35 @@
|
||||
#include "log_enable.h"
|
||||
#include "crypto.h"
|
||||
#include "base64.h"
|
||||
#include "compat/os_cert.h"
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <restinio/impl/tls_socket.hpp>
|
||||
#include <http_parser.h>
|
||||
#include <json/json.h>
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
#define MAXAGE_SEC (14*24*60*60)
|
||||
#define JITTER_SEC (60)
|
||||
#define OCSP_MAX_RESPONSE_SIZE (20480)
|
||||
#ifdef _WIN32
|
||||
#define timegm _mkgmtime
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
namespace http {
|
||||
|
||||
constexpr char HTTP_HEADER_CONTENT_TYPE_JSON[] = "application/json";
|
||||
constexpr char HTTP_HEADER_DELIM[] = "\r\n\r\n";
|
||||
constexpr const char HTTP_HEADER_CONTENT_TYPE_JSON[] = "application/json";
|
||||
constexpr const char HTTP_HEADER_DELIM[] = "\r\n\r\n";
|
||||
constexpr const char HTTP_PROTOCOL[] = "http://";
|
||||
constexpr const char HTTPS_PROTOCOL[] = "https://";
|
||||
constexpr const char ORIGIN_PROTOCOL[] = "//";
|
||||
constexpr unsigned MAX_REDIRECTS {5};
|
||||
|
||||
Url::Url(const std::string& url): url(url)
|
||||
{
|
||||
@@ -41,7 +59,6 @@ Url::Url(const std::string& url): url(url)
|
||||
addr_begin = proto_end + 3;
|
||||
if (url.substr(0, proto_end) == "https"){
|
||||
protocol = "https";
|
||||
service = protocol;
|
||||
}
|
||||
}
|
||||
// host and service
|
||||
@@ -67,20 +84,63 @@ Url::Url(const std::string& url): url(url)
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
Url::toString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
if (not protocol.empty()) {
|
||||
ss << protocol << "://";
|
||||
}
|
||||
ss << host;
|
||||
if (not service.empty()) {
|
||||
ss << ':' << service;
|
||||
}
|
||||
ss << target;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// connection
|
||||
|
||||
std::atomic_uint Connection::ids_ {1};
|
||||
|
||||
std::shared_ptr<asio::ssl::context>
|
||||
newTlsClientContext(const std::shared_ptr<dht::Logger>& logger)
|
||||
{
|
||||
auto ctx = std::make_shared<asio::ssl::context>(asio::ssl::context::tls_client);
|
||||
ctx->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
|
||||
|
||||
if (char* path = getenv("CA_ROOT_FILE")) {
|
||||
if (logger)
|
||||
logger->d("Using CA file: %s", path);
|
||||
ctx->load_verify_file(path);
|
||||
} else if (char* path = getenv("CA_ROOT_PATH")) {
|
||||
if (logger)
|
||||
logger->d("Using CA path: %s", path);
|
||||
ctx->add_verify_path(path);
|
||||
} else {
|
||||
#ifdef __ANDROID__
|
||||
if (logger)
|
||||
logger->d("Using CA path: /system/etc/security/cacerts");
|
||||
ctx->add_verify_path("/system/etc/security/cacerts");
|
||||
#elif defined(WIN32) || defined(TARGET_OS_OSX)
|
||||
PEMCache::instance(logger).fillX509Store(ctx->native_handle());
|
||||
#else
|
||||
if (logger)
|
||||
logger->d("Using default CA path");
|
||||
ctx->set_default_verify_paths();
|
||||
#endif
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
Connection::Connection(asio::io_context& ctx, const bool ssl, std::shared_ptr<dht::Logger> l)
|
||||
: id_(Connection::ids_++), ctx_(ctx), istream_(&read_buf_), logger_(l)
|
||||
{
|
||||
if (ssl){
|
||||
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
|
||||
ssl_ctx_->set_default_verify_paths();
|
||||
ssl_ctx_->set_verify_mode(asio::ssl::verify_none);
|
||||
if (ssl) {
|
||||
ssl_ctx_ = newTlsClientContext(l);
|
||||
ssl_socket_ = std::make_unique<ssl_socket_t>(ctx_, ssl_ctx_);
|
||||
if (logger_)
|
||||
logger_->d("[connection:%i] start https session", id_);
|
||||
logger_->d("[connection:%i] start https session with system CA", id_);
|
||||
}
|
||||
else {
|
||||
socket_ = std::make_unique<socket_t>(ctx);
|
||||
@@ -93,16 +153,20 @@ Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::crypto::Certi
|
||||
const dht::crypto::Identity& identity, std::shared_ptr<dht::Logger> l)
|
||||
: id_(Connection::ids_++), ctx_(ctx), istream_(&read_buf_), logger_(l)
|
||||
{
|
||||
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
|
||||
ssl_ctx_->set_default_verify_paths();
|
||||
asio::error_code ec;
|
||||
if (server_ca){
|
||||
if (server_ca) {
|
||||
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::tls_client);
|
||||
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
|
||||
auto ca = server_ca->toString(false/*chain*/);
|
||||
ssl_ctx_->add_certificate_authority(asio::const_buffer{ca.data(), ca.size()}, ec);
|
||||
if (ec)
|
||||
throw std::runtime_error("Error adding certificate authority: " + ec.message());
|
||||
else if (logger_)
|
||||
logger_->d("[connection:%i] certficate authority %s", id_, server_ca->getUID().c_str());
|
||||
logger_->d("[connection:%i] start https with custom CA %s", id_, server_ca->getUID().c_str());
|
||||
} else {
|
||||
ssl_ctx_ = newTlsClientContext(l);
|
||||
if (logger_)
|
||||
logger_->d("[connection:%i] start https session with system CA", id_);
|
||||
}
|
||||
if (identity.first){
|
||||
auto key = identity.first->serialize();
|
||||
@@ -119,7 +183,6 @@ Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::crypto::Certi
|
||||
else if (logger_)
|
||||
logger_->d("[connection:%i] client certificate %s", id_, identity.second->getUID().c_str());
|
||||
}
|
||||
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
|
||||
ssl_socket_ = std::make_unique<ssl_socket_t>(ctx_, ssl_ctx_);
|
||||
}
|
||||
|
||||
@@ -130,6 +193,7 @@ Connection::~Connection() {
|
||||
void
|
||||
Connection::close()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
asio::error_code ec;
|
||||
if (ssl_socket_) {
|
||||
if (ssl_socket_->is_open())
|
||||
@@ -157,29 +221,312 @@ Connection::is_ssl() const
|
||||
return ssl_ctx_ ? true : false;
|
||||
}
|
||||
|
||||
void
|
||||
Connection::set_ssl_verification(const asio::ip::tcp::endpoint& endpoint, const asio::ssl::verify_mode verify_mode)
|
||||
static time_t
|
||||
parse_ocsp_time(ASN1_GENERALIZEDTIME* gt)
|
||||
{
|
||||
if (ssl_socket_ and verify_mode != asio::ssl::verify_none) {
|
||||
struct tm tm;
|
||||
time_t rv = -1;
|
||||
|
||||
if (gt == nullptr)
|
||||
return -1;
|
||||
// RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME
|
||||
if (ASN1_time_parse((const char*)gt->data, gt->length, &tm, V_ASN1_GENERALIZEDTIME) == -1)
|
||||
return -1;
|
||||
if ((rv = timegm(&tm)) == -1)
|
||||
return -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline X509*
|
||||
cert_from_chain(STACK_OF(X509)* fullchain)
|
||||
{
|
||||
return sk_X509_value(fullchain, 0);
|
||||
}
|
||||
|
||||
static X509*
|
||||
issuer_from_chain(STACK_OF(X509)* fullchain)
|
||||
{
|
||||
X509 *cert, *issuer;
|
||||
X509_NAME *issuer_name;
|
||||
|
||||
cert = cert_from_chain(fullchain);
|
||||
if ((issuer_name = X509_get_issuer_name(cert)) == nullptr)
|
||||
return nullptr;
|
||||
|
||||
issuer = X509_find_by_subject(fullchain, issuer_name);
|
||||
return issuer;
|
||||
}
|
||||
|
||||
using OscpRequestPtr = std::unique_ptr<OCSP_REQUEST, decltype(&OCSP_REQUEST_free)>;
|
||||
struct OscpRequestInfo {
|
||||
OscpRequestPtr req {nullptr, &OCSP_REQUEST_free};
|
||||
std::string data;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
static std::unique_ptr<OscpRequestInfo>
|
||||
ocspRequestFromCert(STACK_OF(X509)* fullchain, const std::shared_ptr<Logger>& logger, bool nonce = false)
|
||||
{
|
||||
if (fullchain == nullptr)
|
||||
return {};
|
||||
|
||||
if (sk_X509_num(fullchain) <= 1) {
|
||||
if (logger)
|
||||
logger->e("Cert does not contain a cert chain");
|
||||
return {};
|
||||
}
|
||||
X509* cert = cert_from_chain(fullchain);
|
||||
if (cert == nullptr) {
|
||||
if (logger)
|
||||
logger->e("No certificate found");
|
||||
return {};
|
||||
}
|
||||
X509* issuer = issuer_from_chain(fullchain);
|
||||
if (issuer == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to find issuer for cert");
|
||||
return {};
|
||||
}
|
||||
|
||||
auto urls = X509_get1_ocsp(cert);
|
||||
if (urls == nullptr || sk_OPENSSL_STRING_num(urls) <= 0) {
|
||||
if (logger)
|
||||
logger->e("Certificate contains no OCSP url");
|
||||
return {};
|
||||
}
|
||||
auto url = sk_OPENSSL_STRING_value(urls, 0);
|
||||
if (url == nullptr)
|
||||
return {};
|
||||
|
||||
auto request = std::make_unique<OscpRequestInfo>();
|
||||
request->req = OscpRequestPtr(OCSP_REQUEST_new(), &OCSP_REQUEST_free);
|
||||
request->url = url;
|
||||
X509_email_free(urls);
|
||||
|
||||
OCSP_CERTID* id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
|
||||
if (id == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to get certificate id from cert");
|
||||
return {};
|
||||
}
|
||||
if (OCSP_request_add0_id(request->req.get(), id) == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to add certificate id to request");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (nonce)
|
||||
OCSP_request_add1_nonce(request->req.get(), nullptr, -1);
|
||||
|
||||
int size;
|
||||
uint8_t* data {nullptr};
|
||||
if ((size = i2d_OCSP_REQUEST(request->req.get(), &data)) <= 0) {
|
||||
if (logger)
|
||||
logger->e("Unable to encode ocsp request");
|
||||
return {};
|
||||
}
|
||||
if (data == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to allocte memory");
|
||||
return {};
|
||||
}
|
||||
request->data = std::string((char*)data, (char*)data+size);
|
||||
free(data);
|
||||
return request;
|
||||
}
|
||||
|
||||
bool
|
||||
ocspValidateResponse(const OscpRequestInfo& info, STACK_OF(X509)* fullchain, const std::string& response, X509_STORE *store, const std::shared_ptr<Logger>& logger)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *revtime = nullptr, *thisupd = nullptr, *nextupd = nullptr;
|
||||
const uint8_t* p = (const uint8_t*)response.data();
|
||||
int status, cert_status=0, crl_reason=0;
|
||||
time_t now, rev_t = -1, this_t, next_t;
|
||||
|
||||
X509* cert = cert_from_chain(fullchain);
|
||||
if (cert == nullptr) {
|
||||
if (logger)
|
||||
logger->e("No certificate found");
|
||||
return false;
|
||||
}
|
||||
X509* issuer = issuer_from_chain(fullchain);
|
||||
if (issuer == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to find issuer for cert");
|
||||
return false;
|
||||
}
|
||||
|
||||
OCSP_CERTID *cidr;
|
||||
if ((cidr = OCSP_cert_to_id(nullptr, cert, issuer)) == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Unable to get issuer cert/CID");
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<OCSP_CERTID, decltype(&OCSP_CERTID_free)> cid(cidr, &OCSP_CERTID_free);
|
||||
|
||||
OCSP_RESPONSE *r;
|
||||
if ((r = d2i_OCSP_RESPONSE(nullptr, &p, response.size())) == nullptr) {
|
||||
if (logger)
|
||||
logger->e("OCSP response unserializable");
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<OCSP_RESPONSE, decltype(&OCSP_RESPONSE_free)> resp(r, &OCSP_RESPONSE_free);
|
||||
|
||||
OCSP_BASICRESP *brespr;
|
||||
if ((brespr = OCSP_response_get1_basic(resp.get())) == nullptr) {
|
||||
if (logger)
|
||||
logger->e("Failed to load OCSP response");
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<OCSP_BASICRESP, decltype(&OCSP_BASICRESP_free)> bresp(brespr, &OCSP_BASICRESP_free);
|
||||
|
||||
if (OCSP_basic_verify(bresp.get(), fullchain, store, OCSP_TRUSTOTHER) != 1) {
|
||||
if (logger)
|
||||
logger->w("OCSP verify failed");
|
||||
return false;
|
||||
}
|
||||
printf("OCSP response signature validated\n");
|
||||
|
||||
status = OCSP_response_status(resp.get());
|
||||
if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
if (logger)
|
||||
logger->w("OCSP Failure: code %d (%s)", status, OCSP_response_status_str(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the nonce if we sent one
|
||||
if (OCSP_check_nonce(info.req.get(), bresp.get()) <= 0) {
|
||||
if (logger)
|
||||
logger->w("No OCSP nonce, or mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OCSP_resp_find_status(bresp.get(), cid.get(), &cert_status, &crl_reason,
|
||||
&revtime, &thisupd, &nextupd) != 1) {
|
||||
if (logger)
|
||||
logger->w("OCSP verify failed: no result for cert");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (revtime && (rev_t = parse_ocsp_time(revtime)) == -1) {
|
||||
if (logger)
|
||||
logger->w("Unable to parse revocation time in OCSP reply");
|
||||
return false;
|
||||
}
|
||||
// Belt and suspenders, Treat it as revoked if there is either
|
||||
// a revocation time, or status revoked.
|
||||
if (rev_t != -1 || cert_status == V_OCSP_CERTSTATUS_REVOKED) {
|
||||
if (logger)
|
||||
logger->w("Invalid OCSP reply: certificate is revoked");
|
||||
if (rev_t != -1) {
|
||||
if (logger)
|
||||
logger->w("Certificate revoked at: %s", ctime(&rev_t));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if ((this_t = parse_ocsp_time(thisupd)) == -1) {
|
||||
if (logger)
|
||||
logger->w("unable to parse this update time in OCSP reply");
|
||||
return false;
|
||||
}
|
||||
if ((next_t = parse_ocsp_time(nextupd)) == -1) {
|
||||
if (logger)
|
||||
logger->w("unable to parse next update time in OCSP reply");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't allow this update to precede next update
|
||||
if (this_t >= next_t) {
|
||||
if (logger)
|
||||
logger->w("Invalid OCSP reply: this update >= next update");
|
||||
return false;
|
||||
}
|
||||
|
||||
now = time(nullptr);
|
||||
// Check that this update is not more than JITTER seconds in the future.
|
||||
if (this_t > now + JITTER_SEC) {
|
||||
if (logger)
|
||||
logger->e("Invalid OCSP reply: this update is in the future (%s)", ctime(&this_t));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that this update is not more than MAXSEC in the past.
|
||||
if (this_t < now - MAXAGE_SEC) {
|
||||
if (logger)
|
||||
logger->e("Invalid OCSP reply: this update is too old (%s)", ctime(&this_t));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that next update is still valid
|
||||
if (next_t < now - JITTER_SEC) {
|
||||
if (logger)
|
||||
logger->w("Invalid OCSP reply: reply has expired (%s)", ctime(&next_t));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (logger) {
|
||||
logger->d("OCSP response validated");
|
||||
logger->d(" This Update: %s", ctime(&this_t));
|
||||
logger->d(" Next Update: %s", ctime(&next_t));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Connection::set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (ssl_socket_) {
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
SSL_set_tlsext_host_name(ssl_socket_->asio_ssl_stream().native_handle(), hostname.c_str());
|
||||
ssl_socket_->asio_ssl_stream().set_verify_mode(verify_mode);
|
||||
ssl_socket_->asio_ssl_stream().set_verify_callback([
|
||||
id = id_,
|
||||
logger = logger_,
|
||||
hostname = endpoint.address().to_string()
|
||||
] (bool preverified, asio::ssl::verify_context& ctx) -> bool {
|
||||
if (logger)
|
||||
logger->d("[connection:%i] verify %s compliance to RFC 2818", id, hostname.c_str());
|
||||
if (preverified)
|
||||
return preverified;
|
||||
// starts from CA and goes down the presented chain
|
||||
auto verifier = asio::ssl::rfc2818_verification(hostname);
|
||||
bool verified = verifier(preverified, ctx);
|
||||
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
|
||||
if (verified != 0 /*X509_V_OK*/ and logger)
|
||||
logger->e("[http::connection:%i] ssl verification error=%i", id, verify_ec);
|
||||
return verified;
|
||||
}
|
||||
);
|
||||
if (verify_mode != asio::ssl::verify_none) {
|
||||
ssl_socket_->asio_ssl_stream().set_verify_callback([
|
||||
id = id_, logger = logger_, hostname, checkOcsp = checkOcsp_
|
||||
] (bool preverified, asio::ssl::verify_context& ctx) -> bool {
|
||||
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
|
||||
if (logger) {
|
||||
char subject_name[1024];
|
||||
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 1024);
|
||||
logger->d("[connection:%i] verify %s compliance to RFC 2818:\n%s", id, hostname.c_str(), subject_name);
|
||||
}
|
||||
|
||||
// starts from CA and goes down the presented chain
|
||||
auto verifier = asio::ssl::rfc2818_verification(hostname);
|
||||
bool verified = verifier(preverified, ctx);
|
||||
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
|
||||
if (verify_ec != 0 /*X509_V_OK*/ and logger)
|
||||
logger->e("[http::connection:%i] ssl verification error=%i %d", id, verify_ec, verified);
|
||||
if (verified and checkOcsp) {
|
||||
std::unique_ptr<stack_st_X509, void(*)(stack_st_X509*)> chain(
|
||||
X509_STORE_CTX_get1_chain(ctx.native_handle()),
|
||||
[](stack_st_X509* c){ sk_X509_pop_free(c, X509_free); });
|
||||
if (auto ocspInfo = ocspRequestFromCert(chain.get(), logger)) {
|
||||
if (logger)
|
||||
logger->w("[http::connection:%i] TLS OCSP server: %s, request size: %zu", id, ocspInfo->url.c_str(), ocspInfo->data.size());
|
||||
bool ocspVerified = false;
|
||||
asio::io_context io_ctx;
|
||||
auto ocspReq = std::make_shared<Request>(io_ctx, ocspInfo->url, [&](const Response& ocspResp){
|
||||
if (ocspResp.status_code == 200) {
|
||||
ocspVerified = ocspValidateResponse(*ocspInfo, chain.get(), ocspResp.body, X509_STORE_CTX_get0_store(ctx.native_handle()), logger);
|
||||
} else {
|
||||
if (logger)
|
||||
logger->w("[http::connection:%i] TLS OCSP check error", id);
|
||||
}
|
||||
}, logger);
|
||||
ocspReq->set_method(restinio::http_method_post());
|
||||
ocspReq->set_header_field(restinio::http_field_t::content_type, "application/ocsp-request");
|
||||
ocspReq->set_body(ocspInfo->data);
|
||||
ocspReq->send();
|
||||
io_ctx.run();
|
||||
if (not ocspVerified)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return verified;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +539,7 @@ Connection::input()
|
||||
std::string
|
||||
Connection::read_bytes(size_t bytes)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (bytes == 0)
|
||||
bytes = read_buf_.in_avail();
|
||||
std::string content;
|
||||
@@ -212,17 +560,70 @@ Connection::read_until(const char delim)
|
||||
void
|
||||
Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb cb)
|
||||
{
|
||||
if (ssl_socket_)
|
||||
asio::async_connect(ssl_socket_->lowest_layer(), std::move(endpoints), wrapCallabck(std::move(cb)));
|
||||
else if (socket_)
|
||||
asio::async_connect(*socket_, std::move(endpoints), wrapCallabck(std::move(cb)));
|
||||
else if (cb)
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!ssl_socket_ && !socket_) {
|
||||
cb(asio::error::operation_aborted, {});
|
||||
return;
|
||||
}
|
||||
auto& base = ssl_socket_? ssl_socket_->lowest_layer() : *socket_;
|
||||
|
||||
ConnectHandlerCb wcb = [&base, cb=std::move(cb)](const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint) {
|
||||
if (!ec) {
|
||||
auto socket = base.native_handle();
|
||||
// Once connected, set a keep alive on the TCP socket with 30 seconds delay
|
||||
// This will generate broken pipes as soon as possible.
|
||||
// Note this needs to be done once connected to have a valid native_handle()
|
||||
uint32_t start = 30;
|
||||
uint32_t interval = 30;
|
||||
uint32_t cnt = 1;
|
||||
#ifdef _WIN32
|
||||
std::string val = "1";
|
||||
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, val.c_str(), sizeof(val));
|
||||
|
||||
// TCP_KEEPIDLE and TCP_KEEPINTVL are available since Win 10 version 1709
|
||||
// TCP_KEEPCNT since Win 10 version 1703
|
||||
#ifdef TCP_KEEPIDLE
|
||||
std::string start_str = std::to_string(start);
|
||||
setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE,
|
||||
start_str.c_str(), sizeof(start_str));
|
||||
#endif
|
||||
#ifdef TCP_KEEPINTVL
|
||||
std::string interval_str = std::to_string(interval);
|
||||
setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL,
|
||||
interval_str.c_str(), sizeof(interval_str));
|
||||
#endif
|
||||
#ifdef TCP_KEEPCNT
|
||||
std::string cnt_str = std::to_string(cnt);
|
||||
setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT,
|
||||
cnt_str.c_str(), sizeof(cnt_str));
|
||||
#endif
|
||||
#else
|
||||
uint32_t val = 1;
|
||||
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(uint32_t));
|
||||
#ifdef __APPLE__
|
||||
// Apple devices only have one parameter
|
||||
setsockopt(socket, IPPROTO_TCP, TCP_KEEPALIVE, &start, sizeof(uint32_t));
|
||||
#else
|
||||
// Linux based systems
|
||||
setsockopt(socket, SOL_TCP, TCP_KEEPIDLE, &start, sizeof(uint32_t));
|
||||
setsockopt(socket, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(uint32_t));
|
||||
setsockopt(socket, SOL_TCP, TCP_KEEPCNT, &cnt, sizeof(uint32_t));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
if (cb)
|
||||
cb(ec, endpoint);
|
||||
};
|
||||
if (ssl_socket_)
|
||||
asio::async_connect(ssl_socket_->lowest_layer(), std::move(endpoints), wrapCallabck(std::move(wcb)));
|
||||
else
|
||||
asio::async_connect(*socket_, std::move(endpoints), wrapCallabck(std::move(wcb)));
|
||||
}
|
||||
|
||||
void
|
||||
Connection::async_handshake(HandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (ssl_socket_) {
|
||||
std::weak_ptr<Connection> wthis = shared_from_this();
|
||||
ssl_socket_->async_handshake(asio::ssl::stream<asio::ip::tcp::socket>::client,
|
||||
@@ -236,9 +637,11 @@ Connection::async_handshake(HandlerCb cb)
|
||||
if (this_.logger_) {
|
||||
if (verify_ec == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT /*18*/
|
||||
|| verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/)
|
||||
this_.logger_->d("[connection:%i] allow self-signed certificate in handshake", this_.id_);
|
||||
this_.logger_->d("[connection:%i] self-signed certificate in handshake: %i", this_.id_, verify_ec);
|
||||
else if (verify_ec != X509_V_OK)
|
||||
this_.logger_->e("[connection:%i] verify handshake error: %i", this_.id_, verify_ec);
|
||||
else
|
||||
this_.logger_->w("[connection:%i] verify handshake success", this_.id_);
|
||||
}
|
||||
}
|
||||
if (cb)
|
||||
@@ -254,44 +657,61 @@ Connection::async_handshake(HandlerCb cb)
|
||||
void
|
||||
Connection::async_write(BytesHandlerCb cb)
|
||||
{
|
||||
if (!is_open()) return;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_write(*ssl_socket_, write_buf_, wrapCallabck(std::move(cb)));
|
||||
else if (socket_) asio::async_write(*socket_, write_buf_, wrapCallabck(std::move(cb)));
|
||||
else if (cb) cb(asio::error::operation_aborted, 0);
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
Connection::async_read_until(const char* delim, BytesHandlerCb cb)
|
||||
{
|
||||
if (!is_open()) return;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
|
||||
else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
|
||||
else if (cb) cb(asio::error::operation_aborted, 0);
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
Connection::async_read_until(char delim, BytesHandlerCb cb)
|
||||
{
|
||||
if (!is_open()) return;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
|
||||
else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallabck(std::move(cb)));
|
||||
else if (cb) cb(asio::error::operation_aborted, 0);
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
Connection::async_read(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
if (!is_open()) return;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read(*ssl_socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallabck(std::move(cb)));
|
||||
else if (socket_) asio::async_read(*socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallabck(std::move(cb)));
|
||||
else if (cb) cb(asio::error::operation_aborted, 0);
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
Connection::async_read_some(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) cb(asio::error::operation_aborted, 0);
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
auto buf = read_buf_.prepare(bytes);
|
||||
@@ -333,7 +753,7 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
|
||||
Resolver::Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger)
|
||||
: url_(url), resolver_(ctx), destroyed_(std::make_shared<bool>(false)), logger_(logger)
|
||||
{
|
||||
resolve(url_.host, url_.service);
|
||||
resolve(url_.host, url_.service.empty() ? url_.protocol : url_.service);
|
||||
}
|
||||
|
||||
Resolver::Resolver(asio::io_context& ctx, const std::string& host, const std::string& service,
|
||||
@@ -343,7 +763,7 @@ Resolver::Resolver(asio::io_context& ctx, const std::string& host, const std::st
|
||||
url_.host = host;
|
||||
url_.service = service;
|
||||
url_.protocol = (ssl ? "https" : "http");
|
||||
resolve(url_.host, url_.service);
|
||||
resolve(url_.host, url_.service.empty() ? url_.protocol : url_.service);
|
||||
}
|
||||
|
||||
Resolver::Resolver(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint> endpoints, const bool ssl,
|
||||
@@ -406,13 +826,12 @@ void
|
||||
Resolver::resolve(const std::string& host, const std::string& service)
|
||||
{
|
||||
asio::ip::tcp::resolver::query query_(host, service);
|
||||
|
||||
resolver_.async_resolve(query_, [this, host, service, destroyed = destroyed_]
|
||||
(const asio::error_code& ec, asio::ip::tcp::resolver::results_type endpoints)
|
||||
{
|
||||
if (ec == asio::error::operation_aborted or *destroyed)
|
||||
return;
|
||||
if (logger_){
|
||||
if (logger_) {
|
||||
if (ec)
|
||||
logger_->e("[http:client] [resolver] error for %s:%s: %s",
|
||||
host.c_str(), service.c_str(), ec.message().c_str());
|
||||
@@ -460,7 +879,29 @@ Request::Request(asio::io_context& ctx, const std::string& url, const Json::Valu
|
||||
logger_->e("[http:request:%i] can't parse response to json", id_, err.c_str());
|
||||
}
|
||||
if (jsoncb)
|
||||
jsoncb(std::move(json), response.status_code);
|
||||
jsoncb(std::move(json), response);
|
||||
});
|
||||
}
|
||||
|
||||
Request::Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb, std::shared_ptr<dht::Logger> logger)
|
||||
: logger_(std::move(logger)), id_(Request::ids_++), ctx_(ctx),
|
||||
resolver_(std::make_shared<Resolver>(ctx, url, logger))
|
||||
{
|
||||
init_default_headers();
|
||||
set_header_field(restinio::http_field_t::accept, HTTP_HEADER_CONTENT_TYPE_JSON);
|
||||
Json::StreamWriterBuilder wbuilder;
|
||||
set_method(restinio::http_method_get());
|
||||
add_on_done_callback([this, jsoncb](const Response& response) {
|
||||
Json::Value json;
|
||||
if (response.status_code != 0) {
|
||||
std::string err;
|
||||
Json::CharReaderBuilder rbuilder;
|
||||
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
|
||||
if (!reader->parse(response.body.data(), response.body.data() + response.body.size(), &json, &err) and logger_)
|
||||
logger_->e("[http:request:%i] can't parse response to json", id_, err.c_str());
|
||||
}
|
||||
if (jsoncb)
|
||||
jsoncb(std::move(json), response);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -504,7 +945,7 @@ Request::Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, cons
|
||||
: logger_(resolver->getLogger()), id_(Request::ids_++), ctx_(ctx), family_(family), resolver_(resolver)
|
||||
{
|
||||
set_header_field(restinio::http_field_t::host, get_url().host + ":" + get_url().service);
|
||||
set_target(target);
|
||||
set_target(Url(target).target);
|
||||
}
|
||||
|
||||
Request::~Request()
|
||||
@@ -567,7 +1008,7 @@ Request::set_method(restinio::http_method_id_t method) {
|
||||
|
||||
void
|
||||
Request::set_target(std::string target) {
|
||||
header_.request_target(std::move(target));
|
||||
header_.request_target(target.empty() ? "/" : std::move(target));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -672,6 +1113,8 @@ Request::notify_state_change(State state) {
|
||||
void
|
||||
Request::init_parser()
|
||||
{
|
||||
response_.request = shared_from_this();
|
||||
|
||||
if (!parser_)
|
||||
parser_ = std::make_unique<http_parser>();
|
||||
http_parser_init(parser_.get(), HTTP_RESPONSE);
|
||||
@@ -737,23 +1180,26 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
|
||||
eps.append(endpoint.address().to_string() + ":" + std::to_string(endpoint.port()) + " ");
|
||||
logger_->d("[http:request:%i] connect begin: %s", id_, eps.c_str());
|
||||
}
|
||||
if (get_url().protocol == "https"){
|
||||
if (server_ca_)
|
||||
bool isHttps = get_url().protocol == "https";
|
||||
if (isHttps) {
|
||||
if (server_ca_ or client_identity_.first)
|
||||
conn_ = std::make_shared<Connection>(ctx_, server_ca_, client_identity_, logger_);
|
||||
else
|
||||
conn_ = std::make_shared<Connection>(ctx_, true/*ssl*/, logger_);
|
||||
conn_->set_ssl_verification(get_url().host, asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
|
||||
}
|
||||
else
|
||||
conn_ = std::make_shared<Connection>(ctx_, false/*ssl*/, logger_);
|
||||
|
||||
// try to connect to any until one works
|
||||
std::weak_ptr<Request> wthis = shared_from_this();
|
||||
conn_->async_connect(std::move(endpoints), [wthis, cb]
|
||||
conn_->async_connect(std::move(endpoints), [wthis, cb, isHttps]
|
||||
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
|
||||
auto sthis = wthis.lock();
|
||||
if (not sthis)
|
||||
return;
|
||||
auto& this_ = *sthis;
|
||||
std::lock_guard<std::mutex> lock(this_.mutex_);
|
||||
if (ec == asio::error::operation_aborted){
|
||||
this_.terminate(ec);
|
||||
return;
|
||||
@@ -762,23 +1208,16 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
|
||||
if (this_.logger_)
|
||||
this_.logger_->e("[http:request:%i] connect failed with all endpoints: %s", this_.id_, ec.message().c_str());
|
||||
} else {
|
||||
// if (this_.logger_)
|
||||
// this_.logger_->d("[http:request:%i] connect success", this_.id_);
|
||||
|
||||
const auto& url = this_.get_url();
|
||||
auto port = endpoint.port();
|
||||
if ((url.protocol == "http" && port == (in_port_t)80)
|
||||
|| (url.protocol == "https" && port == (in_port_t)443))
|
||||
if ((!isHttps && port == (in_port_t)80)
|
||||
|| (isHttps && port == (in_port_t)443))
|
||||
this_.set_header_field(restinio::http_field_t::host, url.host);
|
||||
else
|
||||
this_.set_header_field(restinio::http_field_t::host, url.host + ":" + std::to_string(port));
|
||||
|
||||
if (url.protocol == "https") {
|
||||
if (this_.server_ca_)
|
||||
this_.conn_->set_ssl_verification(endpoint, asio::ssl::verify_peer
|
||||
| asio::ssl::verify_fail_if_no_peer_cert);
|
||||
|
||||
if (this_.conn_ and this_.conn_->is_open() and this_.conn_->is_ssl()){
|
||||
if (isHttps) {
|
||||
if (this_.conn_ and this_.conn_->is_open() and this_.conn_->is_ssl()) {
|
||||
this_.conn_->async_handshake([id = this_.id_, cb, logger = this_.logger_](const asio::error_code& ec){
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
@@ -810,6 +1249,7 @@ Request::send()
|
||||
std::vector<asio::ip::tcp::endpoint> endpoints) {
|
||||
if (auto sthis = wthis.lock()) {
|
||||
auto& this_ = *sthis;
|
||||
std::lock_guard<std::mutex> lock(this_.mutex_);
|
||||
if (ec){
|
||||
if (this_.logger_)
|
||||
this_.logger_->e("[http:request:%i] resolve error: %s", this_.id_, ec.message().c_str());
|
||||
@@ -865,9 +1305,11 @@ Request::terminate(const asio::error_code& ec)
|
||||
return;
|
||||
|
||||
response_.aborted = ec == asio::error::operation_aborted;
|
||||
if (ec == asio::error::basic_errors::broken_pipe)
|
||||
response_.status_code = 0U; // Avoid to give a successful answer (happen with a broken pipe, takes the last status)
|
||||
|
||||
if (logger_) {
|
||||
if (ec and ec != asio::error::eof and ec != asio::error::operation_aborted)
|
||||
if (ec and ec != asio::error::eof and !response_.aborted)
|
||||
logger_->e("[http:request:%i] end with error: %s", id_, ec.message().c_str());
|
||||
else
|
||||
logger_->d("[http:request:%i] done with status code %u", id_, response_.status_code);
|
||||
@@ -882,6 +1324,7 @@ Request::terminate(const asio::error_code& ec)
|
||||
void
|
||||
Request::handle_request(const asio::error_code& ec)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (ec and ec != asio::error::eof){
|
||||
terminate(ec);
|
||||
return;
|
||||
@@ -903,8 +1346,9 @@ Request::handle_request(const asio::error_code& ec)
|
||||
}
|
||||
|
||||
void
|
||||
Request::handle_response(const asio::error_code& ec, size_t n_bytes)
|
||||
Request::handle_response(const asio::error_code& ec, size_t /* n_bytes */)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (ec && ec != asio::error::eof){
|
||||
terminate(ec);
|
||||
return;
|
||||
@@ -948,20 +1392,90 @@ void
|
||||
Request::onHeadersComplete() {
|
||||
notify_state_change(State::HEADER_RECEIVED);
|
||||
|
||||
auto expect_it = headers_.find(restinio::http_field_t::expect);
|
||||
if (expect_it != headers_.end() and (expect_it->second == "100-continue") and response_.status_code != 200){
|
||||
notify_state_change(State::SENDING);
|
||||
request_.append(body_);
|
||||
std::ostream request_stream(&conn_->input());
|
||||
request_stream << body_ << "\r\n";
|
||||
std::weak_ptr<Request> wthis = shared_from_this();
|
||||
conn_->async_write([wthis](const asio::error_code& ec, size_t) {
|
||||
if (auto sthis = wthis.lock())
|
||||
sthis->handle_request(ec);
|
||||
});
|
||||
return;
|
||||
if (response_.status_code == restinio::status_code::moved_permanently.raw_code() or
|
||||
response_.status_code == restinio::status_code::found.raw_code())
|
||||
{
|
||||
auto location_it = response_.headers.find(restinio::field_to_string(restinio::http_field_t::location));
|
||||
if (location_it == response_.headers.end()){
|
||||
if (logger_)
|
||||
logger_->e("[http:client] [request:%i] got redirect without location", id_);
|
||||
terminate(asio::error::connection_aborted);
|
||||
}
|
||||
|
||||
if (follow_redirect and num_redirect < MAX_REDIRECTS) {
|
||||
auto newUrl = getRelativePath(get_url(), location_it->second);
|
||||
if (logger_)
|
||||
logger_->w("[http:client] [request:%i] redirect to %s", id_, newUrl.c_str());
|
||||
auto next = std::make_shared<Request>(ctx_, newUrl, logger_);
|
||||
next->set_method(header_.method());
|
||||
next->headers_ = std::move(headers_);
|
||||
next->body_ = std::move(body_);
|
||||
next->cbs_ = std::move(cbs_);
|
||||
next->num_redirect = num_redirect + 1;
|
||||
next_ = next;
|
||||
next->prev_ = shared_from_this();
|
||||
next->send();
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->e("[http:client] [request:%i] got redirect without location", id_);
|
||||
terminate(asio::error::connection_aborted);
|
||||
}
|
||||
} else {
|
||||
auto expect_it = headers_.find(restinio::http_field_t::expect);
|
||||
if (expect_it != headers_.end() and (expect_it->second == "100-continue") and response_.status_code != 200){
|
||||
notify_state_change(State::SENDING);
|
||||
request_.append(body_);
|
||||
std::ostream request_stream(&conn_->input());
|
||||
request_stream << body_ << "\r\n";
|
||||
std::weak_ptr<Request> wthis = shared_from_this();
|
||||
conn_->async_write([wthis](const asio::error_code& ec, size_t) {
|
||||
if (auto sthis = wthis.lock())
|
||||
sthis->handle_request(ec);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool startsWith(const std::string& haystack, const std::string& needle) {
|
||||
return needle.length() <= haystack.length()
|
||||
&& std::equal(needle.begin(), needle.end(), haystack.begin());
|
||||
}
|
||||
|
||||
std::string
|
||||
Request::getRelativePath(const Url& origin, const std::string& path)
|
||||
{
|
||||
if (startsWith(path, HTTP_PROTOCOL)
|
||||
|| startsWith(path, HTTPS_PROTOCOL)
|
||||
|| startsWith(path, ORIGIN_PROTOCOL)) {
|
||||
// Absolute path
|
||||
return path;
|
||||
}
|
||||
Url newPath = origin;
|
||||
if (not path.empty() and path[0] == '/') {
|
||||
newPath.target = path;
|
||||
} else {
|
||||
if (newPath.target.empty())
|
||||
newPath.target.push_back('/');
|
||||
newPath.target += path;
|
||||
}
|
||||
return newPath.toString();
|
||||
}
|
||||
|
||||
const Response&
|
||||
Request::await()
|
||||
{
|
||||
std::mutex mtx;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
std::condition_variable cv;
|
||||
bool ok {false};
|
||||
add_on_done_callback([&](const Response&){
|
||||
std::lock_guard<std::mutex> lk(mtx);
|
||||
ok = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
cv.wait(lock, [&]{ return ok; });
|
||||
return response_;
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
} // namespace dht
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
* Nicolas Reynaud <nicolas.reynaud@savoirfairelinux.com>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -30,8 +30,9 @@ namespace dht {
|
||||
struct Listener {
|
||||
time_point time;
|
||||
Query query;
|
||||
int version;
|
||||
|
||||
Listener(time_point t, Query&& q) : time(t), query(std::move(q)) {}
|
||||
Listener(time_point t, Query&& q, int version = 0) : time(t), query(std::move(q)), version(version) {}
|
||||
|
||||
void refresh(time_point t, Query&& q) {
|
||||
time = t;
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
@@ -115,22 +115,22 @@ getSyslogLogger(const char* name) {
|
||||
|
||||
void
|
||||
enableLogging(dht::DhtRunner &dht) {
|
||||
dht.setLogger(*getStdLogger());
|
||||
dht.setLogger(getStdLogger());
|
||||
}
|
||||
|
||||
void
|
||||
enableFileLogging(dht::DhtRunner &dht, const std::string &path) {
|
||||
dht.setLogger(*getFileLogger(path));
|
||||
dht.setLogger(getFileLogger(path));
|
||||
}
|
||||
|
||||
OPENDHT_PUBLIC void
|
||||
enableSyslog(dht::DhtRunner &dht, const char* name) {
|
||||
dht.setLogger(*getSyslogLogger(name));
|
||||
dht.setLogger(getSyslogLogger(name));
|
||||
}
|
||||
|
||||
void
|
||||
disableLogging(dht::DhtRunner &dht) {
|
||||
dht.setLogger({});
|
||||
dht.setLogger();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -31,7 +31,8 @@ enum class MessageType {
|
||||
Refresh,
|
||||
Listen,
|
||||
ValueData,
|
||||
ValueUpdate
|
||||
ValueUpdate,
|
||||
UpdateValue
|
||||
};
|
||||
|
||||
} /* namespace net */
|
||||
|
||||
+279
-178
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
namespace dht {
|
||||
namespace net {
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
const std::string DhtProtocolException::GET_NO_INFOHASH {"Get_values with no info_hash"};
|
||||
const std::string DhtProtocolException::LISTEN_NO_INFOHASH {"Listen with no info_hash"};
|
||||
@@ -47,23 +48,6 @@ static constexpr uint8_t v4prefix[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xF
|
||||
constexpr unsigned SEND_NODES {8};
|
||||
|
||||
|
||||
/* Transaction-ids are 4-bytes long, with the first two bytes identifying
|
||||
* the kind of request, and the remaining two a sequence number in
|
||||
* host order.
|
||||
*/
|
||||
struct TransId final : public std::array<uint8_t, 4> {
|
||||
TransId() { std::fill(begin(), end(), 0); }
|
||||
TransId(const std::array<char, 4>& o) { std::copy(o.begin(), o.end(), begin()); }
|
||||
TransId(uint32_t id) {
|
||||
*reinterpret_cast<uint32_t*>(data()) = htonl(id);
|
||||
}
|
||||
|
||||
uint32_t toInt() const {
|
||||
return ntohl(*reinterpret_cast<const uint32_t*>(&(*this)[0]));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct NetworkEngine::PartialMessage {
|
||||
SockAddr from;
|
||||
time_point start;
|
||||
@@ -98,11 +82,11 @@ RequestAnswer::RequestAnswer(ParsedMessage&& msg)
|
||||
nodes6(std::move(msg.nodes6))
|
||||
{}
|
||||
|
||||
NetworkEngine::NetworkEngine(Logger& log, Scheduler& scheduler, std::unique_ptr<DatagramSocket>&& sock)
|
||||
: myid(zeroes), dht_socket(std::move(sock)), DHT_LOG(log), rate_limiter((size_t)-1), scheduler(scheduler)
|
||||
{}
|
||||
|
||||
NetworkEngine::NetworkEngine(InfoHash& myid, NetworkConfig c, std::unique_ptr<DatagramSocket>&& sock, Logger& log, Scheduler& scheduler,
|
||||
NetworkEngine::NetworkEngine(InfoHash& myid, NetworkConfig c,
|
||||
std::unique_ptr<DatagramSocket>&& sock,
|
||||
const Sp<Logger>& log,
|
||||
std::mt19937_64& rand,
|
||||
Scheduler& scheduler,
|
||||
decltype(NetworkEngine::onError)&& onError,
|
||||
decltype(NetworkEngine::onNewNode)&& onNewNode,
|
||||
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
|
||||
@@ -121,7 +105,8 @@ NetworkEngine::NetworkEngine(InfoHash& myid, NetworkConfig c, std::unique_ptr<Da
|
||||
onListen(std::move(onListen)),
|
||||
onAnnounce(std::move(onAnnounce)),
|
||||
onRefresh(std::move(onRefresh)),
|
||||
myid(myid), config(c), dht_socket(std::move(sock)), DHT_LOG(log),
|
||||
myid(myid), config(c), dht_socket(std::move(sock)), logger_(log), rd(rand),
|
||||
cache(rd),
|
||||
rate_limiter(config.max_req_per_sec),
|
||||
scheduler(scheduler)
|
||||
{}
|
||||
@@ -134,72 +119,119 @@ void
|
||||
NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash, want_t want,
|
||||
const Blob& ntoken, std::vector<Sp<Node>>&& nodes,
|
||||
std::vector<Sp<Node>>&& nodes6, std::vector<Sp<Value>>&& values,
|
||||
const Query& query)
|
||||
const Query& query, int version)
|
||||
{
|
||||
auto nnodes = bufferNodes(node->getFamily(), hash, want, nodes, nodes6);
|
||||
try {
|
||||
sendNodesValues(node->getAddr(), socket_id, nnodes.first, nnodes.second, values, query, ntoken);
|
||||
if (version >= 1) {
|
||||
sendUpdateValues(node, hash, values, scheduler.time(), ntoken, socket_id);
|
||||
} else {
|
||||
sendNodesValues(node->getAddr(), socket_id, nnodes.first, nnodes.second, values, query, ntoken);
|
||||
}
|
||||
} catch (const std::overflow_error& e) {
|
||||
DHT_LOG.e("Can't send value: buffer not large enough !");
|
||||
if (logger_)
|
||||
logger_->e("Can't send value: buffer not large enough !");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
|
||||
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
|
||||
pk.pack(KEY_U);
|
||||
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
if (not token.empty()) {
|
||||
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
|
||||
}
|
||||
if (not values.empty()) {
|
||||
pk.pack(KEY_REQ_REFRESHED);
|
||||
pk.pack(values);
|
||||
DHT_LOG.d(n->id, "[node %s] sending %zu refreshed values", n->toString().c_str(), values.size());
|
||||
}
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
|
||||
|
||||
pk.pack(KEY_TID); pk.pack(socket_id);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(version >= 1 ? KEY_A : KEY_U);
|
||||
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
if (version >= 1) {
|
||||
pk.pack(KEY_REQ_SID); pk.pack(socket_id);
|
||||
}
|
||||
if (not token.empty()) {
|
||||
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
|
||||
}
|
||||
if (not values.empty()) {
|
||||
pk.pack(KEY_REQ_REFRESHED);
|
||||
pk.pack(values);
|
||||
if (logger_)
|
||||
logger_->d(n->id, "[node %s] sending %zu refreshed values", n->toString().c_str(), values.size());
|
||||
}
|
||||
|
||||
pk.pack(KEY_Y); pk.pack(version >= 1 ? KEY_Q : KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
if (version >= 1) {
|
||||
Tid tid (n->getNewTid());
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request&, ParsedMessage&&) { /* on done */ },
|
||||
[=](const Request&, bool) { /* on expired */ }
|
||||
);
|
||||
sendRequest(req);
|
||||
++out_stats.updateValue;
|
||||
return;
|
||||
}
|
||||
pk.pack(KEY_TID); pk.pack(socket_id);
|
||||
|
||||
// send response
|
||||
send(n->getAddr(), buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
|
||||
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
|
||||
pk.pack(KEY_U);
|
||||
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
if (not token.empty()) {
|
||||
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
|
||||
}
|
||||
if (not values.empty()) {
|
||||
pk.pack(KEY_REQ_EXPIRED);
|
||||
pk.pack(values);
|
||||
DHT_LOG.d(n->id, "[node %s] sending %zu expired values", n->toString().c_str(), values.size());
|
||||
}
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
|
||||
|
||||
pk.pack(KEY_TID); pk.pack(socket_id);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(version >= 1 ? KEY_A : KEY_U);
|
||||
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
if (version >= 1) {
|
||||
pk.pack(KEY_REQ_SID); pk.pack(socket_id);
|
||||
}
|
||||
if (not token.empty()) {
|
||||
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
|
||||
}
|
||||
if (not values.empty()) {
|
||||
pk.pack(KEY_REQ_EXPIRED);
|
||||
pk.pack(values);
|
||||
if (logger_)
|
||||
logger_->d(n->id, "[node %s] sending %zu expired values", n->toString().c_str(), values.size());
|
||||
}
|
||||
|
||||
pk.pack(KEY_Y); pk.pack(version >= 1 ? KEY_Q : KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
if (version >= 1) {
|
||||
Tid tid (n->getNewTid());
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request&, ParsedMessage&&) { /* on done */ },
|
||||
[=](const Request&, bool) { /* on expired */ }
|
||||
);
|
||||
sendRequest(req);
|
||||
++out_stats.updateValue;
|
||||
return;
|
||||
}
|
||||
pk.pack(KEY_TID); pk.pack(socket_id);
|
||||
|
||||
// send response
|
||||
send(n->getAddr(), buffer.data(), buffer.size());
|
||||
}
|
||||
@@ -246,7 +278,8 @@ NetworkEngine::requestStep(Sp<Request> sreq)
|
||||
auto now = scheduler.time();
|
||||
auto& node = *req.node;
|
||||
if (req.isExpired(now)) {
|
||||
// DHT_LOG.d(node.id, "[node %s] expired !", node.toString().c_str());
|
||||
// if (logger_)
|
||||
// logger_->d(node.id, "[node %s] expired !", node.toString().c_str());
|
||||
node.setExpired();
|
||||
if (not node.id)
|
||||
requests.erase(req.tid);
|
||||
@@ -266,12 +299,17 @@ NetworkEngine::requestStep(Sp<Request> sreq)
|
||||
if (not node.id)
|
||||
requests.erase(req.tid);
|
||||
} else {
|
||||
req.last_try = now;
|
||||
if (err != EAGAIN) {
|
||||
++req.attempt_count;
|
||||
req.attempt_duration +=
|
||||
req.attempt_duration + uniform_duration_distribution<>(0ms, ((duration)Node::MAX_RESPONSE_TIME)/4)(rd);
|
||||
if (not req.parts.empty()){
|
||||
sendValueParts(req.tid, req.parts, node.getAddr());
|
||||
}
|
||||
}
|
||||
req.last_try = now;
|
||||
std::weak_ptr<Request> wreq = sreq;
|
||||
scheduler.add(req.last_try + Node::MAX_RESPONSE_TIME, [this,wreq] {
|
||||
scheduler.add(req.last_try + req.attempt_duration, [this,wreq] {
|
||||
if (auto req = wreq.lock())
|
||||
requestStep(req);
|
||||
});
|
||||
@@ -338,7 +376,7 @@ NetworkEngine::isMartian(const SockAddr& addr)
|
||||
const uint8_t* address = (const uint8_t*)&sin6.sin6_addr;
|
||||
return address[0] == 0xFF ||
|
||||
(address[0] == 0xFE && (address[1] & 0xC0) == 0x80) ||
|
||||
memcmp(address, zeroes.data(), 16) == 0 ||
|
||||
memcmp(address, InfoHash::zero().data(), 16) == 0 ||
|
||||
memcmp(address, v4prefix, 12) == 0;
|
||||
}
|
||||
default:
|
||||
@@ -366,12 +404,14 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
{
|
||||
auto from = f.getMappedIPv4();
|
||||
if (isMartian(from)) {
|
||||
DHT_LOG.w("Received packet from martian node %s", from.toString().c_str());
|
||||
if (logger_)
|
||||
logger_->w("Received packet from martian node %s", from.toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNodeBlacklisted(from)) {
|
||||
DHT_LOG.w("Received packet from blacklisted node %s", from.toString().c_str());
|
||||
if (logger_)
|
||||
logger_->w("Received packet from blacklisted node %s", from.toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -380,13 +420,16 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
msgpack::unpacked msg_res = msgpack::unpack((const char*)buf, buflen);
|
||||
msg->msgpack_unpack(msg_res.get());
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.w("Can't parse message of size %lu: %s", buflen, e.what());
|
||||
//DHT_LOG.DBG.logPrintable(buf, buflen);
|
||||
if (logger_)
|
||||
logger_->w("Can't parse message of size %lu: %s", buflen, e.what());
|
||||
// if (logger_)
|
||||
// logger_->DBG.logPrintable(buf, buflen);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->network != config.network) {
|
||||
DHT_LOG.d("Received message from other config.network %u", msg->network);
|
||||
if (logger_)
|
||||
logger_->d("Received message from other config.network %u", msg->network);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -397,12 +440,14 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
auto pmsg_it = partial_messages.find(msg->tid);
|
||||
if (pmsg_it == partial_messages.end()) {
|
||||
if (logIncoming_)
|
||||
DHT_LOG.d("Can't find partial message");
|
||||
if (logger_)
|
||||
logger_->d("Can't find partial message");
|
||||
rateLimit(from);
|
||||
return;
|
||||
}
|
||||
if (!pmsg_it->second.from.equals(from)) {
|
||||
DHT_LOG.d("Received partial message data from unexpected IP address");
|
||||
if (logger_)
|
||||
logger_->d("Received partial message data from unexpected IP address");
|
||||
rateLimit(from);
|
||||
return;
|
||||
}
|
||||
@@ -411,9 +456,13 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
pmsg_it->second.last_part = now;
|
||||
// check data completion
|
||||
if (pmsg_it->second.msg->complete()) {
|
||||
// process the full message
|
||||
process(std::move(pmsg_it->second.msg), from);
|
||||
partial_messages.erase(pmsg_it);
|
||||
try {
|
||||
// process the full message
|
||||
process(std::move(pmsg_it->second.msg), from);
|
||||
partial_messages.erase(pmsg_it);
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
} else
|
||||
scheduler.add(now + RX_TIMEOUT, std::bind(&NetworkEngine::maintainRxBuffer, this, msg->tid));
|
||||
}
|
||||
@@ -421,20 +470,26 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
}
|
||||
|
||||
if (msg->id == myid or not msg->id) {
|
||||
DHT_LOG.d("Received message from self");
|
||||
if (logger_)
|
||||
logger_->d("Received message from self");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->type > MessageType::Reply) {
|
||||
/* Rate limit requests. */
|
||||
if (!rateLimit(from)) {
|
||||
DHT_LOG.w("Dropping request due to rate limiting");
|
||||
if (logger_)
|
||||
logger_->w("Dropping request due to rate limiting");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg->value_parts.empty()) {
|
||||
process(std::move(msg), from);
|
||||
try {
|
||||
process(std::move(msg), from);
|
||||
} catch(...) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// starting partial message session
|
||||
auto k = msg->tid;
|
||||
@@ -447,7 +502,8 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
|
||||
scheduler.add(now + RX_MAX_PACKET_TIME, std::bind(&NetworkEngine::maintainRxBuffer, this, k));
|
||||
scheduler.add(now + RX_TIMEOUT, std::bind(&NetworkEngine::maintainRxBuffer, this, k));
|
||||
} else
|
||||
DHT_LOG.e("Partial message with given TID already exists");
|
||||
if (logger_)
|
||||
logger_->e("Partial message with given TID already exists");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +537,8 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
node->received(now, req);
|
||||
if (not node->isClient())
|
||||
onNewNode(node, 1);
|
||||
DHT_LOG.d(node->id, "[node %s] can't find transaction with id %u", node->toString().c_str(), msg->tid);
|
||||
if (logger_)
|
||||
logger_->d(node->id, "[node %s] can't find transaction with id %u", node->toString().c_str(), msg->tid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -493,7 +550,8 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
onReportedAddr(msg->id, msg->addr);
|
||||
|
||||
if (req and (req->cancelled() or req->expired() or req->completed())) {
|
||||
DHT_LOG.w(node->id, "[node %s] response to expired, cancelled or completed request", node->toString().c_str());
|
||||
if (logger_)
|
||||
logger_->w(node->id, "[node %s] response to expired, cancelled or completed request", node->toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -506,10 +564,12 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
{
|
||||
req->last_try = time_point::min();
|
||||
req->reply_time = time_point::min();
|
||||
onError(req, DhtProtocolException {msg->error_code});
|
||||
if (not req->setError(DhtProtocolException {msg->error_code}))
|
||||
onError(req, DhtProtocolException {msg->error_code});
|
||||
} else {
|
||||
if (logIncoming_)
|
||||
DHT_LOG.w(msg->id, "[node %s %s] received unknown error message %u",
|
||||
if (logger_)
|
||||
logger_->w(msg->id, "[node %s %s] received unknown error message %u",
|
||||
msg->id.toString().c_str(), from.toString().c_str(), msg->error_code);
|
||||
}
|
||||
break;
|
||||
@@ -517,8 +577,11 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
case MessageType::Reply:
|
||||
if (req) { /* request reply */
|
||||
auto& r = *req;
|
||||
if (r.getType() == MessageType::AnnounceValue or r.getType() == MessageType::Listen)
|
||||
if (r.getType() == MessageType::AnnounceValue
|
||||
or r.getType() == MessageType::Listen
|
||||
or r.getType() == MessageType::Refresh) {
|
||||
r.node->authSuccess();
|
||||
}
|
||||
r.reply_time = scheduler.time();
|
||||
|
||||
deserializeNodes(*msg, from);
|
||||
@@ -541,12 +604,14 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
case MessageType::Ping:
|
||||
++in_stats.ping;
|
||||
if (logIncoming_)
|
||||
DHT_LOG.d(node->id, "[node %s] sending pong", node->toString().c_str());
|
||||
if (logger_)
|
||||
logger_->d(node->id, "[node %s] sending pong", node->toString().c_str());
|
||||
onPing(node);
|
||||
sendPong(from, msg->tid);
|
||||
break;
|
||||
case MessageType::FindNode: {
|
||||
//DHT_LOG.d(msg->target, node->id, "[node %s] got 'find' request for %s (%d)", node->toString().c_str(), msg->target.toString().c_str(), msg->want);
|
||||
// if (logger_)
|
||||
// logger_->d(msg->target, node->id, "[node %s] got 'find' request for %s (%d)", node->toString().c_str(), msg->target.toString().c_str(), msg->want);
|
||||
++in_stats.find;
|
||||
RequestAnswer answer = onFindNode(node, msg->target, msg->want);
|
||||
auto nnodes = bufferNodes(from.getFamily(), msg->target, msg->want, answer.nodes4, answer.nodes6);
|
||||
@@ -554,7 +619,8 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
break;
|
||||
}
|
||||
case MessageType::GetValues: {
|
||||
//DHT_LOG.d(msg->info_hash, node->id, "[node %s] got 'get' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
// if (logger_)
|
||||
// logger_->d(msg->info_hash, node->id, "[node %s] got 'get' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
++in_stats.get;
|
||||
RequestAnswer answer = onGetValues(node, msg->info_hash, msg->want, msg->query);
|
||||
auto nnodes = bufferNodes(from.getFamily(), msg->info_hash, msg->want, answer.nodes4, answer.nodes6);
|
||||
@@ -562,8 +628,8 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
break;
|
||||
}
|
||||
case MessageType::AnnounceValue: {
|
||||
if (logIncoming_)
|
||||
DHT_LOG.d(msg->info_hash, node->id, "[node %s] got 'put' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
if (logIncoming_ and logger_)
|
||||
logger_->d(msg->info_hash, node->id, "[node %s] got 'put' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
++in_stats.put;
|
||||
onAnnounce(node, msg->info_hash, msg->token, msg->values, msg->created);
|
||||
|
||||
@@ -576,27 +642,39 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
break;
|
||||
}
|
||||
case MessageType::Refresh:
|
||||
if (logIncoming_)
|
||||
DHT_LOG.d(msg->info_hash, node->id, "[node %s] got 'refresh' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
if (logIncoming_ and logger_)
|
||||
logger_->d(msg->info_hash, node->id, "[node %s] got 'refresh' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
onRefresh(node, msg->info_hash, msg->token, msg->value_id);
|
||||
/* Same note as above in MessageType::AnnounceValue applies. */
|
||||
sendValueAnnounced(from, msg->tid, msg->value_id);
|
||||
break;
|
||||
case MessageType::Listen: {
|
||||
if (logIncoming_)
|
||||
DHT_LOG.d(msg->info_hash, node->id, "[node %s] got 'listen' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
if (logIncoming_ and logger_)
|
||||
logger_->d(msg->info_hash, node->id, "[node %s] got 'listen' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
++in_stats.listen;
|
||||
RequestAnswer answer = onListen(node, msg->info_hash, msg->token, msg->socket_id, std::move(msg->query));
|
||||
RequestAnswer answer = onListen(node, msg->info_hash, msg->token, msg->socket_id, std::move(msg->query), msg->version);
|
||||
auto nnodes = bufferNodes(from.getFamily(), msg->info_hash, msg->want, answer.nodes4, answer.nodes6);
|
||||
sendListenConfirmation(from, msg->tid);
|
||||
break;
|
||||
}
|
||||
case MessageType::UpdateValue: {
|
||||
if (logIncoming_ and logger_)
|
||||
logger_->d(msg->info_hash, node->id, "[node %s] got 'update' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
++in_stats.updateValue;
|
||||
if (auto rsocket = node->getSocket(msg->socket_id))
|
||||
rsocket->on_receive(node, std::move(*msg));
|
||||
else if (logger_)
|
||||
logger_->e(msg->info_hash, node->id, "[node %s] 'update' request without socket for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
|
||||
sendListenConfirmation(from, msg->tid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (const std::overflow_error& e) {
|
||||
DHT_LOG.e("Can't send value: buffer not large enough !");
|
||||
} catch (DhtProtocolException& e) {
|
||||
if (logger_)
|
||||
logger_->e("Can't send value: buffer not large enough !");
|
||||
} catch (const DhtProtocolException& e) {
|
||||
sendError(from, msg->tid, e.getCode(), e.getMsg().c_str(), true);
|
||||
}
|
||||
}
|
||||
@@ -622,7 +700,7 @@ NetworkEngine::send(const SockAddr& addr, const char *buf, size_t len, bool conf
|
||||
|
||||
Sp<Request>
|
||||
NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
|
||||
TransId tid (node->getNewTid());
|
||||
Tid tid (node->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
@@ -631,18 +709,18 @@ NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& o
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_PING);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Ping, tid.toInt(), node,
|
||||
auto req = std::make_shared<Request>(MessageType::Ping, tid, node,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&&) {
|
||||
DHT_LOG.d(req_status.node->id, "[node %s] got pong !", req_status.node->toString().c_str());
|
||||
if (logger_)
|
||||
logger_->d(req_status.node->id, "[node %s] got pong !", req_status.node->toString().c_str());
|
||||
if (on_done) {
|
||||
on_done(req_status, {});
|
||||
}
|
||||
@@ -668,9 +746,7 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
insertAddr(pk, addr);
|
||||
|
||||
TransId t (tid);
|
||||
pk.pack(KEY_TID); pk.pack_bin(t.size());
|
||||
pk.pack_bin_body((const char*)t.data(), t.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
@@ -683,7 +759,7 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
|
||||
Sp<Request>
|
||||
NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
|
||||
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
|
||||
TransId tid (n->getNewTid());
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
@@ -699,15 +775,14 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
|
||||
}
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_FIND);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::FindNode, tid.toInt(), n,
|
||||
auto req = std::make_shared<Request>(MessageType::FindNode, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
if (on_done) {
|
||||
@@ -729,34 +804,38 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
|
||||
Sp<Request>
|
||||
NetworkEngine::sendGetValues(Sp<Node> n, const InfoHash& info_hash, const Query& query, want_t want,
|
||||
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
|
||||
TransId tid (n->getNewTid());
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map(2 +
|
||||
(query.where.getFilter() or not query.select.getSelection().empty() ? 1:0) +
|
||||
(want>0?1:0));
|
||||
unsigned sendQuery = (not query.where.empty() or not query.select.empty()) ? 1 : 0;
|
||||
unsigned sendWant = (want > 0) ? 1 : 0;
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map(2 + sendQuery + sendWant);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
pk.pack(KEY_REQ_H); pk.pack(info_hash);
|
||||
pk.pack(KEY_Q); pk.pack(query);
|
||||
if (want > 0) {
|
||||
pk.pack(KEY_REQ_WANT);
|
||||
pk.pack_array(((want & WANT4)?1:0) + ((want & WANT6)?1:0));
|
||||
if (want & WANT4) pk.pack(AF_INET);
|
||||
if (want & WANT6) pk.pack(AF_INET6);
|
||||
}
|
||||
if (sendQuery) {
|
||||
pk.pack(KEY_Q); pk.pack(query);
|
||||
}
|
||||
if (sendWant) {
|
||||
pk.pack(KEY_REQ_WANT);
|
||||
unsigned sendWant4 = (want & WANT4) ? 1 : 0;
|
||||
unsigned sendWant6 = (want & WANT6) ? 1 : 0;
|
||||
pk.pack_array(sendWant4 + sendWant6);
|
||||
if (sendWant4) pk.pack(AF_INET);
|
||||
if (sendWant6) pk.pack(AF_INET6);
|
||||
}
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_GET);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::GetValues, tid.toInt(), n,
|
||||
auto req = std::make_shared<Request>(MessageType::GetValues, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
if (on_done) {
|
||||
@@ -847,7 +926,8 @@ NetworkEngine::packValueHeader(msgpack::sbuffer& buffer, const std::vector<Sp<Va
|
||||
if (svals.size() < 50 && total_size < MAX_PACKET_VALUE_SIZE) {
|
||||
for (const auto& b : svals)
|
||||
buffer.write((const char*)b.data(), b.size());
|
||||
// DHT_LOG.d("sending %lu bytes of values", total_size);
|
||||
// if (logger_)
|
||||
// logger_->d("sending %lu bytes of values", total_size);
|
||||
svals.clear();
|
||||
} else {
|
||||
for (const auto& b : svals)
|
||||
@@ -857,7 +937,7 @@ NetworkEngine::packValueHeader(msgpack::sbuffer& buffer, const std::vector<Sp<Va
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngine::sendValueParts(const TransId& tid, const std::vector<Blob>& svals, const SockAddr& addr)
|
||||
NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const SockAddr& addr)
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
unsigned i=0;
|
||||
@@ -872,8 +952,7 @@ NetworkEngine::sendValueParts(const TransId& tid, const std::vector<Blob>& svals
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
pk.pack(KEY_Y); pk.pack(KEY_V);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_V); pk.pack_map(1);
|
||||
pk.pack(i); pk.pack_map(2);
|
||||
pk.pack(std::string("o")); pk.pack(start);
|
||||
@@ -913,10 +992,10 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
|
||||
}
|
||||
std::vector<Blob> svals {};
|
||||
if (not st.empty()) { /* pack complete values */
|
||||
auto fields = query.select.getSelection();
|
||||
if (fields.empty()) {
|
||||
if (query.select.empty()) {
|
||||
svals = packValueHeader(buffer, st);
|
||||
} else { /* pack fields */
|
||||
auto fields = query.select.getSelection();
|
||||
pk.pack(KEY_REQ_FIELDS);
|
||||
pk.pack_map(2);
|
||||
pk.pack(std::string("f")); pk.pack(fields);
|
||||
@@ -928,9 +1007,7 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
|
||||
}
|
||||
}
|
||||
|
||||
TransId t (tid);
|
||||
pk.pack(KEY_TID); pk.pack_bin(t.size());
|
||||
pk.pack_bin_body((const char*)t.data(), t.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
@@ -1000,52 +1077,35 @@ NetworkEngine::sendListen(Sp<Node> n,
|
||||
const InfoHash& hash,
|
||||
const Query& query,
|
||||
const Blob& token,
|
||||
Sp<Request> previous,
|
||||
Tid socketId,
|
||||
RequestCb&& on_done,
|
||||
RequestExpiredCb&& on_expired,
|
||||
SocketCb&& socket_cb)
|
||||
RequestExpiredCb&& on_expired)
|
||||
{
|
||||
Tid socket;
|
||||
TransId tid (n->getNewTid());
|
||||
if (previous and previous->node == n) {
|
||||
socket = previous->getSocket();
|
||||
} else {
|
||||
if (previous)
|
||||
DHT_LOG.e(hash, "[node %s] trying refresh listen contract with wrong node", previous->node->toString().c_str());
|
||||
socket = n->openSocket(std::move(socket_cb));
|
||||
}
|
||||
|
||||
if (not socket) {
|
||||
DHT_LOG.e(hash, "[node %s] unable to get a valid socket for listen. Aborting listen", n->toString().c_str());
|
||||
return {};
|
||||
}
|
||||
TransId sid(socket);
|
||||
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
|
||||
auto has_query = query.where.getFilter() or not query.select.getSelection().empty();
|
||||
pk.pack(KEY_A); pk.pack_map(4 + has_query);
|
||||
auto has_query = not query.where.empty() or not query.select.empty();
|
||||
pk.pack(KEY_A); pk.pack_map(5 + has_query);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
pk.pack(KEY_VERSION); pk.pack(1);
|
||||
pk.pack(KEY_REQ_H); pk.pack(hash);
|
||||
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
|
||||
pk.pack(KEY_REQ_SID); pk.pack_bin(sid.size());
|
||||
pk.pack_bin_body((const char*)sid.data(), sid.size());
|
||||
pk.pack(KEY_REQ_SID); pk.pack(socketId);
|
||||
if (has_query) {
|
||||
pk.pack(KEY_REQ_QUERY); pk.pack(query);
|
||||
}
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_LISTEN);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Listen, tid.toInt(), n,
|
||||
auto req = std::make_shared<Request>(MessageType::Listen, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
if (on_done)
|
||||
@@ -1054,8 +1114,7 @@ NetworkEngine::sendListen(Sp<Node> n,
|
||||
[=](const Request& req_status, bool done) { /* on expired */
|
||||
if (on_expired)
|
||||
on_expired(req_status, done);
|
||||
},
|
||||
socket
|
||||
}
|
||||
);
|
||||
sendRequest(req);
|
||||
++out_stats.listen;
|
||||
@@ -1072,9 +1131,7 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
insertAddr(pk, addr);
|
||||
|
||||
TransId t (tid);
|
||||
pk.pack(KEY_TID); pk.pack_bin(t.size());
|
||||
pk.pack_bin_body((const char*)t.data(), t.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
@@ -1093,7 +1150,7 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
|
||||
RequestCb&& on_done,
|
||||
RequestExpiredCb&& on_expired)
|
||||
{
|
||||
TransId tid (n->getNewTid());
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
@@ -1109,19 +1166,19 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
|
||||
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_PUT);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid.toInt(), n,
|
||||
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
if (msg.value_id == Value::INVALID_ID) {
|
||||
DHT_LOG.d(infohash, "Unknown search or announce!");
|
||||
if (logger_)
|
||||
logger_->d(infohash, "Unknown search or announce!");
|
||||
} else {
|
||||
if (on_done) {
|
||||
RequestAnswer answer {};
|
||||
@@ -1136,22 +1193,68 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
|
||||
}
|
||||
}
|
||||
);
|
||||
req->parts = std::move(v);
|
||||
sendRequest(req);
|
||||
if (not v.empty())
|
||||
sendValueParts(tid, v, n->getAddr());
|
||||
++out_stats.put;
|
||||
return req;
|
||||
}
|
||||
|
||||
Sp<Request>
|
||||
NetworkEngine::sendUpdateValues(Sp<Node> n,
|
||||
const InfoHash& infohash,
|
||||
const std::vector<Sp<Value>>& values,
|
||||
time_point created,
|
||||
const Blob& token,
|
||||
const size_t& socket_id)
|
||||
{
|
||||
Tid tid (n->getNewTid());
|
||||
Tid sid (socket_id);
|
||||
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map((created < scheduler.time() ? 7 : 6));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
pk.pack(KEY_VERSION); pk.pack(1);
|
||||
pk.pack(KEY_REQ_H); pk.pack(infohash);
|
||||
pk.pack(KEY_REQ_SID); pk.pack(sid);
|
||||
auto v = packValueHeader(buffer, values);
|
||||
if (created < scheduler.time()) {
|
||||
pk.pack(KEY_REQ_CREATION);
|
||||
pk.pack(to_time_t(created));
|
||||
}
|
||||
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request&, ParsedMessage&&) { /* on done */ },
|
||||
[=](const Request&, bool) { /* on expired */ }
|
||||
);
|
||||
req->parts = std::move(v);
|
||||
sendRequest(req);
|
||||
++out_stats.updateValue;
|
||||
return req;
|
||||
}
|
||||
|
||||
Sp<Request>
|
||||
NetworkEngine::sendRefreshValue(Sp<Node> n,
|
||||
const InfoHash& infohash,
|
||||
const Value::Id& vid,
|
||||
const Blob& token,
|
||||
RequestCb&& on_done,
|
||||
RequestErrorCb&& on_error,
|
||||
RequestExpiredCb&& on_expired)
|
||||
{
|
||||
TransId tid (n->getNewTid());
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
@@ -1163,19 +1266,19 @@ NetworkEngine::sendRefreshValue(Sp<Node> n,
|
||||
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
|
||||
|
||||
pk.pack(KEY_Q); pk.pack(QUERY_REFRESH);
|
||||
pk.pack(KEY_TID); pk.pack_bin(tid.size());
|
||||
pk.pack_bin_body((const char*)tid.data(), tid.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_Q);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Refresh, tid.toInt(), n,
|
||||
auto req = std::make_shared<Request>(MessageType::Refresh, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
if (msg.value_id == Value::INVALID_ID) {
|
||||
DHT_LOG.d(infohash, "Unknown search or announce!");
|
||||
if (logger_)
|
||||
logger_->d(infohash, "Unknown search or announce!");
|
||||
} else {
|
||||
if (on_done) {
|
||||
RequestAnswer answer {};
|
||||
@@ -1184,6 +1287,7 @@ NetworkEngine::sendRefreshValue(Sp<Node> n,
|
||||
}
|
||||
}
|
||||
},
|
||||
on_error,
|
||||
[=](const Request& req_status, bool done) { /* on expired */
|
||||
if (on_expired) {
|
||||
on_expired(req_status, done);
|
||||
@@ -1206,9 +1310,7 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
|
||||
pk.pack(KEY_REQ_VALUE_ID); pk.pack(vid);
|
||||
insertAddr(pk, addr);
|
||||
|
||||
TransId t(tid);
|
||||
pk.pack(KEY_TID); pk.pack_bin(t.size());
|
||||
pk.pack_bin_body((const char*)t.data(), t.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_R);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
@@ -1227,7 +1329,7 @@ NetworkEngine::sendError(const SockAddr& addr,
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4 + (include_id?1:0));
|
||||
pk.pack_map(4 + (include_id?1:0) + (config.network?1:0));
|
||||
|
||||
pk.pack(KEY_E); pk.pack_array(2);
|
||||
pk.pack(code);
|
||||
@@ -1238,9 +1340,7 @@ NetworkEngine::sendError(const SockAddr& addr,
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
}
|
||||
|
||||
TransId t(tid);
|
||||
pk.pack(KEY_TID); pk.pack_bin(t.size());
|
||||
pk.pack_bin_body((const char*)t.data(), t.size());
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_Y); pk.pack(KEY_E);
|
||||
pk.pack(KEY_UA); pk.pack(my_v);
|
||||
if (config.network) {
|
||||
@@ -1258,7 +1358,8 @@ NetworkEngine::maintainRxBuffer(Tid tid)
|
||||
const auto& now = scheduler.time();
|
||||
if (msg->second.start + RX_MAX_PACKET_TIME < now
|
||||
|| msg->second.last_part + RX_TIMEOUT < now) {
|
||||
DHT_LOG.w("Dropping expired partial message from %s", msg->second.from.toString().c_str());
|
||||
if (logger_)
|
||||
logger_->w("Dropping expired partial message from %s", msg->second.from.toString().c_str());
|
||||
partial_messages.erase(msg);
|
||||
}
|
||||
}
|
||||
|
||||
+62
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -106,7 +106,7 @@ void udpPipe(int fds[2])
|
||||
}
|
||||
#endif
|
||||
|
||||
UdpSocket::UdpSocket(in_port_t port, const Logger& l) : logger(l) {
|
||||
UdpSocket::UdpSocket(in_port_t port, const std::shared_ptr<Logger>& l) : logger(l) {
|
||||
SockAddr bind4;
|
||||
bind4.setFamily(AF_INET);
|
||||
bind4.setPort(port);
|
||||
@@ -117,7 +117,7 @@ UdpSocket::UdpSocket(in_port_t port, const Logger& l) : logger(l) {
|
||||
openSockets(bind4, bind6);
|
||||
}
|
||||
|
||||
UdpSocket::UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const Logger& l) : logger(l)
|
||||
UdpSocket::UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const std::shared_ptr<Logger>& l) : logger(l)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
openSockets(bind4, bind6);
|
||||
@@ -155,7 +155,8 @@ UdpSocket::sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool r
|
||||
|
||||
if (sendto(s, (const char*)data, size, flags, dest.get(), dest.getLength()) == -1) {
|
||||
int err = errno;
|
||||
logger.d("Can't send message to %s: %s", dest.toString().c_str(), strerror(err));
|
||||
if (logger)
|
||||
logger->d("Can't send message to %s: %s", dest.toString().c_str(), strerror(err));
|
||||
if (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
auto bind4 = std::move(bound4), bind6 = std::move(bound6);
|
||||
@@ -194,7 +195,8 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
try {
|
||||
s4 = bindSocket(bind4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet socket: %s", e.what());
|
||||
if (logger)
|
||||
logger->e("Can't bind inet socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +211,8 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
try {
|
||||
s6 = bindSocket(b6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
if (logger)
|
||||
logger->e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,7 +220,8 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
try {
|
||||
s6 = bindSocket(bind6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
if (logger)
|
||||
logger->e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,7 +248,8 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
int rc = select(selectFd, &readfds, nullptr, nullptr, nullptr);
|
||||
if (rc < 0) {
|
||||
if (errno != EINTR) {
|
||||
logger.e("Select error: %s", strerror(errno));
|
||||
if (logger)
|
||||
logger->e("Select error: %s", strerror(errno));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
@@ -259,7 +264,8 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
|
||||
if (FD_ISSET(stop_readfd, &readfds)) {
|
||||
if (recv(stop_readfd, (char*)buf.data(), buf.size(), 0) < 0) {
|
||||
logger.e("Got stop packet error: %s", strerror(errno));
|
||||
if (logger)
|
||||
logger->e("Got stop packet error: %s", strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -271,43 +277,54 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
continue;
|
||||
|
||||
if (rc > 0) {
|
||||
auto pkt = std::unique_ptr<ReceivedPacket>(new ReceivedPacket);
|
||||
pkt->data = {buf.begin(), buf.begin()+rc};
|
||||
pkt->from = {from, from_len};
|
||||
pkt->received = clock::now();
|
||||
onReceived(std::move(pkt));
|
||||
auto pkts = getNewPacket();
|
||||
auto& pkt = pkts.front();
|
||||
pkt.data.insert(pkt.data.end(), buf.begin(), buf.begin()+rc);
|
||||
pkt.from = {from, from_len};
|
||||
pkt.received = clock::now();
|
||||
onReceived(std::move(pkts));
|
||||
} else if (rc == -1) {
|
||||
logger.e("Error receiving packet: %s", strerror(errno));
|
||||
if (logger)
|
||||
logger->e("Error receiving packet: %s", strerror(errno));
|
||||
int err = errno;
|
||||
if (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
if (ls4 >= 0) {
|
||||
close(ls4);
|
||||
try {
|
||||
ls4 = bindSocket(bound4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet socket: %s", e.what());
|
||||
if (not running) break;
|
||||
std::unique_lock<std::mutex> lk(lock, std::try_to_lock);
|
||||
if (lk.owns_lock()) {
|
||||
if (not running) break;
|
||||
if (ls4 >= 0) {
|
||||
close(ls4);
|
||||
try {
|
||||
ls4 = bindSocket(bound4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
if (logger)
|
||||
logger->e("Can't bind inet socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ls6 >= 0) {
|
||||
close(ls6);
|
||||
try {
|
||||
ls6 = bindSocket(bound6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
if (ls6 >= 0) {
|
||||
close(ls6);
|
||||
try {
|
||||
ls6 = bindSocket(bound6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
if (logger)
|
||||
logger->e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ls4 < 0 && ls6 < 0)
|
||||
if (ls4 < 0 && ls6 < 0)
|
||||
break;
|
||||
s4 = ls4;
|
||||
s6 = ls6;
|
||||
selectFd = std::max({ls4, ls6, stop_readfd}) + 1;
|
||||
} else {
|
||||
break;
|
||||
s4 = ls4;
|
||||
s6 = ls6;
|
||||
selectFd = std::max({ls4, ls6, stop_readfd}) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
logger.e("Error in UdpSocket rx thread: %s", e.what());
|
||||
if (logger)
|
||||
logger->e("Error in UdpSocket rx thread: %s", e.what());
|
||||
}
|
||||
if (ls4 >= 0)
|
||||
close(ls4);
|
||||
@@ -315,14 +332,16 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
close(ls6);
|
||||
if (stop_readfd != -1)
|
||||
close(stop_readfd);
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
bound4 = {};
|
||||
bound6 = {};
|
||||
if (stopfd != -1)
|
||||
close(stopfd);
|
||||
stopfd = -1;
|
||||
std::unique_lock<std::mutex> lk(lock, std::try_to_lock);
|
||||
if (lk.owns_lock()) {
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
bound4 = {};
|
||||
bound6 = {};
|
||||
stopfd = -1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -332,7 +351,8 @@ UdpSocket::stop()
|
||||
if (running.exchange(false)) {
|
||||
auto sfd = stopfd;
|
||||
if (sfd != -1 && write(sfd, "\0", 1) == -1) {
|
||||
logger.e("Can't write to stop fd");
|
||||
if (logger)
|
||||
logger->e("Can't write to stop fd");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -30,17 +30,15 @@ constexpr std::chrono::minutes Node::NODE_EXPIRE_TIME;
|
||||
constexpr std::chrono::minutes Node::NODE_GOOD_TIME;
|
||||
constexpr std::chrono::seconds Node::MAX_RESPONSE_TIME;
|
||||
|
||||
Node::Node(const InfoHash& id, const SockAddr& addr, bool client)
|
||||
Node::Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client)
|
||||
: id(id), addr(addr), is_client(client), sockets_()
|
||||
{
|
||||
thread_local crypto::random_device rd {};
|
||||
transaction_id = std::uniform_int_distribution<Tid>{1}(rd);
|
||||
}
|
||||
|
||||
Node::Node(const InfoHash& id, SockAddr&& addr, bool client)
|
||||
Node::Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client)
|
||||
: id(id), addr(std::move(addr)), is_client(client), sockets_()
|
||||
{
|
||||
thread_local crypto::random_device rd {};
|
||||
transaction_id = std::uniform_int_distribution<Tid>{1}(rd);
|
||||
}
|
||||
|
||||
@@ -118,7 +116,6 @@ Node::cancelRequest(const Sp<net::Request>& req)
|
||||
{
|
||||
if (req) {
|
||||
req->cancel();
|
||||
closeSocket(req->closeSocket());
|
||||
requests_.erase(req->getTid());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -37,8 +37,8 @@ NodeCache::getNode(const InfoHash& id, sa_family_t family) {
|
||||
Sp<Node>
|
||||
NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client) {
|
||||
if (not id)
|
||||
return std::make_shared<Node>(id, addr);
|
||||
return cache(addr.getFamily()).getNode(id, addr, now, confirm, client);
|
||||
return std::make_shared<Node>(id, addr, rd, client);
|
||||
return cache(addr.getFamily()).getNode(id, addr, now, confirm, client, rd);
|
||||
}
|
||||
|
||||
std::vector<Sp<Node>>
|
||||
@@ -104,13 +104,13 @@ NodeCache::NodeMap::getNode(const InfoHash& id)
|
||||
}
|
||||
|
||||
Sp<Node>
|
||||
NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client)
|
||||
NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point now, bool confirm, bool client, std::mt19937_64& rd)
|
||||
{
|
||||
auto it = emplace(id, std::weak_ptr<Node>{});
|
||||
auto node = it.first->second.lock();
|
||||
auto& nref = (*this)[id];
|
||||
auto node = nref.lock();
|
||||
if (not node) {
|
||||
node = std::make_shared<Node>(id, addr, client);
|
||||
it.first->second = node;
|
||||
node = std::make_shared<Node>(id, addr, rd, client);
|
||||
nref = node;
|
||||
if (cleanup_counter++ == CLEANUP_FREQ) {
|
||||
cleanup();
|
||||
cleanup_counter = 0;
|
||||
|
||||
+13
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -22,7 +22,7 @@ namespace dht {
|
||||
constexpr const std::chrono::seconds OpCache::EXPIRATION;
|
||||
|
||||
bool
|
||||
OpValueCache::onValuesAdded(const std::vector<Sp<Value>>& vals) {
|
||||
OpValueCache::onValuesAdded(const std::vector<Sp<Value>>& vals, const system_clock::time_point& t) {
|
||||
std::vector<Sp<Value>> newValues;
|
||||
for (const auto& v : vals) {
|
||||
auto viop = values.emplace(v->id, v);
|
||||
@@ -31,16 +31,21 @@ OpValueCache::onValuesAdded(const std::vector<Sp<Value>>& vals) {
|
||||
} else {
|
||||
viop.first->second.refCount++;
|
||||
}
|
||||
viop.first->second.updated = t;
|
||||
}
|
||||
return newValues.empty() ? true : callback(newValues, false);
|
||||
}
|
||||
|
||||
bool
|
||||
OpValueCache::onValuesExpired(const std::vector<Sp<Value>>& vals) {
|
||||
OpValueCache::onValuesExpired(const std::vector<Sp<Value>>& vals, const system_clock::time_point& t) {
|
||||
std::vector<Sp<Value>> expiredValues;
|
||||
for (const auto& v : vals) {
|
||||
auto vit = values.find(v->id);
|
||||
if (vit != values.end()) {
|
||||
if (vit->second.updated > t)
|
||||
continue;
|
||||
|
||||
vit->second.updated = t;
|
||||
vit->second.refCount--;
|
||||
if (not vit->second.refCount) {
|
||||
expiredValues.emplace_back(std::move(vit->second.data));
|
||||
@@ -52,12 +57,16 @@ OpValueCache::onValuesExpired(const std::vector<Sp<Value>>& vals) {
|
||||
}
|
||||
|
||||
bool
|
||||
OpValueCache::onValuesExpired(const std::vector<Value::Id>& vids)
|
||||
OpValueCache::onValuesExpired(const std::vector<Value::Id>& vids, const system_clock::time_point& t)
|
||||
{
|
||||
std::vector<Sp<Value>> expiredValues;
|
||||
for (const auto& vid : vids) {
|
||||
auto vit = values.find(vid);
|
||||
if (vit != values.end()) {
|
||||
if (vit->second.updated > t)
|
||||
continue;
|
||||
|
||||
vit->second.updated = t;
|
||||
vit->second.refCount--;
|
||||
if (not vit->second.refCount) {
|
||||
expiredValues.emplace_back(std::move(vit->second.data));
|
||||
|
||||
+25
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -27,6 +27,7 @@ struct OpCacheValueStorage
|
||||
{
|
||||
Sp<Value> data {};
|
||||
unsigned refCount {1};
|
||||
system_clock::time_point updated {system_clock::time_point::min()};
|
||||
OpCacheValueStorage(Sp<Value> val) : data(val) {}
|
||||
};
|
||||
|
||||
@@ -38,8 +39,10 @@ public:
|
||||
}
|
||||
|
||||
static ValueCallback cacheCallback(ValueCallback&& cb, std::function<void()>&& onCancel) {
|
||||
auto cache = std::make_shared<OpValueCache>(std::forward<ValueCallback>(cb));
|
||||
return [cache, onCancel](const std::vector<Sp<Value>>& vals, bool expired){
|
||||
return [
|
||||
cache = std::make_shared<OpValueCache>(std::forward<ValueCallback>(cb)),
|
||||
onCancel = std::move(onCancel)
|
||||
](const std::vector<Sp<Value>>& vals, bool expired){
|
||||
auto ret = cache->onValue(vals, expired);
|
||||
if (not ret)
|
||||
onCancel();
|
||||
@@ -47,16 +50,15 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
bool onValue(const std::vector<Sp<Value>>& vals, bool expired) {
|
||||
if (expired)
|
||||
return onValuesExpired(vals);
|
||||
else
|
||||
return onValuesAdded(vals);
|
||||
bool onValue(const std::vector<Sp<Value>>& vals, bool expired, const system_clock::time_point& t = system_clock::time_point::min()) {
|
||||
return expired
|
||||
? onValuesExpired(vals, t)
|
||||
: onValuesAdded(vals, t);
|
||||
}
|
||||
|
||||
bool onValuesAdded(const std::vector<Sp<Value>>& vals);
|
||||
bool onValuesExpired(const std::vector<Sp<Value>>& vals);
|
||||
bool onValuesExpired(const std::vector<Value::Id>& vals);
|
||||
bool onValuesAdded(const std::vector<Sp<Value>>& vals, const system_clock::time_point& t = system_clock::time_point::min());
|
||||
bool onValuesExpired(const std::vector<Sp<Value>>& vals, const system_clock::time_point& t = system_clock::time_point::min());
|
||||
bool onValuesExpired(const std::vector<Value::Id>& vals, const system_clock::time_point& t = system_clock::time_point::min());
|
||||
|
||||
void onNodeChanged(ListenSyncStatus status) {
|
||||
switch (status) {
|
||||
@@ -72,6 +74,7 @@ public:
|
||||
std::vector<Sp<Value>> get(const Value::Filter& filter) const;
|
||||
Sp<Value> get(Value::Id id) const;
|
||||
std::vector<Sp<Value>> getValues() const;
|
||||
size_t size() const { return values.size(); }
|
||||
|
||||
private:
|
||||
OpValueCache(const OpValueCache&) = delete;
|
||||
@@ -143,6 +146,10 @@ public:
|
||||
}
|
||||
time_point getExpiration() const;
|
||||
|
||||
size_t size() const {
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
size_t searchToken;
|
||||
private:
|
||||
constexpr static const std::chrono::seconds EXPIRATION {60};
|
||||
@@ -174,6 +181,13 @@ public:
|
||||
std::vector<Sp<Value>> get(const Value::Filter& filter) const;
|
||||
Sp<Value> get(Value::Id id) const;
|
||||
|
||||
std::pair<size_t, size_t> size() const {
|
||||
size_t tot = 0;
|
||||
for (const auto& c : ops)
|
||||
tot += c.second->size();
|
||||
return {ops.size(), tot};
|
||||
}
|
||||
|
||||
private:
|
||||
SearchCache(const SearchCache&) = delete;
|
||||
SearchCache& operator=(const SearchCache&) = delete;
|
||||
|
||||
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user