mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 20:37:23 +00:00
Compare commits
245
Commits
ssl
...
proxy_restinio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29fe7d5f92 | ||
|
|
459217b6d6 | ||
|
|
d8aa94c8f5 | ||
|
|
8a88ca94db | ||
|
|
a72ddfdb03 | ||
|
|
e7b03e4d53 | ||
|
|
baf43d96ff | ||
|
|
0f9df9a62b | ||
|
|
630112601c | ||
|
|
b0500af062 | ||
|
|
6c985e8fda | ||
|
|
9c1e55279c | ||
|
|
593d024f51 | ||
|
|
a6e57d95d6 | ||
|
|
846f495202 | ||
|
|
6f603bfc0a | ||
|
|
9c106f9efe | ||
|
|
ff288fb4a3 | ||
|
|
17ff4c0224 | ||
|
|
45a2c6dadb | ||
|
|
477ff59e91 | ||
|
|
a001e0cafd | ||
|
|
ac63527e0b | ||
|
|
4b3d8d1231 | ||
|
|
d04a741d5e | ||
|
|
ac2b7deda8 | ||
|
|
c8b08b5ed1 | ||
|
|
f556987e47 | ||
|
|
2daf36c97e | ||
|
|
2a2555f0c2 | ||
|
|
bdfb0148e4 | ||
|
|
01be4d2eb8 | ||
|
|
93f7251805 | ||
|
|
a8718242cd | ||
|
|
297a23fb1f | ||
|
|
0d641161e8 | ||
|
|
27b3c0d47e | ||
|
|
149b33ef57 | ||
|
|
150e62de0b | ||
|
|
89bdfce840 | ||
|
|
bce41ecd69 | ||
|
|
4374d206ab | ||
|
|
b64820af59 | ||
|
|
0e509318bb | ||
|
|
bcc2baa94a | ||
|
|
bbed9d530d | ||
|
|
5a3612be98 | ||
|
|
8202c1f7d7 | ||
|
|
a200b0e14c | ||
|
|
bd32edc6c5 | ||
|
|
d0d3ef7394 | ||
|
|
712da15ae2 | ||
|
|
fcdc997d29 | ||
|
|
cf18effebb | ||
|
|
b8c2ff8a11 | ||
|
|
1fad1b9ce3 | ||
|
|
117fedb641 | ||
|
|
422f5a6c45 | ||
|
|
51a42aa2c8 | ||
|
|
be0baefee8 | ||
|
|
2ac5157ab8 | ||
|
|
fbe8834e04 | ||
|
|
89ff131750 | ||
|
|
feb498305f | ||
|
|
b00f56c94a | ||
|
|
2067cb052f | ||
|
|
51aeaeaeab | ||
|
|
c0bb8f065c | ||
|
|
126318956a | ||
|
|
9014c0a7bb | ||
|
|
728782921c | ||
|
|
d438d4ef1b | ||
|
|
2959709462 | ||
|
|
4a26168248 | ||
|
|
9c348b1df4 | ||
|
|
7e7654d1ae | ||
|
|
69ee1d212a | ||
|
|
21ec9129c3 | ||
|
|
b7185fa87c | ||
|
|
54acd67a1f | ||
|
|
045de8602c | ||
|
|
390fa48700 | ||
|
|
0d08f0d356 | ||
|
|
738424b1ae | ||
|
|
d123d8f768 | ||
|
|
a20a48506d | ||
|
|
063a2b4860 | ||
|
|
829d365475 | ||
|
|
11e6671e60 | ||
|
|
6fe473d3cc | ||
|
|
9f493b9572 | ||
|
|
2164c5ddc7 | ||
|
|
a57a4d55e8 | ||
|
|
b98cc78b42 | ||
|
|
789d41ff07 | ||
|
|
632403875c | ||
|
|
bc2737cdc9 | ||
|
|
0c6bfde1c5 | ||
|
|
cfeeaf7950 | ||
|
|
e31ebfea32 | ||
|
|
07efe8c76e | ||
|
|
5c78bf386d | ||
|
|
86088b043b | ||
|
|
fad8bb1631 | ||
|
|
9a56c099a1 | ||
|
|
8298c0c868 | ||
|
|
971f590941 | ||
|
|
1813d83273 | ||
|
|
e87d164f0b | ||
|
|
b9604807ea | ||
|
|
9f12b44179 | ||
|
|
0772d5435c | ||
|
|
368ee9e22e | ||
|
|
dd56bdd8e2 | ||
|
|
71b36e0643 | ||
|
|
61b43759df | ||
|
|
96e12e88c3 | ||
|
|
8da933c01a | ||
|
|
20c0069867 | ||
|
|
8942e0d00e | ||
|
|
bc760f9348 | ||
|
|
59702190a7 | ||
|
|
cb3e94d0be | ||
|
|
ab7b8f6027 | ||
|
|
6e5231047b | ||
|
|
777505434c | ||
|
|
18c3161261 | ||
|
|
1060038bdf | ||
|
|
9d427a6a80 | ||
|
|
f1dbac2aff | ||
|
|
a63c5d172b | ||
|
|
9c6de8cc16 | ||
|
|
fe9de44867 | ||
|
|
4bfd6bb545 | ||
|
|
120c017399 | ||
|
|
7fc7597564 | ||
|
|
f8d62dc6a7 | ||
|
|
fc3686d817 | ||
|
|
a692f7fbe2 | ||
|
|
cb349d9cf6 | ||
|
|
6266f88cd5 | ||
|
|
0a3320e2c8 | ||
|
|
d6ad67d8e2 | ||
|
|
19d0aa55f7 | ||
|
|
941e53425f | ||
|
|
10971f700f | ||
|
|
2e7767d192 | ||
|
|
baf811bfe9 | ||
|
|
76f0672e63 | ||
|
|
330ad8ed12 | ||
|
|
3252e6daa3 | ||
|
|
07599239a6 | ||
|
|
eac61678f4 | ||
|
|
078c1198b0 | ||
|
|
3d525030b9 | ||
|
|
3733fc2890 | ||
|
|
c40f35fa06 | ||
|
|
13661929d1 | ||
|
|
4e934f8902 | ||
|
|
125a05a5fc | ||
|
|
868c114bcb | ||
|
|
f0acc3e735 | ||
|
|
171e2b130b | ||
|
|
cb5a261b82 | ||
|
|
feb8bd0d4f | ||
|
|
3955368c01 | ||
|
|
b841ff1b83 | ||
|
|
7a04c0eb66 | ||
|
|
fe1659bd2f | ||
|
|
b90e14edd6 | ||
|
|
9e3e9e65e6 | ||
|
|
1c3132e0ef | ||
|
|
f3e304e661 | ||
|
|
2545282624 | ||
|
|
52c413f056 | ||
|
|
ab082543ea | ||
|
|
ff6be81929 | ||
|
|
bd994384f0 | ||
|
|
598e38dbf4 | ||
|
|
b1a35b82a2 | ||
|
|
e4516772ee | ||
|
|
c7844fc320 | ||
|
|
c7e2483160 | ||
|
|
37b12c114d | ||
|
|
77bd34ad9c | ||
|
|
44490bd9ca | ||
|
|
ca01568824 | ||
|
|
2b259639d2 | ||
|
|
84d322e428 | ||
|
|
6d5e3d8cd2 | ||
|
|
b56518f258 | ||
|
|
d807af3951 | ||
|
|
5f393490a5 | ||
|
|
efe869fe42 | ||
|
|
a31cecdeac | ||
|
|
4a4becdbec | ||
|
|
eef2838a12 | ||
|
|
a520657fac | ||
|
|
29003700db | ||
|
|
b143bc459d | ||
|
|
4d6e5ab877 | ||
|
|
248d2e3f73 | ||
|
|
0692bd9bc9 | ||
|
|
7f48c4808b | ||
|
|
32a443a1d8 | ||
|
|
6d0fcba3b5 | ||
|
|
76e2efb19b | ||
|
|
bbe1b9233f | ||
|
|
7558ca0dca | ||
|
|
38141322f1 | ||
|
|
6c5ea125ca | ||
|
|
d0362e58e0 | ||
|
|
1b3a40f345 | ||
|
|
38d854e6f4 | ||
|
|
e0241ccfbd | ||
|
|
d4311925b4 | ||
|
|
9aa56dd464 | ||
|
|
ec3b259ead | ||
|
|
332cab10ef | ||
|
|
85f2b618c7 | ||
|
|
bcf18fda53 | ||
|
|
6b78a4cad6 | ||
|
|
66d3a8aeaa | ||
|
|
958cb250a3 | ||
|
|
6a5724a868 | ||
|
|
11ac84de54 | ||
|
|
f65e8c1a1f | ||
|
|
c2fdf6ae92 | ||
|
|
91a81f64ac | ||
|
|
17b772e6cc | ||
|
|
75738ac28b | ||
|
|
84a2d771c1 | ||
|
|
f6273f9efc | ||
|
|
5881c91510 | ||
|
|
e09c55ca42 | ||
|
|
c737e4690e | ||
|
|
35a9d1f612 | ||
|
|
0f3396cd66 | ||
|
|
98cd6cc61e | ||
|
|
092cb9551e | ||
|
|
a2bbca792c | ||
|
|
0f51115f44 | ||
|
|
18aa6ddb7b | ||
|
|
0a436e17b0 | ||
|
|
763ffddf51 |
No files matched your search
+31
-13
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
project (opendht)
|
||||
set (opendht_VERSION_MAJOR 1)
|
||||
set (opendht_VERSION_MINOR 9.1)
|
||||
set (opendht_VERSION_MINOR 10.0)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -16,10 +16,10 @@ option (OPENDHT_SYSTEMD "Install systemd module" OFF)
|
||||
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
|
||||
option (OPENDHT_LTO "Build with LTO" OFF)
|
||||
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
|
||||
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restbed and jsoncpp" OFF)
|
||||
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp" OFF)
|
||||
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 Restbed and jsoncpp" OFF)
|
||||
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
|
||||
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
|
||||
option (OPENDHT_TESTS "Add unit tests executable" OFF)
|
||||
|
||||
@@ -58,14 +58,20 @@ if (Jsoncpp_FOUND)
|
||||
endif()
|
||||
|
||||
if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
|
||||
find_package(Restbed REQUIRED)
|
||||
find_package(Restinio REQUIRED)
|
||||
if (Restinio_FOUND)
|
||||
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()
|
||||
endif()
|
||||
|
||||
# Build flags
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
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)
|
||||
@@ -100,8 +106,8 @@ endif ()
|
||||
if (Nettle_INCLUDE_DIRS)
|
||||
include_directories (SYSTEM "${Nettle_INCLUDE_DIRS}")
|
||||
endif ()
|
||||
if (Restbed_INCLUDE_DIR)
|
||||
include_directories (SYSTEM "${Restbed_INCLUDE_DIR}")
|
||||
if (Restinio_INCLUDE_DIR)
|
||||
include_directories (SYSTEM "${Restinio_INCLUDE_DIR}")
|
||||
endif ()
|
||||
if (Jsoncpp_INCLUDE_DIRS)
|
||||
include_directories (SYSTEM "${Jsoncpp_INCLUDE_DIRS}")
|
||||
@@ -151,8 +157,8 @@ list (APPEND opendht_SOURCES
|
||||
src/dhtrunner.cpp
|
||||
src/log.cpp
|
||||
src/peer_discovery.cpp
|
||||
src/network_utils.h
|
||||
src/network_utils.cpp
|
||||
src/thread_pool.cpp
|
||||
)
|
||||
|
||||
list (APPEND opendht_HEADERS
|
||||
@@ -177,6 +183,8 @@ list (APPEND opendht_HEADERS
|
||||
include/opendht/log.h
|
||||
include/opendht/log_enable.h
|
||||
include/opendht/peer_discovery.h
|
||||
include/opendht/thread_pool.h
|
||||
include/opendht/network_utils.h
|
||||
include/opendht.h
|
||||
)
|
||||
|
||||
@@ -199,8 +207,6 @@ if (OPENDHT_PROXY_SERVER)
|
||||
include/opendht/dht_proxy_server.h
|
||||
)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/thread_pool.h
|
||||
src/thread_pool.cpp
|
||||
src/dht_proxy_server.cpp
|
||||
)
|
||||
endif ()
|
||||
@@ -222,6 +228,10 @@ if (OPENDHT_PROXY_SERVER OR OPENDHT_PROXY_CLIENT)
|
||||
endif ()
|
||||
list (APPEND opendht_HEADERS
|
||||
include/opendht/proxy.h
|
||||
include/opendht/http.h
|
||||
)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/http.cpp
|
||||
)
|
||||
endif ()
|
||||
|
||||
@@ -255,8 +265,9 @@ if (OPENDHT_STATIC)
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
target_link_libraries(opendht-static
|
||||
PRIVATE ${Restbed_LIBRARY} ${argon2_LIBRARIES}
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Jsoncpp_LIBRARIES})
|
||||
PRIVATE ${argon2_LIBRARIES}
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
|
||||
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
|
||||
endif ()
|
||||
|
||||
@@ -274,7 +285,12 @@ if (OPENDHT_SHARED)
|
||||
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
target_link_libraries(opendht PRIVATE ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${Restbed_LIBRARY} ${Jsoncpp_LIBRARIES})
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
|
||||
|
||||
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
|
||||
endif ()
|
||||
|
||||
@@ -321,6 +337,8 @@ if (OPENDHT_TESTS)
|
||||
tests/dhtrunnertester.cpp
|
||||
tests/peerdiscoverytester.h
|
||||
tests/peerdiscoverytester.cpp
|
||||
tests/threadpooltester.h
|
||||
tests/threadpooltester.cpp
|
||||
)
|
||||
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND test_FILES
|
||||
|
||||
+22
-22
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -21,32 +21,32 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8BE7F14D-B227-4D54-9105-7E5473F2D0BA}</ProjectGuid>
|
||||
<RootNamespace>dhtchat</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -86,14 +86,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -102,14 +102,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -120,16 +120,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -140,16 +140,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;$(ProjectDir)contrib\build\include;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;Argon2Ref.lib;libgnutls.lib;opendht.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)contrib\build\lib\x64;$(ProjectDir)..\..\lib\x64;$(ProjectDir)vs2015\build</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
|
||||
+22
-22
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -21,32 +21,32 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BF92AECF-AA1D-4B05-9D00-0247E92A24B5}</ProjectGuid>
|
||||
<RootNamespace>dhtnode</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -86,14 +86,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -102,14 +102,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -120,16 +120,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -140,16 +140,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;$(ProjectDir)contrib\build\include;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;Argon2Ref.lib;libgnutls.lib;opendht.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)contrib\build\lib\x64;$(ProjectDir)..\..\lib\x64;$(ProjectDir)vs2015\build</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
|
||||
+22
-22
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -21,32 +21,32 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{78443BCD-4689-4007-A246-F8F34B27F561}</ProjectGuid>
|
||||
<RootNamespace>dhtscanner</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -86,14 +86,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -102,14 +102,14 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -120,16 +120,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\..\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;blake.lib;argon.lib;libgnutls.lib;opendht.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)..\..\lib\x64</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
@@ -140,16 +140,16 @@
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;$(ProjectDir)contrib\build\include;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<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>crypt32.lib;Argon2Ref.lib;libgnutls.lib;opendht.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)contrib\build\lib\x64;$(ProjectDir)..\..\lib\x64;$(ProjectDir)vs2015\build</AdditionalLibraryDirectories>
|
||||
<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>
|
||||
|
||||
+50
-35
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
@@ -19,6 +19,17 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\dht_proxy_client.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" />
|
||||
@@ -39,6 +50,8 @@
|
||||
<ClCompile Include="..\src\value.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
@@ -75,32 +88,32 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{711397CE-E5D5-467D-9457-8716C047E50C}</ProjectGuid>
|
||||
<RootNamespace>opendht</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<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>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -123,33 +136,34 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)..\..\</OutDir>
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>opendhtd</TargetName>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)..\..\</OutDir>
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<TargetName>opendht</TargetName>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)..\..\</OutDir>
|
||||
<TargetName>opendhtd</TargetName>
|
||||
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
|
||||
<TargetName>libopendht</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)..\..\</OutDir>
|
||||
<TargetName>opendht</TargetName>
|
||||
<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>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source</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;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
@@ -160,7 +174,7 @@ copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@@ -168,10 +182,11 @@ copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source</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;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>mkdir $(OutDir)\include
|
||||
@@ -182,7 +197,7 @@ copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
@@ -192,11 +207,11 @@ copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source</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;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
@@ -211,7 +226,7 @@ copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -222,11 +237,11 @@ copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)contrib\build\include;$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)contrib\build\msgpack-c\include;$(ProjectDir)contrib\build\argon2\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source</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;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
|
||||
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
@@ -241,7 +256,7 @@ copy ..\include\opendht\*.h $(OutDir)\include\opendht
|
||||
copy ..\include\opendht.h $(OutDir)\include\</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
<AdditionalLibraryDirectories>
|
||||
</AdditionalLibraryDirectories>
|
||||
|
||||
@@ -53,12 +53,26 @@
|
||||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\opendht\def.h" />
|
||||
<ClInclude Include="..\include\opendht\sockaddr.h" />
|
||||
<ClInclude Include="..\src\net.h" />
|
||||
<ClInclude Include="..\src\parsed_message.h" />
|
||||
<ClInclude Include="..\src\base64.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -139,6 +153,24 @@
|
||||
</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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<a id="user-content-opendht-" class="anchor" href="/savoirfairelinux/opendht/blob/master/README.md#opendht-" aria-hidden="true"></a>OpenDHT
|
||||
</h1>
|
||||
|
||||
A lightweight C++11 Distributed Hash Table implementation.
|
||||
A lightweight C++14 Distributed Hash Table implementation.
|
||||
|
||||
OpenDHT provides an easy to use distributed in-memory data store.
|
||||
Every node in the network can read and write values to the store.
|
||||
@@ -14,7 +14,7 @@ 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++11 map API
|
||||
* Clean and powerful C++14 map API
|
||||
* Python 3 bindings
|
||||
* REST API
|
||||
|
||||
@@ -27,13 +27,13 @@ Build instructions: <https://github.com/savoirfairelinux/opendht/wiki/Build-the-
|
||||
|
||||
#### How-to build a simple client app
|
||||
```bash
|
||||
g++ main.cpp -std=c++11 -lopendht -lgnutls
|
||||
g++ main.cpp -std=c++14 -lopendht -lgnutls
|
||||
```
|
||||
|
||||
## Examples
|
||||
### C++ example
|
||||
The `tools` directory includes simple example programs :
|
||||
* `dhtnode`, a command line tool, mostly used for debuging, allowing to perform operations supported by the library (get, put etc.) with text values.
|
||||
* `dhtnode`, a command line tool, allowing to run a DHT node and perform operations supported by the library (get, put etc.) with text values.
|
||||
* `dhtchat`, a very simple IM client working over the dht.
|
||||
|
||||
Example program launching a DHT node, connecting to the network and performing some basic operations:
|
||||
@@ -96,7 +96,7 @@ for r in results:
|
||||
- msgpack-c 1.2+, used for data serialization.
|
||||
- GnuTLS 3.3+, used for cryptographic operations.
|
||||
- Nettle 2.4+, a GnuTLS dependency for crypto.
|
||||
- (optional) restbed used for the REST API. commit fb84213e170bc171fecd825a8e47ed9f881a12cd (https://github.com/AmarOk1412/restbed/tree/async_read_until)
|
||||
- (optional) restinio used for the REST API.
|
||||
- (optional) jsoncpp 1.7.4-3+, used for the REST API.
|
||||
- Build tested with GCC 5.2+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
|
||||
- Build tested with Microsoft Visual Studio 2015
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
if(NOT Restbed_FOUND)
|
||||
find_path (Restbed_INCLUDE_DIR restbed
|
||||
HINTS
|
||||
"/usr/include"
|
||||
"/usr/local/include"
|
||||
"/opt/local/include")
|
||||
find_library(Restbed_LIBRARY restbed
|
||||
HINTS ${Restbed_ROOT_DIR} PATH_SUFFIXES lib)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Restbed DEFAULT_MSG Restbed_LIBRARY Restbed_INCLUDE_DIR)
|
||||
if (Restbed_INCLUDE_DIR)
|
||||
set(Restbed_FOUND TRUE)
|
||||
set(Restbed_LIBRARIES ${Restbed_LIBRARY})
|
||||
set(Restbed_INCLUDE_DIRS ${Restbed_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,14 @@
|
||||
# header-only does not produce a library
|
||||
if(NOT Restinio_FOUND)
|
||||
find_path (Restinio_INCLUDE_DIR restinio
|
||||
HINTS
|
||||
"/usr/include"
|
||||
"/usr/local/include"
|
||||
"/opt/local/include")
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Restinio DEFAULT_MSG Restinio_INCLUDE_DIR)
|
||||
if (Restinio_INCLUDE_DIR)
|
||||
set(Restinio_FOUND TRUE)
|
||||
set(Restinio_INCLUDE_DIRS ${Restinio_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
+8
-4
@@ -1,7 +1,7 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 1)
|
||||
m4_define([opendht_minor_version], 9)
|
||||
m4_define([opendht_patch_version], 1)
|
||||
m4_define([opendht_minor_version], 10)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
|
||||
@@ -142,8 +142,12 @@ AS_IF([test "x$have_jsoncpp" = "xyes"], [
|
||||
])
|
||||
|
||||
AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
AC_CHECK_LIB(restbed, exit,, AC_MSG_ERROR([Missing restbed files]))
|
||||
LDFLAGS="${LDFLAGS} -lrestbed"
|
||||
PKG_CHECK_MODULES([Asio], [fmt >= 1.12.2])
|
||||
PKG_CHECK_MODULES([Fmt], [fmt >= 5.3.0])
|
||||
# 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;])
|
||||
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"
|
||||
|
||||
+57
-35
@@ -1,22 +1,24 @@
|
||||
.TH DHTNODE 1 2016-07-29
|
||||
|
||||
.TH DHTNODE 1 2019-06-08
|
||||
.SH NAME
|
||||
.B dhtnode
|
||||
- a simple OpenDHT command line node runner.
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B dhtnode [-h]
|
||||
|
||||
.B dhtnode [-v [-l \fIlogfile\fP]] [-i] [-d] [-n \fInetwork_id\fP] [-p \fIlocal_port\fP] [-b \fIbootstrap_host\fP[:\fIport\fP]]
|
||||
|
||||
.B dhtnode
|
||||
[\fB\-h\fR]
|
||||
[\fB\-v\fR [\fB\-l\fR \fIlogfile\fR] [\fB\-L\fR]]
|
||||
[\fB\-i\fR [\fB\-\-save\-identity\fR \fIfile\fR]]
|
||||
[\fB\-d\fR] [\fB\-s\fR]
|
||||
[\fB\-n\fR \fInetwork_id\fR]
|
||||
[\fB\-p\fR \fIlocal_port\fR]
|
||||
[\fB\-b\fR \fIbootstrap_host\fR[:\fIport\fR]]
|
||||
[\fB\-\-certificate\fR \fIfile\fR]
|
||||
[\fB\-\-privkey\fR \fIfile\fR]
|
||||
[\fB\-\-privkey\-password\fR \fIpassword\fR]
|
||||
[\fB\-\-proxyserver\fR \fIport\fR]
|
||||
[\fB\-\-proxyclient\fR \fIserver\fR]
|
||||
.SH DESCRIPTION
|
||||
|
||||
This program runs a simple OpenDHT node in an interactive way. If you rather
|
||||
want to run the node in daemon mode, option \fB'-d'\fP is provided. When running
|
||||
in the interactive shell, you benefit from the readline capabilities for writing
|
||||
your commands such as command history. Here are the available commands in the
|
||||
interactive shell:
|
||||
|
||||
Runs an OpenDHT node, with a CLI (default) or as a daemon (with \fB'-d'\fP or \fB'-s'\fP).
|
||||
Commands available in the interactive shell are:
|
||||
.EE
|
||||
h, help Print this help message.
|
||||
q, quit Quit the program.
|
||||
@@ -37,43 +39,63 @@ interactive shell:
|
||||
private key.
|
||||
e [key] [dest] [str] Put string value at [key], encrypted for [dest] with
|
||||
its public key (if found).
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
\fB-h\fP
|
||||
\fB\-h\fP
|
||||
Prints some help.
|
||||
|
||||
.TP
|
||||
\fB-v\fP
|
||||
Enable the verbose mode (log to stdout by default)
|
||||
|
||||
\fB\-v\fP
|
||||
Enable the verbose mode (log to stdout/stderr by default)
|
||||
.TP
|
||||
\fB-l\fP \fIlog_file\fP
|
||||
Write log to file instead of stdout
|
||||
|
||||
\fB\-l\fP \fIlog_file\fP
|
||||
Write log to file instead of stdout/stderr
|
||||
.TP
|
||||
\fB-i\fP
|
||||
\fB\-L\fP
|
||||
Write log to syslog instead of stdout/stderr
|
||||
.TP
|
||||
\fB\-i\fP
|
||||
Generate cryptographic identity for the node.
|
||||
|
||||
.TP
|
||||
\fB-d\fP
|
||||
\fB\-\-save\-identity\fP \fIfile\fP
|
||||
Save generated identity (certificate and private key) to given file prefix.
|
||||
.TP
|
||||
\fB\-\-certificate\fP \fIfile\fP
|
||||
Load identity certificate from given file.
|
||||
.TP
|
||||
\fB\-\-privkey\fP \fIfile\fP
|
||||
Load identity private key from given file.
|
||||
.TP
|
||||
\fB\-\-privkey\-password\fP \fIpassword\fP
|
||||
Password to use for private key encryption or decryption (optional).
|
||||
.TP
|
||||
\fB\-d\fP
|
||||
Run the program in daemon mode (will fork in the background).
|
||||
|
||||
.TP
|
||||
\fB-n\fP \fInetwork_id\fP
|
||||
\fB\-s\fP
|
||||
Run the program in service mode (non\-forking daemon).
|
||||
.TP
|
||||
\fB\-D\fP
|
||||
Enables multicast automatic local peer discovery.
|
||||
.TP
|
||||
\fB\-f\fP \fIfile\fP
|
||||
Specify a file path to persist/load the node state.
|
||||
.TP
|
||||
\fB\-n\fP \fInetwork_id\fP
|
||||
Specify the network id. This let you connect to distinct networks and prevents
|
||||
the merge of two different networks (available since OpenDHT v0.6.1).
|
||||
|
||||
.TP
|
||||
\fB-p\fP \fIlocal_port\fP
|
||||
Use port \fIlocal_port\fP for the program to bind to.
|
||||
|
||||
\fB\-p\fP \fIlocal_port\fP
|
||||
Use UDP port \fIlocal_port\fP for the program to bind to.
|
||||
.TP
|
||||
\fB-b\fP \fIbootstrap_host\fP[:\fIport\fP]
|
||||
\fB\-b\fP \fIbootstrap_host\fP[:\fIport\fP]
|
||||
The program needs to be given a node to connect to the network. You use this
|
||||
option to provide the ip address of that node.
|
||||
|
||||
.TP
|
||||
\fB\-\-proxyserver\fP \fIlocal_port\fP
|
||||
Run a proxy server bound to this DHT node on HTTP port \fIlocal_port\fP
|
||||
.TP
|
||||
\fB\-\-proxyclient\fP \fIserver\fP
|
||||
Run this DHT node in proxy client mode, and connect to \fIserver\fP
|
||||
.SH AUTHORS
|
||||
.TP
|
||||
Program written by
|
||||
|
||||
+39
-12
@@ -1,18 +1,45 @@
|
||||
FROM ubuntu:16.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
RUN apt-get update && apt-get install -y build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libuv1-dev cython3 python3-dev libcppunit-dev libjsoncpp-dev libasio-dev libssl-dev python3-setuptools && apt-get clean
|
||||
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 libcppunit-dev libjsoncpp-dev \
|
||||
libasio-dev libssl-dev python3-setuptools \
|
||||
&& apt-get clean
|
||||
|
||||
# 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
|
||||
#patch for https://github.com/Stiffstream/restinio-conan-example/issues/2
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3-pip libasio-dev
|
||||
RUN pip3 install --upgrade cmake
|
||||
#install conan & add restinio remotes
|
||||
RUN pip3 install conan && \
|
||||
conan remote add stiffstream https://api.bintray.com/conan/stiffstream/public && \
|
||||
conan remote add public-conan https://api.bintray.com/conan/bincrafters/public-conan
|
||||
#setup restinio docker project
|
||||
RUN mkdir restinio-conan
|
||||
COPY conan/restinio/conanfile.txt restinio-conan/conanfile.txt
|
||||
COPY conan/restinio/conanfile.py restinio-conan/conanfile.py
|
||||
#build restinio from source
|
||||
RUN echo "*** Installing RESTinio & dependencies ***" \
|
||||
&& cd restinio-conan \
|
||||
&& conan source . \
|
||||
&& conan install -o restinio:boost_libs=none --build=missing . \
|
||||
&& conan package . -pf /usr/local \
|
||||
&& cd ../ && rm -rf restinio*
|
||||
#installing dependencies
|
||||
RUN echo "*** Installing asio & fmt dependencies ***" \
|
||||
&& cp -r ~/.conan/data/asio/*/bincrafters/stable/package/*/include/* /usr/local/include/ \
|
||||
&& cp -r ~/.conan/data/fmt/*/bincrafters/stable/package/*/lib/* /usr/local/lib/ \
|
||||
&& cp -r ~/.conan/data/fmt/*/bincrafters/stable/package/*/include/* /usr/local/include/
|
||||
#build http_parser fork
|
||||
RUN echo "*** Building http_parser dependency for custom HTTP methods ***" \
|
||||
&& git clone https://github.com/eao197/http-parser.git \
|
||||
&& cd http-parser && make -j8 && make install PREFIX=/usr \
|
||||
&& cd ../ && rm -rf restinio-conan/
|
||||
|
||||
#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
|
||||
&& 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
|
||||
+36
-13
@@ -1,23 +1,46 @@
|
||||
FROM ubuntu:16.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y llvm llvm-dev clang make cmake git wget libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev libasio-dev cython3 python3-dev python3-setuptools libcppunit-dev \
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
|
||||
&& apt-get install -y llvm llvm-dev clang make cmake git wget libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev libasio-dev cython3 python3-dev python3-setuptools libcppunit-dev python3-pip \
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
|
||||
|
||||
ENV CC cc
|
||||
ENV CXX c++
|
||||
|
||||
# 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
|
||||
#patch for https://github.com/Stiffstream/restinio-conan-example/issues/2
|
||||
RUN apt-get update && apt-get install -y \
|
||||
python3-pip libasio-dev
|
||||
RUN pip3 install --upgrade cmake
|
||||
#install conan & add restinio remotes
|
||||
RUN pip3 install conan && \
|
||||
conan remote add stiffstream https://api.bintray.com/conan/stiffstream/public && \
|
||||
conan remote add public-conan https://api.bintray.com/conan/bincrafters/public-conan
|
||||
#setup restinio docker project
|
||||
RUN mkdir restinio-conan
|
||||
COPY conan/restinio/conanfile.txt restinio-conan/conanfile.txt
|
||||
COPY conan/restinio/conanfile.py restinio-conan/conanfile.py
|
||||
#build restinio from source
|
||||
RUN echo "*** Installing RESTinio & dependencies ***" \
|
||||
&& cd restinio-conan \
|
||||
&& conan source . \
|
||||
&& conan install -o restinio:boost_libs=none --build=missing . \
|
||||
&& conan package . -pf /usr/local \
|
||||
&& cd ../ && rm -rf restinio*
|
||||
#installing dependencies
|
||||
RUN echo "*** Installing asio & fmt dependencies ***" \
|
||||
&& cp -r ~/.conan/data/asio/*/bincrafters/stable/package/*/include/* /usr/local/include/ \
|
||||
&& cp -r ~/.conan/data/fmt/*/bincrafters/stable/package/*/lib/* /usr/local/lib/ \
|
||||
&& cp -r ~/.conan/data/fmt/*/bincrafters/stable/package/*/include/* /usr/local/include/
|
||||
#build http_parser fork
|
||||
RUN echo "*** Building http_parser dependency for custom HTTP methods ***" \
|
||||
&& git clone https://github.com/eao197/http-parser.git \
|
||||
&& cd http-parser && make -j8 && make install PREFIX=/usr \
|
||||
&& cd ../ && rm -rf restinio-conan/
|
||||
|
||||
#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
|
||||
&& 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,59 @@
|
||||
from conans import ConanFile, CMake, tools
|
||||
import os
|
||||
|
||||
|
||||
class SobjectizerConan(ConanFile):
|
||||
name = "restinio"
|
||||
version = "0.5.1"
|
||||
|
||||
license = "BSD-3-Clause"
|
||||
url = "https://github.com/Stiffstream/restinio-conan"
|
||||
|
||||
description = (
|
||||
"RESTinio is a header-only C++14 library that gives you "
|
||||
"an embedded HTTP/Websocket server."
|
||||
)
|
||||
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
options = {'boost_libs': ['none', 'static', 'shared']}
|
||||
default_options = {'boost_libs': 'none'}
|
||||
generators = "cmake"
|
||||
source_subfolder = "restinio"
|
||||
build_policy = "missing"
|
||||
|
||||
def requirements(self):
|
||||
self.requires.add("http-parser/2.8.1@bincrafters/stable")
|
||||
self.requires.add("fmt/5.3.0@bincrafters/stable")
|
||||
|
||||
if self.options.boost_libs == "none":
|
||||
self.requires.add("asio/1.12.2@bincrafters/stable")
|
||||
else:
|
||||
self.requires.add("boost/1.69.0@conan/stable")
|
||||
if self.options.boost_libs == "shared":
|
||||
self.options["boost"].shared = True
|
||||
else:
|
||||
self.options["boost"].shared = False
|
||||
|
||||
def source(self):
|
||||
source_url = "https://bitbucket.org/sobjectizerteam/restinio/downloads"
|
||||
tools.get("{0}/restinio-{1}.zip".format(source_url, self.version))
|
||||
extracted_dir = "restinio-" + self.version
|
||||
os.rename(extracted_dir, self.source_subfolder)
|
||||
|
||||
def _configure_cmake(self):
|
||||
cmake = CMake(self)
|
||||
cmake.definitions['RESTINIO_INSTALL'] = True
|
||||
cmake.definitions['RESTINIO_FIND_DEPS'] = False
|
||||
cmake.definitions['RESTINIO_USE_BOOST_ASIO'] = self.options.boost_libs
|
||||
cmake.configure(source_folder = self.source_subfolder + "/dev/restinio")
|
||||
return cmake
|
||||
|
||||
def package(self):
|
||||
cmake = self._configure_cmake()
|
||||
self.output.info(cmake.definitions)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.info.header_only()
|
||||
if self.options.boost_libs != "none":
|
||||
self.cpp_info.defines.append("RESTINIO_USE_BOOST_ASIO")
|
||||
@@ -0,0 +1,11 @@
|
||||
[requires]
|
||||
restinio/0.5.1@stiffstream/stable
|
||||
|
||||
[generators]
|
||||
cmake
|
||||
|
||||
[options]
|
||||
|
||||
[imports]
|
||||
bin, *.dll -> ./bin # Copies all dll files from packages bin folder to my "bin" folder
|
||||
lib, *.dylib* -> ./bin # Copies all dylib files from packages lib folder to my "bin" folder
|
||||
@@ -22,7 +22,6 @@
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
#include "opendht/dht_proxy_server.h"
|
||||
#endif
|
||||
#include "opendht/log.h"
|
||||
#include "opendht/default_types.h"
|
||||
#ifdef OPENDHT_INDEXATION
|
||||
#include "opendht/indexation/pht.h"
|
||||
|
||||
@@ -89,23 +89,23 @@ struct OPENDHT_PUBLIC NodeInfo {
|
||||
*/
|
||||
struct OPENDHT_PUBLIC Config {
|
||||
/** DHT node ID */
|
||||
InfoHash node_id;
|
||||
InfoHash node_id {};
|
||||
|
||||
/**
|
||||
* DHT network ID. A node will only talk with other nodes having
|
||||
* the same network ID.
|
||||
* Network ID 0 (default) represents the main public network.
|
||||
*/
|
||||
NetId network;
|
||||
NetId network {0};
|
||||
|
||||
/** For testing purposes only, enables bootstrap mode */
|
||||
bool is_bootstrap;
|
||||
bool is_bootstrap {false};
|
||||
|
||||
/** Makes the DHT responsible to maintain its stored values. Consumes more ressources. */
|
||||
bool maintain_storage;
|
||||
bool maintain_storage {false};
|
||||
|
||||
/** 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;
|
||||
std::string persist_path {};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -113,8 +113,8 @@ struct OPENDHT_PUBLIC Config {
|
||||
*/
|
||||
struct OPENDHT_PUBLIC SecureDhtConfig
|
||||
{
|
||||
Config node_config;
|
||||
crypto::Identity id;
|
||||
Config node_config {};
|
||||
crypto::Identity id {};
|
||||
};
|
||||
|
||||
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
|
||||
|
||||
@@ -654,6 +654,7 @@ OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode", co
|
||||
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name, const Identity& ca, bool is_ca);
|
||||
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name = "dhtnode", const Identity& ca = {});
|
||||
|
||||
OPENDHT_PUBLIC void saveIdentity(const Identity& id, const std::string& path, const std::string& privkey_password = {});
|
||||
|
||||
/**
|
||||
* Performs SHA512, SHA256 or SHA1, depending on hash_length.
|
||||
|
||||
@@ -114,8 +114,10 @@ public:
|
||||
ImMessage() {}
|
||||
ImMessage(dht::Value::Id id, std::string&& m, long d = 0)
|
||||
: id(id), msg(std::move(m)), date(d) {}
|
||||
ImMessage(dht::Value::Id id, std::string&& dt, std::string&& m, long d = 0)
|
||||
ImMessage(dht::Value::Id id, std::string &&dt, std::string &&m, long d = 0)
|
||||
: id(id), msg(std::move(m)), datatype(std::move(dt)), date(d) {}
|
||||
ImMessage(dht::Value::Id id, std::string &&dt, std::string &&m, std::map<std::string, std::string> &&md, long d = 0)
|
||||
: id(id), msg(std::move(m)), datatype(std::move(dt)), metadatas(std::move(md)), date(d) {}
|
||||
|
||||
virtual void unpackValue(const Value& v) override {
|
||||
to = v.recipient;
|
||||
@@ -126,10 +128,11 @@ public:
|
||||
dht::Value::Id id {0};
|
||||
std::string msg;
|
||||
std::string datatype;
|
||||
std::map<std::string, std::string> metadatas;
|
||||
long date {0};
|
||||
ImStatus status {ImStatus::NONE};
|
||||
|
||||
MSGPACK_DEFINE_MAP(id, msg, date, status, datatype)
|
||||
MSGPACK_DEFINE_MAP(id, msg, date, status, datatype, metadatas)
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC TrustRequest : public EncryptedValue<TrustRequest>
|
||||
|
||||
+14
-20
@@ -68,7 +68,7 @@ public:
|
||||
* Initialise the Dht with two open sockets (for IPv4 and IP6)
|
||||
* and an ID for the node.
|
||||
*/
|
||||
Dht(const int& s, const int& s6, const Config& config);
|
||||
Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Logger& l = {});
|
||||
virtual ~Dht();
|
||||
|
||||
/**
|
||||
@@ -85,6 +85,8 @@ public:
|
||||
return std::max(getStatus(AF_INET), getStatus(AF_INET6));
|
||||
}
|
||||
|
||||
net::DatagramSocket* getSocket() const override { return network_engine.getSocket(); };
|
||||
|
||||
/**
|
||||
* Performs final operations before quitting.
|
||||
*/
|
||||
@@ -120,7 +122,7 @@ public:
|
||||
|
||||
void pingNode(const sockaddr*, socklen_t, DoneCallbackSimple&& cb={}) override;
|
||||
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr&) 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));
|
||||
}
|
||||
@@ -274,19 +276,19 @@ public:
|
||||
std::string getStorageLog() const override;
|
||||
std::string getStorageLog(const InfoHash&) const override;
|
||||
|
||||
std::string getRoutingTablesLog(sa_family_t) const;
|
||||
std::string getSearchesLog(sa_family_t) const;
|
||||
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;
|
||||
std::string getRoutingTablesLog(sa_family_t) const override;
|
||||
std::string getSearchesLog(sa_family_t) const override;
|
||||
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const override;
|
||||
|
||||
void dumpTables() const;
|
||||
std::vector<unsigned> getNodeMessageStats(bool in = false) {
|
||||
void dumpTables() const override;
|
||||
std::vector<unsigned> getNodeMessageStats(bool in = false) override {
|
||||
return network_engine.getNodeMessageStats(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the in-memory storage limit in bytes
|
||||
*/
|
||||
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) {
|
||||
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
|
||||
max_store_size = limit;
|
||||
}
|
||||
|
||||
@@ -294,7 +296,7 @@ public:
|
||||
* Returns the total memory usage of stored values and the number
|
||||
* of stored values.
|
||||
*/
|
||||
std::pair<size_t, size_t> getStoreSize() const {
|
||||
std::pair<size_t, size_t> getStoreSize() const override {
|
||||
return {total_store_size, total_values};
|
||||
}
|
||||
|
||||
@@ -436,17 +438,9 @@ private:
|
||||
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; }
|
||||
Bucket* findBucket(const InfoHash& id, sa_family_t af) {
|
||||
RoutingTable::iterator b;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
b = buckets4.findBucket(id);
|
||||
return b == buckets4.end() ? nullptr : &(*b);
|
||||
case AF_INET6:
|
||||
b = buckets6.findBucket(id);
|
||||
return b == buckets6.end() ? nullptr : &(*b);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
auto& b = buckets(af);
|
||||
auto it = b.findBucket(id);
|
||||
return it == b.end() ? nullptr : &(*it);
|
||||
}
|
||||
const Bucket* findBucket(const InfoHash& id, sa_family_t af) const {
|
||||
return const_cast<Dht*>(this)->findBucket(id, af);
|
||||
|
||||
@@ -23,9 +23,14 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
namespace net {
|
||||
class DatagramSocket;
|
||||
}
|
||||
|
||||
class OPENDHT_PUBLIC DhtInterface {
|
||||
public:
|
||||
DhtInterface() = default;
|
||||
DhtInterface(const Logger& l) : DHT_LOG(l) {};
|
||||
virtual ~DhtInterface() = default;
|
||||
|
||||
// [[deprecated]]
|
||||
@@ -39,6 +44,8 @@ public:
|
||||
virtual NodeStatus getStatus(sa_family_t af) const = 0;
|
||||
virtual NodeStatus getStatus() const = 0;
|
||||
|
||||
virtual net::DatagramSocket* getSocket() const { return {}; };
|
||||
|
||||
/**
|
||||
* Get the ID of the DHT node.
|
||||
*/
|
||||
@@ -72,7 +79,7 @@ public:
|
||||
|
||||
virtual void pingNode(const sockaddr*, socklen_t, DoneCallbackSimple&& cb={}) = 0;
|
||||
|
||||
virtual time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr&) = 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;
|
||||
|
||||
/**
|
||||
@@ -214,13 +221,18 @@ public:
|
||||
/**
|
||||
* Enable or disable logging of DHT internal messages
|
||||
*/
|
||||
virtual void setLoggers(LogMethod error = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG)
|
||||
{
|
||||
virtual void setLoggers(LogMethod error = {}, LogMethod warn = {}, LogMethod debug = {}) {
|
||||
DHT_LOG.DBG = debug;
|
||||
DHT_LOG.WARN = warn;
|
||||
DHT_LOG.ERR = error;
|
||||
}
|
||||
|
||||
virtual void setLogger(const Logger& l) {
|
||||
DHT_LOG.DBG = l.DBG;
|
||||
DHT_LOG.WARN = l.WARN;
|
||||
DHT_LOG.ERR = l.ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
|
||||
*/
|
||||
@@ -238,8 +250,6 @@ public:
|
||||
virtual void pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
|
||||
|
||||
protected:
|
||||
bool logFilerEnable_ {};
|
||||
InfoHash logFiler_ {};
|
||||
Logger DHT_LOG;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2016-2019 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>
|
||||
*
|
||||
* 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
|
||||
@@ -20,23 +21,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "def.h"
|
||||
#include "dht_interface.h"
|
||||
#include "scheduler.h"
|
||||
#include "proxy.h"
|
||||
|
||||
namespace restbed {
|
||||
class Request;
|
||||
}
|
||||
#include <restinio/all.hpp>
|
||||
#include <http_parser.h>
|
||||
#include <json/json.h>
|
||||
#include "http.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace http {
|
||||
class Client;
|
||||
}
|
||||
|
||||
namespace dht {
|
||||
|
||||
class OPENDHT_PUBLIC DhtProxyClient final : public DhtInterface {
|
||||
@@ -44,7 +52,11 @@ public:
|
||||
|
||||
DhtProxyClient();
|
||||
|
||||
explicit DhtProxyClient(std::function<void()> loopSignal, const std::string& serverHost, const std::string& pushClientId = "");
|
||||
explicit DhtProxyClient(std::function<void()> loopSignal, const std::string& serverHost,
|
||||
const std::string& pushClientId = "",
|
||||
std::shared_ptr<dht::Logger> logger = {});
|
||||
|
||||
restinio::http_header_fields_t initHeaderFields();
|
||||
|
||||
virtual void setPushNotificationToken(const std::string& token) {
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
@@ -172,6 +184,10 @@ public:
|
||||
virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w={}) {
|
||||
return listen(key, bindGetCb(cb), std::forward<Value::Filter>(f), std::forward<Where>(w));
|
||||
}
|
||||
/*
|
||||
* This function relies on the cache implementation.
|
||||
* It means that there are no true cancel here, it keeps the caching in higher priority.
|
||||
*/
|
||||
virtual bool cancelListen(const InfoHash& key, size_t token);
|
||||
|
||||
/**
|
||||
@@ -180,12 +196,11 @@ public:
|
||||
*/
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>& notification);
|
||||
|
||||
time_point periodic(const uint8_t*, size_t, const SockAddr&);
|
||||
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) {
|
||||
time_point periodic(const uint8_t*, size_t, SockAddr);
|
||||
time_point periodic(const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen) {
|
||||
return periodic(buf, buflen, SockAddr(from, fromlen));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Similar to Dht::get, but sends a Query to filter data remotely.
|
||||
* @param key the key for which to query data for.
|
||||
@@ -262,6 +277,7 @@ private:
|
||||
* Start the connection with a server.
|
||||
*/
|
||||
void startProxy();
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Get informations from the proxy node
|
||||
@@ -269,25 +285,34 @@ private:
|
||||
*/
|
||||
struct InfoState;
|
||||
void getProxyInfos();
|
||||
void handleProxyStatus(const asio::error_code &ec, std::shared_ptr<InfoState> infoState);
|
||||
void onProxyInfos(const Json::Value& val, sa_family_t family);
|
||||
SockAddr parsePublicAddress(const Json::Value& val);
|
||||
|
||||
void opFailed();
|
||||
|
||||
bool doCancelListen(const InfoHash& key, size_t token);
|
||||
void handleExpireListener(const asio::error_code &ec, const InfoHash& key);
|
||||
|
||||
struct Listener;
|
||||
struct ListenState;
|
||||
enum class ListenMethod {
|
||||
LISTEN,
|
||||
SUBSCRIBE,
|
||||
RESUBSCRIBE,
|
||||
};
|
||||
void sendListen(const std::shared_ptr<restbed::Request> &request,
|
||||
const ValueCallback &, const Value::Filter &filter,
|
||||
const Sp<ListenState> &state,
|
||||
/**
|
||||
* Send Listen with httpClient_
|
||||
*/
|
||||
void sendListen(const restinio::http_request_header_t header,
|
||||
const ValueCallback &cb,
|
||||
const Sp<ListenState> &state, Listener &listener,
|
||||
ListenMethod method = ListenMethod::LISTEN);
|
||||
void handleResubscribe(const asio::error_code &ec, const InfoHash& key,
|
||||
const size_t token, std::shared_ptr<ListenState> state);
|
||||
|
||||
void doPut(const InfoHash&, Sp<Value>, DoneCallback, time_point created, bool permanent);
|
||||
void handleRefreshPut(const asio::error_code &ec, const InfoHash& key, const Value::Id id,
|
||||
std::shared_ptr<std::atomic_bool> ok);
|
||||
|
||||
/**
|
||||
* Initialize statusIpvX_
|
||||
@@ -302,9 +327,23 @@ private:
|
||||
*/
|
||||
void cancelAllOperations();
|
||||
|
||||
std::string serverHost_;
|
||||
std::pair<std::string, std::string> serverHostService_;
|
||||
std::string pushClientId_;
|
||||
|
||||
/*
|
||||
* ASIO I/O Context for sockets in httpClient_
|
||||
* Note: Each context is used in one thread only
|
||||
*/
|
||||
asio::io_context httpContext_;
|
||||
/*
|
||||
* http::Client instance used on http io_context
|
||||
*/
|
||||
std::unique_ptr<http::Client> httpClient_;
|
||||
/*
|
||||
* Thread for executing the http io_context.run() blocking call
|
||||
*/
|
||||
std::thread httpClientThread_;
|
||||
|
||||
mutable std::mutex lockCurrentProxyInfos_;
|
||||
NodeStatus statusIpv4_ {NodeStatus::Disconnected};
|
||||
NodeStatus statusIpv6_ {NodeStatus::Disconnected};
|
||||
@@ -321,41 +360,28 @@ private:
|
||||
/**
|
||||
* Store listen requests.
|
||||
*/
|
||||
struct Listener;
|
||||
struct ProxySearch;
|
||||
|
||||
size_t listenerToken_ {0};
|
||||
std::map<InfoHash, ProxySearch> searches_;
|
||||
mutable std::mutex searchLock_;
|
||||
|
||||
/**
|
||||
* Store current put and get requests.
|
||||
*/
|
||||
struct Operation
|
||||
{
|
||||
std::shared_ptr<restbed::Request> req;
|
||||
std::thread thread;
|
||||
std::shared_ptr<std::atomic_bool> finished;
|
||||
};
|
||||
std::vector<Operation> operations_;
|
||||
std::mutex lockOperations_;
|
||||
/**
|
||||
* Callbacks should be executed in the main thread.
|
||||
*/
|
||||
std::vector<std::function<void()>> callbacks_;
|
||||
std::mutex lockCallbacks;
|
||||
std::mutex lockCallbacks_;
|
||||
|
||||
Sp<InfoState> infoState_;
|
||||
std::thread statusThread_;
|
||||
Sp<asio::steady_timer> statusTimer_;
|
||||
mutable std::mutex statusLock_;
|
||||
|
||||
Scheduler scheduler;
|
||||
/**
|
||||
* Retrieve if we can connect to the proxy (update statusIpvX_)
|
||||
*/
|
||||
void confirmProxy();
|
||||
Sp<Scheduler::Job> nextProxyConfirmation {};
|
||||
Sp<Scheduler::Job> listenerRestart {};
|
||||
void handleProxyConfirm(const asio::error_code &ec);
|
||||
Sp<asio::steady_timer> nextProxyConfirmationTimer_;
|
||||
Sp<asio::steady_timer> listenerRestartTimer_;
|
||||
|
||||
/**
|
||||
* Relaunch LISTEN requests if the client disconnect/reconnect.
|
||||
@@ -366,7 +392,7 @@ private:
|
||||
* Refresh a listen via a token
|
||||
* @param token
|
||||
*/
|
||||
void resubscribe(const InfoHash& key, Listener& listener);
|
||||
void resubscribe(const InfoHash& key, const size_t token, Listener& listener);
|
||||
|
||||
/**
|
||||
* If we want to use push notifications by default.
|
||||
@@ -377,11 +403,13 @@ private:
|
||||
const std::function<void()> loopSignal_;
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
void fillBody(std::shared_ptr<restbed::Request> request, bool resubscribe);
|
||||
std::string fillBody(bool resubscribe);
|
||||
void getPushRequest(Json::Value&) const;
|
||||
#endif // OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
std::atomic_bool isDestroying_ {false};
|
||||
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2017-2019 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>
|
||||
*
|
||||
* 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,16 +27,43 @@
|
||||
#include "scheduler.h"
|
||||
#include "sockaddr.h"
|
||||
#include "value.h"
|
||||
#include "dht_proxy_client.h"
|
||||
|
||||
#include <thread>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <restbed>
|
||||
#include <restinio/all.hpp>
|
||||
#include "http.h"
|
||||
|
||||
#ifdef OPENDHT_JSONCPP
|
||||
#include <json/json.h>
|
||||
#endif
|
||||
|
||||
namespace http {
|
||||
class Client;
|
||||
class opendht_logger_t;
|
||||
struct ListenerSession;
|
||||
class ConnectionListener;
|
||||
}
|
||||
|
||||
namespace restinio {
|
||||
class opendht_logger_t;
|
||||
struct custom_http_methods_t;
|
||||
}
|
||||
|
||||
using RestRouter = restinio::router::express_router_t<>;
|
||||
struct RestRouterTraits : public restinio::default_traits_t
|
||||
{
|
||||
using timer_manager_t = restinio::asio_timer_manager_t;
|
||||
using http_methods_mapper_t = restinio::custom_http_methods_t;
|
||||
using logger_t = restinio::opendht_logger_t;
|
||||
using request_handler_t = RestRouter;
|
||||
using connection_state_listener_t = http::ConnectionListener;
|
||||
};
|
||||
using ServerSettings = restinio::run_on_this_thread_settings_t<RestRouterTraits>;
|
||||
using RequestStatus = restinio::request_handling_status_t;
|
||||
using ResponseByParts = restinio::chunked_output_t;
|
||||
using ResponseByPartsBuilder = restinio::response_builder_t<ResponseByParts>;
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
}
|
||||
@@ -43,7 +71,6 @@ namespace Json {
|
||||
namespace dht {
|
||||
|
||||
class DhtRunner;
|
||||
class ThreadPool;
|
||||
|
||||
/**
|
||||
* Describes the REST API
|
||||
@@ -59,7 +86,9 @@ public:
|
||||
* @note if the server fails to start (if port is already used or reserved),
|
||||
* it will fails silently
|
||||
*/
|
||||
DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port = 8000, const std::string& pushServer = "");
|
||||
DhtProxyServer(std::shared_ptr<DhtRunner> dht, in_port_t port = 8000,
|
||||
const std::string& pushServer = "",
|
||||
std::shared_ptr<dht::Logger> logger = {});
|
||||
virtual ~DhtProxyServer();
|
||||
|
||||
DhtProxyServer(const DhtProxyServer& other) = delete;
|
||||
@@ -123,6 +152,14 @@ public:
|
||||
void stop();
|
||||
|
||||
private:
|
||||
template <typename HttpResponse>
|
||||
HttpResponse initHttpResponse(HttpResponse response) const;
|
||||
|
||||
ServerSettings makeHttpServerSettings(
|
||||
const unsigned int max_pipelined_requests = 16);
|
||||
|
||||
std::unique_ptr<RestRouter> createRestRouter();
|
||||
|
||||
/**
|
||||
* Return the PublicKey id, the node id and node stats
|
||||
* Method: GET "/"
|
||||
@@ -130,7 +167,8 @@ private:
|
||||
* On error: HTTP 503, body: {"err":"xxxx"}
|
||||
* @param session
|
||||
*/
|
||||
void getNodeInfo(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus getNodeInfo(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params) const;
|
||||
|
||||
/**
|
||||
* Return ServerStats in JSON format
|
||||
@@ -138,7 +176,8 @@ private:
|
||||
* Result: HTTP 200, body: Node infos in JSON format
|
||||
* @param session
|
||||
*/
|
||||
void getStats(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus getStats(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Return Values of an infoHash
|
||||
@@ -150,7 +189,8 @@ private:
|
||||
* On error: HTTP 503, body: {"err":"xxxx"}
|
||||
* @param session
|
||||
*/
|
||||
void get(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus get(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Listen incoming Values of an infoHash.
|
||||
@@ -162,7 +202,8 @@ private:
|
||||
* On error: HTTP 503, body: {"err":"xxxx"}
|
||||
* @param session
|
||||
*/
|
||||
void listen(const std::shared_ptr<restbed::Session>& session);
|
||||
RequestStatus listen(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Put a value on the DHT
|
||||
@@ -173,9 +214,10 @@ private:
|
||||
* HTTP 400, body: {"err":"xxxx"} if bad json or HTTP 502 if put fails
|
||||
* @param session
|
||||
*/
|
||||
void put(const std::shared_ptr<restbed::Session>& session);
|
||||
RequestStatus put(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
void cancelPut(const InfoHash& key, Value::Id vid);
|
||||
void handleCancelPermamentPut(const asio::error_code &ec, const InfoHash& key, Value::Id vid);
|
||||
|
||||
#ifdef OPENDHT_PROXY_SERVER_IDENTITY
|
||||
/**
|
||||
@@ -187,7 +229,8 @@ private:
|
||||
* HTTP 400, body: {"err":"xxxx"} if bad json
|
||||
* @param session
|
||||
*/
|
||||
void putSigned(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus putSigned(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params) const;
|
||||
|
||||
/**
|
||||
* Put a value to encrypt by the proxy on the DHT
|
||||
@@ -198,7 +241,9 @@ private:
|
||||
* HTTP 400, body: {"err":"xxxx"} if bad json
|
||||
* @param session
|
||||
*/
|
||||
void putEncrypted(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus putEncrypted(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
#endif // OPENDHT_PROXY_SERVER_IDENTITY
|
||||
|
||||
/**
|
||||
@@ -211,7 +256,8 @@ private:
|
||||
* On error: HTTP 503, body: {"err":"xxxx"}
|
||||
* @param session
|
||||
*/
|
||||
void getFiltered(const std::shared_ptr<restbed::Session>& session) const;
|
||||
RequestStatus getFiltered(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Respond allowed Methods
|
||||
@@ -220,13 +266,8 @@ private:
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
|
||||
* @param session
|
||||
*/
|
||||
void handleOptionsMethod(const std::shared_ptr<restbed::Session>& session) const;
|
||||
|
||||
/**
|
||||
* Remove finished listeners
|
||||
* @param testSession if we remove the listener only if the session is closed
|
||||
*/
|
||||
void removeClosedListeners(bool testSession = true);
|
||||
RequestStatus options(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
/**
|
||||
@@ -238,7 +279,9 @@ private:
|
||||
* so you need to refresh the operation each six hours.
|
||||
* @param session
|
||||
*/
|
||||
void subscribe(const std::shared_ptr<restbed::Session>& session);
|
||||
RequestStatus subscribe(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Unsubscribe to push notifications for an iOS or Android device.
|
||||
* Method: UNSUBSCRIBE "/{InfoHash: .*}"
|
||||
@@ -246,7 +289,9 @@ private:
|
||||
* Return: nothing
|
||||
* @param session
|
||||
*/
|
||||
void unsubscribe(const std::shared_ptr<restbed::Session>& session);
|
||||
RequestStatus unsubscribe(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
/**
|
||||
* Send a push notification via a gorush push gateway
|
||||
* @param key of the device
|
||||
@@ -254,49 +299,65 @@ private:
|
||||
*/
|
||||
void sendPushNotification(const std::string& key, Json::Value&& json, bool isAndroid) const;
|
||||
|
||||
/**
|
||||
* Send push notification with an expire timeout.
|
||||
* @param ec
|
||||
* @param pushToken
|
||||
* @param json
|
||||
* @param isAndroid
|
||||
*/
|
||||
void handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
|
||||
Json::Value json, const bool isAndroid);
|
||||
|
||||
/**
|
||||
* Remove a push listener between a client and a hash
|
||||
* @param ec
|
||||
* @param pushToken
|
||||
* @param key
|
||||
* @param clientId
|
||||
*/
|
||||
void cancelPushListen(const std::string& pushToken, const InfoHash& key, const std::string& clientId);
|
||||
|
||||
void handleCancelPushListen(const asio::error_code &ec, const std::string pushToken,
|
||||
const InfoHash key, const std::string clientId);
|
||||
|
||||
#endif //OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
void handlePrintStats(const asio::error_code &ec);
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
|
||||
std::thread server_thread {};
|
||||
std::unique_ptr<restbed::Service> service_;
|
||||
std::shared_ptr<DhtRunner> dht_;
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
Json::StreamWriterBuilder jsonBuilder_;
|
||||
|
||||
std::mutex schedulerLock_;
|
||||
std::condition_variable schedulerCv_;
|
||||
Scheduler scheduler_;
|
||||
std::thread schedulerThread_;
|
||||
std::unique_ptr<ThreadPool> threadPool_;
|
||||
std::thread httpServerThread_;
|
||||
std::unique_ptr<restinio::http_server_t<RestRouterTraits>> httpServer_;
|
||||
std::unique_ptr<http::Client> httpClient_;
|
||||
|
||||
Sp<Scheduler::Job> printStatsJob_;
|
||||
mutable std::mutex statsMutex_;
|
||||
mutable ServerStats stats_;
|
||||
mutable NodeInfo nodeInfo_ {};
|
||||
std::unique_ptr<asio::steady_timer> printStatsTimer_;
|
||||
|
||||
// Handle client quit for listen.
|
||||
// NOTE: can be simplified when we will supports restbed 5.0
|
||||
std::thread listenThread_;
|
||||
struct SessionToHashToken {
|
||||
std::shared_ptr<restbed::Session> session;
|
||||
InfoHash hash;
|
||||
std::future<size_t> token;
|
||||
// Thread-safe access to listeners map.
|
||||
std::shared_ptr<std::mutex> lockListener_;
|
||||
// Shared with connection listener.
|
||||
std::shared_ptr<std::map<restinio::connection_id_t,
|
||||
http::ListenerSession>> listeners_;
|
||||
// Connection Listener observing conn state changes.
|
||||
std::shared_ptr<http::ConnectionListener> connListener_;
|
||||
|
||||
struct PermanentPut {
|
||||
time_point expiration;
|
||||
std::string pushToken;
|
||||
std::string clientId;
|
||||
std::unique_ptr<asio::steady_timer> expireTimer;
|
||||
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
|
||||
};
|
||||
std::vector<SessionToHashToken> currentListeners_;
|
||||
std::mutex lockListener_;
|
||||
std::atomic_bool stopListeners {false};
|
||||
|
||||
struct PermanentPut;
|
||||
struct SearchPuts;
|
||||
struct SearchPuts {
|
||||
std::map<dht::Value::Id, PermanentPut> puts;
|
||||
};
|
||||
std::mutex lockSearchPuts_;
|
||||
std::map<InfoHash, SearchPuts> puts_;
|
||||
|
||||
mutable std::atomic<size_t> requestNum_ {0};
|
||||
@@ -304,11 +365,16 @@ private:
|
||||
|
||||
const std::string pushServer_;
|
||||
|
||||
mutable ServerStats stats_;
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
struct Listener;
|
||||
struct PushListener;
|
||||
struct Listener {
|
||||
std::string clientId;
|
||||
std::future<size_t> internalToken;
|
||||
std::unique_ptr<asio::steady_timer> expireTimer;
|
||||
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
|
||||
};
|
||||
struct PushListener {
|
||||
std::map<InfoHash, std::vector<Listener>> listeners;
|
||||
};
|
||||
std::mutex lockPushListeners_;
|
||||
std::map<std::string, PushListener> pushListeners_;
|
||||
proxy::ListenToken tokenPushNotif_ {0};
|
||||
|
||||
+43
-60
@@ -20,12 +20,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "def.h"
|
||||
#include "infohash.h"
|
||||
#include "value.h"
|
||||
#include "callbacks.h"
|
||||
#include "sockaddr.h"
|
||||
#include "log_enable.h"
|
||||
#include "def.h"
|
||||
#include "network_utils.h"
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@@ -52,15 +53,24 @@ struct SecureDhtConfig;
|
||||
class OPENDHT_PUBLIC DhtRunner {
|
||||
|
||||
public:
|
||||
typedef std::function<void(NodeStatus, NodeStatus)> StatusCallback;
|
||||
using StatusCallback = std::function<void(NodeStatus, NodeStatus)>;
|
||||
|
||||
struct Config {
|
||||
SecureDhtConfig dht_config;
|
||||
bool threaded;
|
||||
std::string proxy_server;
|
||||
std::string push_node_id;
|
||||
bool peer_discovery;
|
||||
bool peer_publish;
|
||||
SecureDhtConfig dht_config {};
|
||||
bool threaded {true};
|
||||
std::string proxy_server {};
|
||||
std::string push_node_id {};
|
||||
bool peer_discovery {false};
|
||||
bool peer_publish {false};
|
||||
};
|
||||
|
||||
struct Context {
|
||||
std::shared_ptr<Logger> logger {};
|
||||
std::unique_ptr<net::DatagramSocket> sock;
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery {};
|
||||
StatusCallback statusChangedCallback {};
|
||||
CertificateStoreQuery certificateStore {};
|
||||
Context() {}
|
||||
};
|
||||
|
||||
DhtRunner();
|
||||
@@ -296,9 +306,7 @@ public:
|
||||
* Returns the currently bound address.
|
||||
* @param f: address family of the bound address to retreive.
|
||||
*/
|
||||
const SockAddr& getBound(sa_family_t f = AF_INET) const {
|
||||
return (f == AF_INET) ? bound4 : bound6;
|
||||
}
|
||||
SockAddr getBound(sa_family_t f = AF_INET) const;
|
||||
|
||||
/**
|
||||
* Returns the currently bound port, in host byte order.
|
||||
@@ -316,7 +324,8 @@ public:
|
||||
|
||||
std::vector<ValuesExport> exportValues() const;
|
||||
|
||||
void setLoggers(LogMethod err = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG);
|
||||
void setLogger(const Logger& logger = {});
|
||||
void setLoggers(LogMethod err = {}, LogMethod warn = {}, LogMethod debug = {});
|
||||
|
||||
/**
|
||||
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
|
||||
@@ -356,26 +365,14 @@ public:
|
||||
* @param threaded: If false, ::loop() must be called periodically. Otherwise a thread is launched.
|
||||
* @param cb: Optional callback to receive general state information.
|
||||
*/
|
||||
void run(in_port_t port = 4222, const crypto::Identity identity = {}, bool threaded = false, NetId network = 0) {
|
||||
run(port, {
|
||||
/*.dht_config = */{
|
||||
/*.node_config = */{
|
||||
/*.node_id = */{},
|
||||
/*.network = */network,
|
||||
/*.is_bootstrap = */false,
|
||||
/*.maintain_storage = */false,
|
||||
/*.persist_path = */{}
|
||||
},
|
||||
/*.id = */identity
|
||||
},
|
||||
/*.threaded = */threaded,
|
||||
/*.proxy_server = */"",
|
||||
/*.push_node_id = */"",
|
||||
/*.peer_discovery = */true,
|
||||
/*.peer_publish = */true,
|
||||
});
|
||||
void run(in_port_t port = 4222, const crypto::Identity& identity = {}, bool threaded = true, NetId network = 0) {
|
||||
Config config;
|
||||
config.dht_config.node_config.network = network;
|
||||
config.dht_config.id = identity;
|
||||
config.threaded = threaded;
|
||||
run(port, config);
|
||||
}
|
||||
void run(in_port_t port, const Config& config);
|
||||
void run(in_port_t port, const Config& config, Context&& context = {});
|
||||
|
||||
/**
|
||||
* @param local4: Local IPv4 address and port to bind. Can be null.
|
||||
@@ -385,12 +382,14 @@ public:
|
||||
* @param threaded: If false, loop() must be called periodically. Otherwise a thread is launched.
|
||||
* @param cb: Optional callback to receive general state information.
|
||||
*/
|
||||
void run(const SockAddr& local4, const SockAddr& local6, const Config& config);
|
||||
void run(const SockAddr& local4, const SockAddr& local6, const 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);
|
||||
void run(const char* ip4, const char* ip6, const char* service, const Config& config, Context&& context = {});
|
||||
|
||||
void run(const Config& config, Context&& context);
|
||||
|
||||
void setOnStatusChanged(StatusCallback&& cb) {
|
||||
statusCb = std::move(cb);
|
||||
@@ -403,13 +402,7 @@ public:
|
||||
*/
|
||||
time_point loop() {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
time_point wakeup = time_point::min();
|
||||
try {
|
||||
wakeup = loop_();
|
||||
} catch (const dht::SocketException& e) {
|
||||
startNetwork(bound4, bound6);
|
||||
}
|
||||
return wakeup;
|
||||
return loop_();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -424,6 +417,8 @@ public:
|
||||
*/
|
||||
void join();
|
||||
|
||||
std::shared_ptr<PeerDiscovery> getPeerDiscovery() const { return peerDiscovery_; };
|
||||
|
||||
void setProxyServer(const std::string& proxy, const std::string& pushNodeId = "");
|
||||
|
||||
/**
|
||||
@@ -459,8 +454,6 @@ private:
|
||||
*/
|
||||
void tryBootstrapContinuously();
|
||||
|
||||
void stopNetwork();
|
||||
void startNetwork(const SockAddr sin4, const SockAddr sin6);
|
||||
time_point loop_();
|
||||
|
||||
NodeStatus getStatus() const {
|
||||
@@ -498,16 +491,8 @@ private:
|
||||
mutable std::mutex dht_mtx {};
|
||||
std::thread dht_thread {};
|
||||
std::condition_variable cv {};
|
||||
|
||||
std::thread rcv_thread {};
|
||||
std::mutex sock_mtx {};
|
||||
|
||||
struct ReceivedPacket {
|
||||
Blob data;
|
||||
SockAddr from;
|
||||
time_point received;
|
||||
};
|
||||
std::queue<ReceivedPacket> rcv {};
|
||||
std::queue<std::unique_ptr<net::ReceivedPacket>> rcv {};
|
||||
|
||||
/** true if currently actively boostraping */
|
||||
std::atomic_bool bootstraping {false};
|
||||
@@ -515,7 +500,6 @@ private:
|
||||
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 {};
|
||||
/** protects bootstrap_nodes, bootstrap_thread */
|
||||
std::mutex bootstrap_mtx {};
|
||||
std::condition_variable bootstrap_cv {};
|
||||
|
||||
@@ -524,23 +508,22 @@ private:
|
||||
std::mutex storage_mtx {};
|
||||
|
||||
std::atomic_bool running {false};
|
||||
std::atomic_bool running_network {false};
|
||||
|
||||
NodeStatus status4 {NodeStatus::Disconnected},
|
||||
status6 {NodeStatus::Disconnected};
|
||||
StatusCallback statusCb {nullptr};
|
||||
|
||||
int stop_writefd {-1};
|
||||
int s4 {-1}, s6 {-1};
|
||||
SockAddr bound4 {};
|
||||
SockAddr bound6 {};
|
||||
|
||||
/** Push notification token */
|
||||
std::string pushToken_;
|
||||
|
||||
/** PeerDiscovery Parameters */
|
||||
std::unique_ptr<PeerDiscovery> peerDiscovery4_;
|
||||
std::unique_ptr<PeerDiscovery> peerDiscovery6_;
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery_;
|
||||
|
||||
/**
|
||||
* The Logger instance is used in enableProxy and other methods that
|
||||
* would create instances of classes using a common logger.
|
||||
*/
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Author: 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
|
||||
* 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 <asio.hpp>
|
||||
#include <json/json.h>
|
||||
#include <http_parser.h>
|
||||
#include <restinio/all.hpp>
|
||||
#include <opendht.h>
|
||||
#include <opendht/def.h>
|
||||
#include <opendht/log.h>
|
||||
|
||||
namespace http {
|
||||
|
||||
class Connection;
|
||||
|
||||
// basic types
|
||||
using Id = unsigned int;
|
||||
|
||||
// asio handlers callbacks
|
||||
using HandlerCb = std::function<void(const asio::error_code& ec)>;
|
||||
using ConnectionCb = std::function<void(const asio::error_code& ec, std::shared_ptr<Connection>)>;
|
||||
|
||||
class OPENDHT_PUBLIC Connection
|
||||
{
|
||||
public:
|
||||
Connection(asio::ip::tcp::socket socket, std::shared_ptr<dht::Logger> logger = {});
|
||||
~Connection();
|
||||
|
||||
Id id();
|
||||
bool is_open();
|
||||
bool is_v6();
|
||||
void timeout(const std::chrono::seconds timeout, HandlerCb cb = {});
|
||||
// TODO abort to silence error in request?
|
||||
void close();
|
||||
|
||||
private:
|
||||
friend class Client;
|
||||
|
||||
Id id_;
|
||||
static Id ids_;
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
|
||||
asio::ip::tcp::socket socket_;
|
||||
asio::ip::tcp::endpoint endpoint_;
|
||||
|
||||
asio::streambuf request_;
|
||||
std::string response_body_;
|
||||
asio::streambuf response_chunk_;
|
||||
|
||||
std::unique_ptr<asio::steady_timer> timeout_timer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Session value associated with a connection_id_t key.
|
||||
*/
|
||||
struct ListenerSession
|
||||
{
|
||||
ListenerSession() = default;
|
||||
dht::InfoHash hash;
|
||||
std::future<size_t> token;
|
||||
std::shared_ptr<restinio::response_builder_t<restinio::chunked_output_t>> response;
|
||||
};
|
||||
|
||||
class ConnectionListener
|
||||
{
|
||||
public:
|
||||
ConnectionListener();
|
||||
ConnectionListener(std::shared_ptr<dht::DhtRunner> dht,
|
||||
std::shared_ptr<std::map<restinio::connection_id_t, http::ListenerSession>> listeners,
|
||||
std::shared_ptr<std::mutex> lock, std::shared_ptr<dht::Logger> logger);
|
||||
~ConnectionListener();
|
||||
|
||||
/**
|
||||
* Connection state change used to handle Listeners disconnects.
|
||||
* RESTinio >= 0.5.1 https://github.com/Stiffstream/restinio/issues/28
|
||||
*/
|
||||
void state_changed(const restinio::connection_state::notice_t& notice) noexcept;
|
||||
|
||||
private:
|
||||
std::string to_str( restinio::connection_state::cause_t cause ) noexcept;
|
||||
|
||||
std::shared_ptr<dht::DhtRunner> dht_;
|
||||
std::shared_ptr<std::mutex> lock_;
|
||||
std::shared_ptr<std::map<restinio::connection_id_t,
|
||||
http::ListenerSession>> listeners_;
|
||||
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
};
|
||||
|
||||
|
||||
class Resolver {
|
||||
Resolver(asio::io_context& ctx, const std::string& host, const std::string& service = "80");
|
||||
|
||||
using ResolvedCb = std::function<void(const asio::error_code&, const asio::ip::basic_resolver_results<asio::ip::tcp>&)>;
|
||||
void addOnResolved(ResolvedCb cb);
|
||||
|
||||
private:
|
||||
std::mutex cbsMutex_;
|
||||
asio::ip::tcp::resolver resolver_;
|
||||
asio::error_code error_;
|
||||
asio::ip::basic_resolver_results<asio::ip::tcp> endpoints_;
|
||||
std::queue<ResolvedCb> cbs_;
|
||||
bool completed_ {false};
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC Request
|
||||
{
|
||||
public:
|
||||
Request(asio::io_context& ctx, const std::string host, const std::string service = "80",
|
||||
const bool resolve = true, std::shared_ptr<dht::Logger> logger = {});
|
||||
~Request();
|
||||
|
||||
void set_logger(std::shared_ptr<dht::Logger> logger);
|
||||
|
||||
void terminate();
|
||||
|
||||
void resolve(const std::string host, const std::string service, HandlerCb cb = {});
|
||||
bool resolved();
|
||||
|
||||
void connect(ConnectionCb cb = {});
|
||||
|
||||
std::string build(const restinio::http_request_header_t header,
|
||||
const restinio::http_header_fields_t header_fields,
|
||||
const restinio::http_connection_header_t connection, const std::string body);
|
||||
|
||||
void send(std::string request, std::unique_ptr<http_parser> parser,
|
||||
std::unique_ptr<http_parser_settings> parser_s, HandlerCb cb = {});
|
||||
|
||||
private:
|
||||
void handle_request(const asio::error_code& ec, HandlerCb cb = {});
|
||||
|
||||
void handle_response_header(const asio::error_code& ec, const size_t bytes, HandlerCb cb = {});
|
||||
|
||||
void handle_response_body(const asio::error_code& ec, const size_t bytes, HandlerCb cb = {});
|
||||
|
||||
void parse_request(const std::string request);
|
||||
|
||||
size_t get_content_length(const std::string str);
|
||||
|
||||
Resolver resolver_;
|
||||
/* std::string service_;
|
||||
std::string host_;
|
||||
|
||||
asio::ip::tcp::resolver resolver_;
|
||||
asio::ip::basic_resolver_results<asio::ip::tcp> endpoints_;
|
||||
*/
|
||||
Id id_;
|
||||
static Id ids_;
|
||||
std::shared_ptr<Connection> conn_;
|
||||
|
||||
std::string request_;
|
||||
std::unique_ptr<http_parser> parser_;
|
||||
std::unique_ptr<http_parser_settings> parser_s_;
|
||||
|
||||
std::shared_ptr<dht::Logger> logger_;
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
namespace restinio
|
||||
{
|
||||
|
||||
class opendht_logger_t
|
||||
{
|
||||
public:
|
||||
opendht_logger_t(std::shared_ptr<dht::Logger> logger = {}){
|
||||
if (logger)
|
||||
m_logger = logger;
|
||||
}
|
||||
|
||||
template <typename Builder>
|
||||
void trace(Builder && msg_builder){
|
||||
if (m_logger)
|
||||
m_logger->d("[proxy:server] %s", msg_builder().c_str());
|
||||
}
|
||||
|
||||
template <typename Builder>
|
||||
void info(Builder && msg_builder){
|
||||
if (m_logger)
|
||||
m_logger->d("[proxy:server] %s", msg_builder().c_str());
|
||||
}
|
||||
|
||||
template <typename Builder>
|
||||
void warn(Builder && msg_builder){
|
||||
if (m_logger)
|
||||
m_logger->w("[proxy:server] %s", msg_builder().c_str());
|
||||
}
|
||||
|
||||
template <typename Builder>
|
||||
void error(Builder && msg_builder){
|
||||
if (m_logger)
|
||||
m_logger->e("[proxy:server] %s", msg_builder().c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<dht::Logger> m_logger;
|
||||
};
|
||||
|
||||
/* 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"};
|
||||
|
||||
struct custom_http_methods_t
|
||||
{
|
||||
static constexpr restinio::http_method_id_t from_nodejs(int m) noexcept {
|
||||
if(m == method_listen.raw_id())
|
||||
return method_listen;
|
||||
else if(m == method_stats.raw_id())
|
||||
return method_stats;
|
||||
else if(m == method_sign.raw_id())
|
||||
return method_sign;
|
||||
else if(m == method_encrypt.raw_id())
|
||||
return method_encrypt;
|
||||
else
|
||||
return restinio::default_http_methods_t::from_nodejs(m);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace restinio
|
||||
@@ -66,6 +66,15 @@ constexpr const Color::Modifier yellow(Color::FG_YELLOW);
|
||||
OPENDHT_PUBLIC void
|
||||
printLog(std::ostream &s, char const *m, va_list args);
|
||||
|
||||
OPENDHT_PUBLIC
|
||||
std::unique_ptr<Logger> getStdLogger();
|
||||
|
||||
OPENDHT_PUBLIC
|
||||
std::unique_ptr<Logger> getFileLogger(const std::string &path);
|
||||
|
||||
OPENDHT_PUBLIC
|
||||
std::unique_ptr<Logger> getSyslogLogger(const char* name);
|
||||
|
||||
OPENDHT_PUBLIC void
|
||||
enableLogging(dht::DhtRunner &dht);
|
||||
|
||||
|
||||
@@ -32,11 +32,6 @@ namespace dht {
|
||||
|
||||
// Logging related utility functions
|
||||
|
||||
/**
|
||||
* Dummy function used to disable logging
|
||||
*/
|
||||
inline void NOLOG(char const*, va_list) {}
|
||||
|
||||
/**
|
||||
* Wrapper for logging methods
|
||||
*/
|
||||
@@ -85,9 +80,13 @@ private:
|
||||
};
|
||||
|
||||
struct Logger {
|
||||
LogMethod DBG = NOLOG;
|
||||
LogMethod WARN = NOLOG;
|
||||
LogMethod ERR = NOLOG;
|
||||
LogMethod DBG = {};
|
||||
LogMethod WARN = {};
|
||||
LogMethod ERR = {};
|
||||
|
||||
Logger() = default;
|
||||
Logger(LogMethod&& err, LogMethod&& warn, LogMethod&& dbg)
|
||||
: DBG(std::move(dbg)), WARN(std::move(warn)), ERR(std::move(err)) {}
|
||||
void setFilter(const InfoHash& f) {
|
||||
filter_ = f;
|
||||
filterEnable_ = static_cast<bool>(filter_);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "rng.h"
|
||||
#include "rate_limiter.h"
|
||||
#include "log_enable.h"
|
||||
#include "network_utils.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -205,8 +206,8 @@ public:
|
||||
using RequestCb = std::function<void(const Request&, RequestAnswer&&)>;
|
||||
using RequestExpiredCb = std::function<void(const Request&, bool)>;
|
||||
|
||||
NetworkEngine(Logger& log, Scheduler& scheduler, const int& s = -1, const int& s6 = -1);
|
||||
NetworkEngine(InfoHash& myid, NetId net, const int& s, const int& s6, Logger& log, Scheduler& scheduler,
|
||||
NetworkEngine(Logger& log, Scheduler& scheduler, std::unique_ptr<DatagramSocket>&& sock);
|
||||
NetworkEngine(InfoHash& myid, NetId net, std::unique_ptr<DatagramSocket>&& sock, Logger& log, Scheduler& scheduler,
|
||||
decltype(NetworkEngine::onError)&& onError,
|
||||
decltype(NetworkEngine::onNewNode)&& onNewNode,
|
||||
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
|
||||
@@ -217,7 +218,9 @@ public:
|
||||
decltype(NetworkEngine::onAnnounce)&& onAnnounce,
|
||||
decltype(NetworkEngine::onRefresh)&& onRefresh);
|
||||
|
||||
virtual ~NetworkEngine();
|
||||
~NetworkEngine();
|
||||
|
||||
net::DatagramSocket* getSocket() const { return dht_socket.get(); };
|
||||
|
||||
void clear();
|
||||
|
||||
@@ -242,7 +245,7 @@ public:
|
||||
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values);
|
||||
|
||||
bool isRunning(sa_family_t af) const;
|
||||
inline want_t want () const { return dht_socket >= 0 && dht_socket6 >= 0 ? (WANT4 | WANT6) : -1; }
|
||||
inline want_t want () const { return dht_socket->hasIPv4() and dht_socket->hasIPv6() ? (WANT4 | WANT6) : -1; }
|
||||
|
||||
void connectivityChanged(sa_family_t);
|
||||
|
||||
@@ -394,7 +397,7 @@ public:
|
||||
* @param fromlen The length of the corresponding sockaddr structure.
|
||||
* @param now The time to adjust the clock in the network engine.
|
||||
*/
|
||||
void processMessage(const uint8_t *buf, size_t buflen, const SockAddr& addr);
|
||||
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);
|
||||
@@ -469,7 +472,7 @@ private:
|
||||
|
||||
|
||||
// basic wrapper for socket sendto function
|
||||
int send(const char *buf, size_t len, int flags, const SockAddr& addr);
|
||||
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);
|
||||
std::vector<Blob> packValueHeader(msgpack::sbuffer&, const std::vector<Sp<Value>>&);
|
||||
@@ -511,8 +514,7 @@ private:
|
||||
/* DHT info */
|
||||
const InfoHash& myid;
|
||||
const NetId network {0};
|
||||
const int& dht_socket;
|
||||
const int& dht_socket6;
|
||||
const std::unique_ptr<DatagramSocket> dht_socket;
|
||||
const Logger& DHT_LOG;
|
||||
|
||||
NodeCache cache {};
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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
|
||||
* 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 "def.h"
|
||||
|
||||
#include "sockaddr.h"
|
||||
#include "utils.h"
|
||||
#include "log_enable.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
|
||||
namespace dht {
|
||||
namespace net {
|
||||
|
||||
int bindSocket(const SockAddr& addr, SockAddr& bound);
|
||||
|
||||
bool setNonblocking(int fd, bool nonblocking = true);
|
||||
|
||||
#ifdef _WIN32
|
||||
void udpPipe(int fds[2]);
|
||||
#endif
|
||||
struct ReceivedPacket {
|
||||
Blob data;
|
||||
SockAddr from;
|
||||
time_point received;
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC DatagramSocket {
|
||||
public:
|
||||
using OnReceive = std::function<void(std::unique_ptr<ReceivedPacket>&& packet)>;
|
||||
virtual ~DatagramSocket() {};
|
||||
|
||||
virtual int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) = 0;
|
||||
|
||||
inline void setOnReceive(OnReceive&& cb) {
|
||||
rx_callback = std::move(cb);
|
||||
}
|
||||
|
||||
virtual const SockAddr& getBound(sa_family_t family = AF_UNSPEC) const = 0;
|
||||
virtual bool hasIPv4() const = 0;
|
||||
virtual bool hasIPv6() const = 0;
|
||||
|
||||
in_port_t getPort(sa_family_t family = AF_UNSPEC) const {
|
||||
return getBound(family).getPort();
|
||||
}
|
||||
|
||||
virtual void stop() = 0;
|
||||
protected:
|
||||
|
||||
inline void onReceived(std::unique_ptr<ReceivedPacket>&& packet) {
|
||||
if (rx_callback)
|
||||
rx_callback(std::move(packet));
|
||||
}
|
||||
private:
|
||||
OnReceive rx_callback;
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) override;
|
||||
|
||||
const SockAddr& getBound(sa_family_t family = AF_UNSPEC) const override {
|
||||
return (family == AF_INET6) ? bound6 : bound4;
|
||||
}
|
||||
|
||||
bool hasIPv4() const override { return s4 != -1; }
|
||||
bool hasIPv6() const override { return s6 != -1; }
|
||||
|
||||
void stop() override;
|
||||
private:
|
||||
Logger logger;
|
||||
int s4 {-1};
|
||||
int s6 {-1};
|
||||
int stopfd {-1};
|
||||
SockAddr bound4, bound6;
|
||||
std::thread rcv_thread {};
|
||||
std::atomic_bool running {false};
|
||||
|
||||
void openSockets(const SockAddr& bind4, const SockAddr& bind6);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,27 +31,53 @@ namespace dht {
|
||||
class OPENDHT_PUBLIC PeerDiscovery
|
||||
{
|
||||
public:
|
||||
static constexpr in_port_t DEFAULT_PORT = 8888;
|
||||
using ServiceDiscoveredCallback = std::function<void(msgpack::object&&, SockAddr&&)>;
|
||||
|
||||
using PeerDiscoveredCallback = std::function<void(const InfoHash&, const SockAddr&)>;
|
||||
|
||||
PeerDiscovery(sa_family_t domain, in_port_t port);
|
||||
PeerDiscovery(in_port_t port = DEFAULT_PORT);
|
||||
~PeerDiscovery();
|
||||
|
||||
/**
|
||||
* startDiscovery - Keep Listening data from the sender until node is joinned or stop is called
|
||||
*/
|
||||
void startDiscovery(PeerDiscoveredCallback callback);
|
||||
void startDiscovery(const std::string &type, ServiceDiscoveredCallback callback);
|
||||
|
||||
template<typename T>
|
||||
void startDiscovery(const std::string &type, std::function<void(T&&, SockAddr&&)> cb) {
|
||||
startDiscovery(type, [cb](msgpack::object&& ob, SockAddr&& addr) {
|
||||
cb(ob.as<T>(), std::move(addr));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* startPublish - Keeping sending data until node is joinned or stop is called
|
||||
* startPublish - Keeping sending data until node is joinned or stop is called - msgpack
|
||||
*/
|
||||
void startPublish(const dht::InfoHash &nodeId, in_port_t port_to_send);
|
||||
void startPublish(const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
void startPublish(sa_family_t domain, const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
|
||||
template<typename T>
|
||||
void startPublish(const std::string &type, const T& object) {
|
||||
msgpack::sbuffer buf;
|
||||
msgpack::pack(buf, object);
|
||||
startPublish(type, buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread Stopper
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Remove possible callBack to discovery
|
||||
*/
|
||||
bool stopDiscovery(const std::string &type);
|
||||
|
||||
/**
|
||||
* Remove different serivce message to send
|
||||
*/
|
||||
bool stopPublish(const std::string &type);
|
||||
bool stopPublish(sa_family_t domain, const std::string &type);
|
||||
|
||||
/**
|
||||
* Configure the sockopt to be able to listen multicast group
|
||||
*/
|
||||
@@ -60,62 +86,12 @@ public:
|
||||
/**
|
||||
* Join the threads
|
||||
*/
|
||||
void join() {
|
||||
if(running_listen.joinable()) running_listen.join();
|
||||
if(running_send.joinable()) running_send.join();
|
||||
}
|
||||
void join();
|
||||
|
||||
private:
|
||||
std::mutex mtx_;
|
||||
std::condition_variable cv_;
|
||||
bool running_ {true};
|
||||
sa_family_t domain_ {AF_UNSPEC};
|
||||
int port_;
|
||||
int sockfd_ {-1};
|
||||
int stop_writefd_ {-1};
|
||||
|
||||
SockAddr sockAddrSend_;
|
||||
std::array<uint8_t,dht::InfoHash::size() + sizeof(in_port_t)> data_send_;
|
||||
|
||||
//Thread export to be joined
|
||||
std::thread running_listen;
|
||||
std::thread running_send;
|
||||
dht::InfoHash nodeId_;
|
||||
|
||||
/**
|
||||
* Multicast Socket Initialization, accept IPV4, IPV6
|
||||
*/
|
||||
static int initialize_socket(sa_family_t domain);
|
||||
|
||||
/**
|
||||
* Send messages
|
||||
*/
|
||||
void sendTo(uint8_t *buf,size_t buf_size);
|
||||
|
||||
/**
|
||||
* Receive messages
|
||||
*/
|
||||
SockAddr recvFrom(uint8_t *buf, size_t &buf_size);
|
||||
|
||||
/**
|
||||
* Send thread loop
|
||||
*/
|
||||
void sender_thread();
|
||||
|
||||
/**
|
||||
* Listener thread loop
|
||||
*/
|
||||
void listener_thread(PeerDiscoveredCallback callback);
|
||||
|
||||
/**
|
||||
* Listener Parameters Setup
|
||||
*/
|
||||
void listener_setup();
|
||||
|
||||
/**
|
||||
* Sender Parameters Setup
|
||||
*/
|
||||
void sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send);
|
||||
class DomainPeerDiscovery;
|
||||
std::unique_ptr<DomainPeerDiscovery> peerDiscovery4_;
|
||||
std::unique_ptr<DomainPeerDiscovery> peerDiscovery6_;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -195,8 +195,8 @@ 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, const SockAddr& sa) override {
|
||||
return dht_->periodic(buf, buflen, sa);
|
||||
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, const sockaddr* from, socklen_t fromlen) override {
|
||||
return dht_->periodic(buf, buflen, from, fromlen);
|
||||
@@ -207,6 +207,9 @@ public:
|
||||
NodeStatus getStatus() const override {
|
||||
return dht_->getStatus();
|
||||
}
|
||||
net::DatagramSocket* getSocket() const override {
|
||||
return dht_->getSocket();
|
||||
};
|
||||
bool isRunning(sa_family_t af = 0) const override {
|
||||
return dht_->isRunning(af);
|
||||
}
|
||||
@@ -311,10 +314,9 @@ public:
|
||||
dht_->pushNotificationReceived(notification);
|
||||
}
|
||||
|
||||
void setLoggers(LogMethod error = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG) override
|
||||
{
|
||||
DhtInterface::setLoggers(error, warn, debug);
|
||||
dht_->setLoggers(error, warn, debug);
|
||||
void setLogger(const Logger& logger) override {
|
||||
DhtInterface::setLogger(logger);
|
||||
dht_->setLogger(logger);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
SockAddr(const SockAddr& o) {
|
||||
set(o.get(), o.getLength());
|
||||
}
|
||||
SockAddr(SockAddr&& o) noexcept : len(o.len), addr(std::move(o.addr)) {
|
||||
SockAddr(SockAddr&& o) noexcept : addr(std::move(o.addr)), len(o.len) {
|
||||
o.len = 0;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
/**
|
||||
* Returns the address family or AF_UNSPEC if the address is not set.
|
||||
*/
|
||||
sa_family_t getFamily() const { return len > sizeof(sa_family_t) ? addr->sa_family : AF_UNSPEC; }
|
||||
sa_family_t getFamily() const { return len ? addr->sa_family : AF_UNSPEC; }
|
||||
|
||||
/**
|
||||
* Resize the managed structure to the appropriate size (if needed),
|
||||
@@ -248,7 +248,8 @@ public:
|
||||
bool isUnspecified() const;
|
||||
|
||||
bool isMappedIPv4() const;
|
||||
SockAddr getMappedIPv4() const;
|
||||
SockAddr getMappedIPv4();
|
||||
SockAddr getMappedIPv6();
|
||||
|
||||
/**
|
||||
* A comparator to classify IP addresses, only considering the
|
||||
@@ -279,9 +280,9 @@ public:
|
||||
}
|
||||
};
|
||||
private:
|
||||
socklen_t len {0};
|
||||
struct free_delete { void operator()(void* p) { ::free(p); } };
|
||||
std::unique_ptr<sockaddr, free_delete> addr {};
|
||||
socklen_t len {0};
|
||||
|
||||
void set(const sockaddr* sa, socklen_t length) {
|
||||
if (len != length) {
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "def.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
@@ -27,7 +29,7 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
class ThreadPool {
|
||||
class OPENDHT_PUBLIC ThreadPool {
|
||||
public:
|
||||
static ThreadPool& computation();
|
||||
static ThreadPool& io();
|
||||
@@ -47,8 +49,8 @@ public:
|
||||
return ret->get_future();
|
||||
}
|
||||
template<class T>
|
||||
std::shared_ptr<std::future<T>> getShared(std::function<T()>&& cb) {
|
||||
return std::make_shared<std::future<T>>(get(std::move(cb)));
|
||||
std::shared_future<T> getShared(std::function<T()>&& cb) {
|
||||
return get(std::move(cb));
|
||||
}
|
||||
|
||||
void stop();
|
||||
@@ -66,4 +68,23 @@ private:
|
||||
bool running_ {true};
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC Executor : public std::enable_shared_from_this<Executor> {
|
||||
public:
|
||||
Executor(ThreadPool& pool, unsigned maxConcurrent = 1)
|
||||
: threadPool_(pool), maxConcurrent_(maxConcurrent)
|
||||
{}
|
||||
|
||||
void run(std::function<void()>&& task);
|
||||
|
||||
private:
|
||||
std::reference_wrapper<ThreadPool> threadPool_;
|
||||
const unsigned maxConcurrent_ {1};
|
||||
std::mutex lock_ {};
|
||||
unsigned current_ {0};
|
||||
std::queue<std::function<void()>> tasks_ {};
|
||||
|
||||
void run_(std::function<void()>&& task);
|
||||
void schedule();
|
||||
};
|
||||
|
||||
}
|
||||
@@ -92,6 +92,18 @@ print_dt(DT d) {
|
||||
return std::chrono::duration_cast<std::chrono::duration<double>>(d).count();
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
static std::string
|
||||
print_duration(DT 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::seconds(1)) {
|
||||
return std::to_string(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
|
||||
} else {
|
||||
return std::to_string(print_dt(d)) + " s";
|
||||
}
|
||||
}
|
||||
|
||||
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>;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# distutils: language = c++
|
||||
# distutils: extra_compile_args = -std=c++11
|
||||
# distutils: extra_compile_args = -std=c++14
|
||||
# distutils: include_dirs = ../../include
|
||||
# distutils: library_dirs = ../../src
|
||||
# distutils: libraries = opendht gnutls
|
||||
|
||||
+2
-2
@@ -50,8 +50,8 @@ setup(name="opendht",
|
||||
["@CURRENT_SOURCE_DIR@/opendht.pyx"],
|
||||
include_dirs = ['@PROJECT_SOURCE_DIR@/include'],
|
||||
language="c++",
|
||||
extra_compile_args=["-std=c++11"],
|
||||
extra_link_args=["-std=c++11"],
|
||||
extra_compile_args=["-std=c++14"],
|
||||
extra_link_args=["-std=c++14"],
|
||||
libraries=["opendht"],
|
||||
library_dirs = ['@CURRENT_BINARY_DIR@', '@PROJECT_BINARY_DIR@']
|
||||
))
|
||||
|
||||
+6
-4
@@ -28,8 +28,8 @@ libopendht_la_SOURCES = \
|
||||
default_types.cpp \
|
||||
log.cpp \
|
||||
peer_discovery.cpp \
|
||||
network_utils.h \
|
||||
network_utils.cpp
|
||||
network_utils.cpp \
|
||||
thread_pool.cpp
|
||||
|
||||
if WIN32
|
||||
libopendht_la_SOURCES += rng.cpp
|
||||
@@ -57,10 +57,12 @@ nobase_include_HEADERS = \
|
||||
../include/opendht/log.h \
|
||||
../include/opendht/log_enable.h \
|
||||
../include/opendht/peer_discovery.h \
|
||||
../include/opendht/rng.h
|
||||
../include/opendht/network_utils.h \
|
||||
../include/opendht/rng.h \
|
||||
../include/opendht/thread_pool.h
|
||||
|
||||
if ENABLE_PROXY_SERVER
|
||||
libopendht_la_SOURCES += dht_proxy_server.cpp thread_pool.h thread_pool.cpp
|
||||
libopendht_la_SOURCES += dht_proxy_server.cpp
|
||||
nobase_include_HEADERS += ../include/opendht/dht_proxy_server.h
|
||||
endif
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ extern "C" {
|
||||
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
@@ -1043,6 +1044,21 @@ generateEcIdentity(const std::string& name, const Identity& ca) {
|
||||
return generateEcIdentity(name, ca, !ca.first || !ca.second);
|
||||
}
|
||||
|
||||
void
|
||||
saveIdentity(const Identity& id, const std::string& path, const std::string& privkey_password)
|
||||
{
|
||||
{
|
||||
auto ca_key_data = id.first->serialize(privkey_password);
|
||||
std::ofstream key_file(path + ".pem");
|
||||
key_file.write((char*)ca_key_data.data(), ca_key_data.size());
|
||||
}
|
||||
{
|
||||
auto ca_key_data = id.second->getPacked();
|
||||
std::ofstream crt_file(path + ".crt");
|
||||
crt_file.write((char*)ca_key_data.data(), ca_key_data.size());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setValidityPeriod(gnutls_x509_crt_t cert, int64_t validity)
|
||||
{
|
||||
|
||||
+14
-15
@@ -1689,11 +1689,11 @@ Dht::~Dht()
|
||||
s.second->clear();
|
||||
}
|
||||
|
||||
Dht::Dht() : store(), network_engine(DHT_LOG, scheduler) {}
|
||||
Dht::Dht() : store(), network_engine(DHT_LOG, scheduler, {}) {}
|
||||
|
||||
Dht::Dht(const int& s, const int& s6, const Config& config)
|
||||
: myid(config.node_id ? config.node_id : InfoHash::getRandom()), store(), store_quota(),
|
||||
network_engine(myid, config.network, s, s6, DHT_LOG, scheduler,
|
||||
Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Logger& l)
|
||||
: DhtInterface(l), myid(config.node_id ? config.node_id : InfoHash::getRandom()), store(), store_quota(),
|
||||
network_engine(myid, config.network, std::move(sock), DHT_LOG, scheduler,
|
||||
std::bind(&Dht::onError, this, _1, _2),
|
||||
std::bind(&Dht::onNewNode, this, _1, _2),
|
||||
std::bind(&Dht::onReportedAddr, this, _1, _2),
|
||||
@@ -1708,13 +1708,14 @@ Dht::Dht(const int& s, const int& s6, const Config& config)
|
||||
maintain_storage(config.maintain_storage)
|
||||
{
|
||||
scheduler.syncTime();
|
||||
if (s < 0 && s6 < 0)
|
||||
return;
|
||||
if (s >= 0) {
|
||||
auto s = network_engine.getSocket();
|
||||
if (not s or (not s->hasIPv4() and not s->hasIPv6()))
|
||||
throw DhtException("Opened socket required");
|
||||
if (s->hasIPv4()) {
|
||||
buckets4 = {Bucket {AF_INET}};
|
||||
buckets4.is_client = config.is_bootstrap;
|
||||
}
|
||||
if (s6 >= 0) {
|
||||
if (s->hasIPv6()) {
|
||||
buckets6 = {Bucket {AF_INET6}};
|
||||
buckets6.is_client = config.is_bootstrap;
|
||||
}
|
||||
@@ -1722,9 +1723,7 @@ Dht::Dht(const int& s, const int& s6, const Config& config)
|
||||
search_id = std::uniform_int_distribution<decltype(search_id)>{}(rd);
|
||||
|
||||
uniform_duration_distribution<> time_dis {std::chrono::seconds(3), std::chrono::seconds(5)};
|
||||
auto confirm_nodes_time = scheduler.time() + time_dis(rd);
|
||||
DHT_LOG.d(myid, "Scheduling %s", myid.toString().c_str());
|
||||
nextNodesConfirmation = scheduler.add(confirm_nodes_time, std::bind(&Dht::confirmNodes, this));
|
||||
nextNodesConfirmation = scheduler.add(scheduler.time() + time_dis(rd), std::bind(&Dht::confirmNodes, this));
|
||||
|
||||
// Fill old secret
|
||||
{
|
||||
@@ -1735,7 +1734,7 @@ Dht::Dht(const int& s, const int& s6, const Config& config)
|
||||
|
||||
expire();
|
||||
|
||||
DHT_LOG.d("DHT initialised with node ID %s", myid.toString().c_str());
|
||||
DHT_LOG.d("DHT node initialised with ID %s", myid.toString().c_str());
|
||||
|
||||
if (not persistPath.empty())
|
||||
loadState(persistPath);
|
||||
@@ -1902,14 +1901,14 @@ Dht::maintainStorage(decltype(store)::value_type& storage, bool force, const Don
|
||||
}
|
||||
|
||||
time_point
|
||||
Dht::periodic(const uint8_t *buf, size_t buflen, const SockAddr& from)
|
||||
Dht::periodic(const uint8_t *buf, size_t buflen, SockAddr from)
|
||||
{
|
||||
scheduler.syncTime();
|
||||
if (buflen) {
|
||||
try {
|
||||
network_engine.processMessage(buf, buflen, from);
|
||||
network_engine.processMessage(buf, buflen, std::move(from));
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.e("Can't process message from %s: %s", from.toString().c_str(), e.what());
|
||||
DHT_LOG.e("Can't process message: %s", e.what());
|
||||
}
|
||||
}
|
||||
return scheduler.run();
|
||||
|
||||
+875
-586
File diff suppressed because it is too large.
Load diff
+861
-699
File diff suppressed because it is too large.
Load diff
+151
-216
@@ -37,7 +37,8 @@ namespace dht {
|
||||
|
||||
constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD;
|
||||
static constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 16;
|
||||
static constexpr in_port_t PEER_DISCOVERY_PORT = 8888;
|
||||
static constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(500);
|
||||
static const std::string PEER_DISCOVERY_DHT_SERVICE = "dht";
|
||||
|
||||
struct DhtRunner::Listener {
|
||||
size_t tokenClassicDht {0};
|
||||
@@ -48,6 +49,13 @@ struct DhtRunner::Listener {
|
||||
Where w;
|
||||
};
|
||||
|
||||
struct NodeInsertionPack {
|
||||
dht::InfoHash nodeId;
|
||||
in_port_t port;
|
||||
dht::NetId net;
|
||||
MSGPACK_DEFINE(nodeId, port, net)
|
||||
};
|
||||
|
||||
DhtRunner::DhtRunner() : dht_()
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
, dht_via_proxy_()
|
||||
@@ -69,7 +77,7 @@ DhtRunner::~DhtRunner()
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(in_port_t port, const DhtRunner::Config& config)
|
||||
DhtRunner::run(in_port_t port, const Config& config, Context&& context)
|
||||
{
|
||||
SockAddr sin4;
|
||||
sin4.setFamily(AF_INET);
|
||||
@@ -77,45 +85,76 @@ DhtRunner::run(in_port_t port, const DhtRunner::Config& config)
|
||||
SockAddr sin6;
|
||||
sin6.setFamily(AF_INET6);
|
||||
sin6.setPort(port);
|
||||
run(sin4, sin6, config);
|
||||
run(sin4, sin6, config, std::move(context));
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(const char* ip4, const char* ip6, const char* service, const DhtRunner::Config& config)
|
||||
DhtRunner::run(const char* ip4, const char* ip6, const char* service, const 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);
|
||||
res6.empty() ? SockAddr() : res6.front(), config, std::move(context));
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const DhtRunner::Config& config)
|
||||
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const Config& config, Context&& context)
|
||||
{
|
||||
if (not running) {
|
||||
if (not context.sock)
|
||||
context.sock.reset(new net::UdpSocket(local4, local6, context.logger ? *context.logger : Logger{}));
|
||||
run(config, std::move(context));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::run(const Config& config, Context&& context)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (running)
|
||||
return;
|
||||
startNetwork(local4, local6);
|
||||
|
||||
auto dht = std::unique_ptr<DhtInterface>(new Dht(s4, s6, SecureDht::getConfig(config.dht_config)));
|
||||
if (context.logger)
|
||||
logger_ = context.logger;
|
||||
|
||||
context.sock->setOnReceive([&] (std::unique_ptr<net::ReceivedPacket>&& pkt) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
if (rcv.size() >= RX_QUEUE_MAX_SIZE) {
|
||||
std::cerr << "Dropping packet: queue is full!" << std::endl;
|
||||
rcv.pop();
|
||||
}
|
||||
rcv.emplace(std::move(pkt));
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
auto dht = std::unique_ptr<DhtInterface>(new Dht(std::move(context.sock), SecureDht::getConfig(config.dht_config)));
|
||||
dht_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht), config.dht_config));
|
||||
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
config_ = config;
|
||||
#endif
|
||||
enableProxy(not config.proxy_server.empty());
|
||||
if (context.logger and dht_via_proxy_) {
|
||||
dht_via_proxy_->setLogger(*context.logger);
|
||||
}
|
||||
if (context.statusChangedCallback) {
|
||||
statusCb = std::move(context.statusChangedCallback);
|
||||
}
|
||||
if (context.certificateStore) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
}
|
||||
|
||||
running = true;
|
||||
if (not config.threaded)
|
||||
return;
|
||||
dht_thread = std::thread([this, local4, local6]() {
|
||||
dht_thread = std::thread([this]() {
|
||||
while (running) {
|
||||
std::unique_lock<std::mutex> lk(dht_mtx);
|
||||
time_point wakeup;
|
||||
try {
|
||||
wakeup = loop_();
|
||||
} catch (const dht::SocketException& e) {
|
||||
startNetwork(local4, local6);
|
||||
}
|
||||
time_point wakeup = loop_();
|
||||
|
||||
auto hasJobToDo = [this]() {
|
||||
if (not running)
|
||||
@@ -143,44 +182,55 @@ DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const DhtRunner::
|
||||
});
|
||||
|
||||
if (config.peer_discovery or config.peer_publish) {
|
||||
try {
|
||||
peerDiscovery4_.reset(new PeerDiscovery(AF_INET, PEER_DISCOVERY_PORT));
|
||||
} catch(const std::exception& e){
|
||||
std::cerr << "Can't start peer discovery (IPv4): " << e.what() << std::endl;
|
||||
}
|
||||
try {
|
||||
peerDiscovery6_.reset(new PeerDiscovery(AF_INET6, PEER_DISCOVERY_PORT));
|
||||
} catch(const std::exception& e) {
|
||||
std::cerr << "Can't start peer discovery (IPv6): " << e.what() << std::endl;
|
||||
}
|
||||
peerDiscovery_ = context.peerDiscovery ?
|
||||
std::move(context.peerDiscovery) :
|
||||
std::make_shared<PeerDiscovery>();
|
||||
}
|
||||
if (config.peer_discovery) {
|
||||
using sig = void (DhtRunner::*)(const InfoHash&, const SockAddr&);
|
||||
if (peerDiscovery4_)
|
||||
peerDiscovery4_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap), this,
|
||||
std::placeholders::_1,std::placeholders::_2));
|
||||
|
||||
if (peerDiscovery6_)
|
||||
peerDiscovery6_->startDiscovery(std::bind(static_cast<sig>(&DhtRunner::bootstrap), this,
|
||||
std::placeholders::_1,std::placeholders::_2));
|
||||
auto netId = config.dht_config.node_config.network;
|
||||
if (config.peer_discovery) {
|
||||
peerDiscovery_->startDiscovery<NodeInsertionPack>(PEER_DISCOVERY_DHT_SERVICE, [this, netId](NodeInsertionPack&& v, SockAddr&& addr){
|
||||
addr.setPort(v.port);
|
||||
if (v.nodeId != dht_->getNodeId() && netId == v.net){
|
||||
bootstrap(v.nodeId, addr);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (config.peer_publish) {
|
||||
if (peerDiscovery4_)
|
||||
peerDiscovery4_->startPublish(dht_->getNodeId(), getBoundPort(AF_INET));
|
||||
if (peerDiscovery6_)
|
||||
peerDiscovery6_->startPublish(dht_->getNodeId(), getBoundPort(AF_INET6));
|
||||
msgpack::sbuffer sbuf_node;
|
||||
NodeInsertionPack adc;
|
||||
adc.net = netId;
|
||||
adc.nodeId = dht_->getNodeId();
|
||||
// IPv4
|
||||
if (auto bound4 = dht_->getSocket()->getBound(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)) {
|
||||
adc.port = bound6.getPort();
|
||||
sbuf_node.clear();
|
||||
msgpack::pack(sbuf_node, adc);
|
||||
peerDiscovery_->startPublish(AF_INET6, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::shutdown(ShutdownCallback cb) {
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->shutdown(cb);
|
||||
#endif
|
||||
if (not running) {
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht& dht) mutable {
|
||||
dht.shutdown(cb);
|
||||
pending_ops_prio.emplace([=](SecureDht&) mutable {
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->shutdown(cb);
|
||||
#endif
|
||||
if (dht_)
|
||||
dht_->shutdown(cb);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -188,22 +238,28 @@ DhtRunner::shutdown(ShutdownCallback cb) {
|
||||
void
|
||||
DhtRunner::join()
|
||||
{
|
||||
stopNetwork();
|
||||
running = false;
|
||||
cv.notify_all();
|
||||
bootstrap_cv.notify_all();
|
||||
if (peerDiscovery4_) peerDiscovery4_->stop();
|
||||
if (peerDiscovery6_) peerDiscovery6_->stop();
|
||||
if (peerDiscovery_)
|
||||
peerDiscovery_->stop();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
running = false;
|
||||
cv.notify_all();
|
||||
bootstrap_cv.notify_all();
|
||||
if (dht_)
|
||||
if (auto sock = dht_->getSocket())
|
||||
sock->stop();
|
||||
}
|
||||
|
||||
if (dht_thread.joinable())
|
||||
dht_thread.join();
|
||||
|
||||
if (bootstrap_thread.joinable())
|
||||
bootstrap_thread.join();
|
||||
if (rcv_thread.joinable())
|
||||
rcv_thread.join();
|
||||
|
||||
if (peerDiscovery4_) peerDiscovery4_->join();
|
||||
if (peerDiscovery6_) peerDiscovery6_->join();
|
||||
if (peerDiscovery_) {
|
||||
peerDiscovery_->join();
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
@@ -218,6 +274,15 @@ DhtRunner::join()
|
||||
}
|
||||
}
|
||||
|
||||
SockAddr
|
||||
DhtRunner::getBound(sa_family_t af) const {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (dht_)
|
||||
if (auto sock = dht_->getSocket())
|
||||
return sock->getBound(af);
|
||||
return SockAddr{};
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::dumpTables() const
|
||||
{
|
||||
@@ -275,16 +340,22 @@ DhtRunner::exportValues() const {
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLoggers(LogMethod error, LogMethod warn, LogMethod debug) {
|
||||
DhtRunner::setLogger(const Logger& logger) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (dht_)
|
||||
dht_->setLoggers(error, warn, debug);
|
||||
dht_->setLogger(logger);
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
dht_via_proxy_->setLoggers(error, warn, debug);
|
||||
dht_via_proxy_->setLogger(logger);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLoggers(LogMethod error, LogMethod warn, LogMethod debug) {
|
||||
Logger logger {std::move(error), std::move(warn), std::move(debug)};
|
||||
setLogger(logger);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLogFilter(const InfoHash& f) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
@@ -439,20 +510,35 @@ DhtRunner::loop_()
|
||||
// move to stack
|
||||
received = std::move(rcv);
|
||||
}
|
||||
|
||||
// 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();
|
||||
dropped++;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle packets
|
||||
if (not received.empty()) {
|
||||
while (not received.empty()) {
|
||||
auto& pck = received.front();
|
||||
auto delay = clock::now() - pck.received;
|
||||
if (delay > std::chrono::milliseconds(500))
|
||||
std::cerr << "Dropping packet with high delay: " << print_dt(delay) << std::endl;
|
||||
if (clock::now() - pck->received > RX_QUEUE_MAX_DELAY)
|
||||
dropped++;
|
||||
else
|
||||
wakeup = dht->periodic(pck.data.data(), pck.data.size()-1, pck.from);
|
||||
wakeup = dht->periodic(pck->data.data(), pck->data.size(), std::move(pck->from));
|
||||
received.pop();
|
||||
}
|
||||
} else {
|
||||
// Or just run the scheduler
|
||||
wakeup = dht->periodic(nullptr, 0, nullptr, 0);
|
||||
}
|
||||
|
||||
if (dropped)
|
||||
std::cerr << "Dropped " << dropped << " packets with high delay" << std::endl;
|
||||
|
||||
NodeStatus nstatus4 = dht->getStatus(AF_INET);
|
||||
NodeStatus nstatus6 = dht->getStatus(AF_INET6);
|
||||
if (nstatus4 != status4 || nstatus6 != status6) {
|
||||
@@ -474,159 +560,6 @@ DhtRunner::loop_()
|
||||
return wakeup;
|
||||
}
|
||||
|
||||
|
||||
int bindSocket(const SockAddr& addr, SockAddr& bound)
|
||||
{
|
||||
bool is_ipv6 = addr.getFamily() == AF_INET6;
|
||||
int sock = socket(is_ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
throw DhtException(std::string("Can't open socket: ") + strerror(sock));
|
||||
int set = 1;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&set, sizeof(set));
|
||||
#endif
|
||||
if (is_ipv6)
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&set, sizeof(set));
|
||||
net::set_nonblocking(sock);
|
||||
int rc = bind(sock, addr.get(), addr.getLength());
|
||||
if(rc < 0) {
|
||||
rc = errno;
|
||||
close(sock);
|
||||
throw DhtException("Can't bind socket on " + addr.toString() + " " + strerror(rc));
|
||||
}
|
||||
sockaddr_storage ss;
|
||||
socklen_t ss_len = sizeof(ss);
|
||||
getsockname(sock, (sockaddr*)&ss, &ss_len);
|
||||
bound = {ss, ss_len};
|
||||
return sock;
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::stopNetwork()
|
||||
{
|
||||
running_network = false;
|
||||
if (stop_writefd != -1) {
|
||||
if (write(stop_writefd, "\0", 1) == -1) {
|
||||
perror("write");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::startNetwork(const SockAddr sin4, const SockAddr sin6)
|
||||
{
|
||||
stopNetwork();
|
||||
if (rcv_thread.joinable())
|
||||
rcv_thread.join();
|
||||
|
||||
int stopfds[2];
|
||||
#ifndef _WIN32
|
||||
auto status = pipe(stopfds);
|
||||
if (status == -1) {
|
||||
throw DhtException(std::string("Can't open pipe: ") + strerror(errno));
|
||||
}
|
||||
#else
|
||||
net::udpPipe(stopfds);
|
||||
#endif
|
||||
int stop_readfd = stopfds[0];
|
||||
stop_writefd = stopfds[1];
|
||||
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
|
||||
bound4 = {};
|
||||
if (sin4) {
|
||||
try {
|
||||
s4 = bindSocket(sin4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
std::cerr << "Can't bind inet socket: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
bound6 = {};
|
||||
if (sin6) {
|
||||
try {
|
||||
s6 = bindSocket(sin6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
std::cerr << "Can't bind inet6 socket: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s4 == -1 && s6 == -1) {
|
||||
throw DhtException("Can't bind socket");
|
||||
}
|
||||
|
||||
running_network = true;
|
||||
rcv_thread = std::thread([this, stop_readfd]() {
|
||||
try {
|
||||
while (running_network) {
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(stop_readfd, &readfds);
|
||||
if(s4 >= 0)
|
||||
FD_SET(s4, &readfds);
|
||||
if(s6 >= 0)
|
||||
FD_SET(s6, &readfds);
|
||||
|
||||
int selectFd = std::max({s4, s6, stop_readfd}) + 1;
|
||||
int rc = select(selectFd, &readfds, nullptr, nullptr, nullptr);
|
||||
if(rc < 0) {
|
||||
if(errno != EINTR) {
|
||||
perror("select");
|
||||
std::this_thread::sleep_for( std::chrono::seconds(1) );
|
||||
}
|
||||
}
|
||||
|
||||
if (not running_network)
|
||||
break;
|
||||
|
||||
if(rc > 0) {
|
||||
std::array<uint8_t, 1024 * 64> buf;
|
||||
sockaddr_storage from;
|
||||
socklen_t from_len = sizeof(from);
|
||||
|
||||
if(s4 >= 0 && FD_ISSET(s4, &readfds))
|
||||
rc = recvfrom(s4, (char*)buf.data(), buf.size(), 0, (sockaddr*)&from, &from_len);
|
||||
else if(s6 >= 0 && FD_ISSET(s6, &readfds))
|
||||
rc = recvfrom(s6, (char*)buf.data(), buf.size(), 0, (sockaddr*)&from, &from_len);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (rc > 0) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
if (rcv.size() >= RX_QUEUE_MAX_SIZE) {
|
||||
std::cerr << "Dropping packet: queue is full!" << std::endl;
|
||||
rcv.pop();
|
||||
}
|
||||
rcv.emplace(ReceivedPacket {Blob {buf.begin(), buf.begin()+rc+1}, SockAddr(from, from_len), clock::now()});
|
||||
}
|
||||
cv.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error in DHT networking thread: " << e.what() << std::endl;
|
||||
}
|
||||
if (s4 >= 0)
|
||||
close(s4);
|
||||
if (s6 >= 0)
|
||||
close(s6);
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
bound4 = {};
|
||||
bound6 = {};
|
||||
if (stop_readfd != -1)
|
||||
close(stop_readfd);
|
||||
if (stop_writefd != -1)
|
||||
close(stop_writefd);
|
||||
stop_writefd = -1;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f, Where w)
|
||||
{
|
||||
@@ -988,8 +921,7 @@ DhtRunner::findCertificate(InfoHash hash, std::function<void(const std::shared_p
|
||||
void
|
||||
DhtRunner::resetDht()
|
||||
{
|
||||
peerDiscovery4_.reset();
|
||||
peerDiscovery6_.reset();
|
||||
peerDiscovery_.reset();
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
listeners_.clear();
|
||||
dht_via_proxy_.reset();
|
||||
@@ -1011,6 +943,7 @@ void
|
||||
DhtRunner::setProxyServer(const std::string& proxy, const std::string& pushNodeId)
|
||||
{
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (config_.proxy_server == proxy and config_.push_node_id == pushNodeId)
|
||||
return;
|
||||
config_.proxy_server = proxy;
|
||||
@@ -1040,7 +973,7 @@ DhtRunner::enableProxy(bool proxify)
|
||||
}
|
||||
cv.notify_all();
|
||||
}
|
||||
}, config_.proxy_server, config_.push_node_id)
|
||||
}, 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
|
||||
@@ -1076,6 +1009,7 @@ DhtRunner::enableProxy(bool proxify)
|
||||
void
|
||||
DhtRunner::forwardAllMessages(bool forward)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_)
|
||||
@@ -1093,6 +1027,7 @@ DhtRunner::forwardAllMessages(bool forward)
|
||||
*/
|
||||
void
|
||||
DhtRunner::setPushNotificationToken(const std::string& token) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
|
||||
pushToken_ = token;
|
||||
if (dht_via_proxy_)
|
||||
|
||||
+519
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
|
||||
* Author: 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
|
||||
* 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 "http.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
constexpr char HTTP_HEADER_CONTENT_LENGTH[] = "Content-Length:";
|
||||
|
||||
// connection
|
||||
|
||||
Connection::Connection(asio::ip::tcp::socket socket, std::shared_ptr<dht::Logger> logger):
|
||||
id_(++ids_), socket_(std::move(socket)), logger_(logger)
|
||||
{}
|
||||
|
||||
Connection::~Connection(){
|
||||
close();
|
||||
}
|
||||
|
||||
ConnectionId
|
||||
Connection::id(){
|
||||
return id_;
|
||||
}
|
||||
|
||||
bool
|
||||
Connection::is_open(){
|
||||
return socket_.is_open();
|
||||
}
|
||||
|
||||
bool
|
||||
Connection::is_v6(){
|
||||
return endpoint_.address().is_v6();
|
||||
}
|
||||
|
||||
void
|
||||
Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
|
||||
{
|
||||
if (!is_open()){
|
||||
if (logger_)
|
||||
logger_->e("[connection:%i] closed, can't timeout", id_);
|
||||
return;
|
||||
}
|
||||
if (!timeout_timer_)
|
||||
timeout_timer_ = std::make_unique<asio::steady_timer>(io_context());
|
||||
timeout_timer_->expires_at(std::chrono::steady_clock::now() + timeout);
|
||||
timeout_timer_->async_wait([this, cb](const asio::error_code &ec){
|
||||
if (ec == asio::error_code::operation_aborted)
|
||||
return;
|
||||
else if (ec){
|
||||
if (logger_)
|
||||
logger_->e("[connection:%i] timeout error: %s", id_, ec.message().c_str());
|
||||
}
|
||||
if (cb)
|
||||
cb(ec);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Connection::close(){
|
||||
socket_.close();
|
||||
}
|
||||
|
||||
// connection listener
|
||||
|
||||
ConnectionListener::ConnectionListener()
|
||||
{}
|
||||
|
||||
ConnectionListener::ConnectionListener(std::shared_ptr<dht::DhtRunner> dht,
|
||||
std::shared_ptr<std::map<restinio::connection_id_t, http::ListenerSession>> listeners,
|
||||
std::shared_ptr<std::mutex> lock, std::shared_ptr<dht::Logger> logger):
|
||||
dht_(dht), lock_(lock), listeners_(listeners), logger_(logger)
|
||||
{}
|
||||
|
||||
ConnectionListener::~ConnectionListener()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionListener::state_changed(const restinio::connection_state::notice_t& notice) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(*lock_);
|
||||
auto id = notice.connection_id();
|
||||
auto cause = to_str(notice.cause());
|
||||
|
||||
if (listeners_->find(id) != listeners_->end()){
|
||||
if (notice.cause() == restinio::connection_state::cause_t::closed){
|
||||
if (logger_)
|
||||
logger_->d("[proxy:server] [connection:%li] cancelling listener", id);
|
||||
dht_->cancelListen(listeners_->at(id).hash,
|
||||
std::move(listeners_->at(id).token));
|
||||
listeners_->erase(id);
|
||||
if (logger_)
|
||||
logger_->d("[proxy:server] %li listeners are connected", listeners_->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
ConnectionListener::to_str(restinio::connection_state::cause_t cause) noexcept
|
||||
{
|
||||
std::string result;
|
||||
switch(cause)
|
||||
{
|
||||
case restinio::connection_state::cause_t::accepted:
|
||||
result = "accepted";
|
||||
break;
|
||||
case restinio::connection_state::cause_t::closed:
|
||||
result = "closed";
|
||||
break;
|
||||
case restinio::connection_state::cause_t::upgraded_to_websocket:
|
||||
result = "upgraded";
|
||||
break;
|
||||
default:
|
||||
result = "unknown";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// request
|
||||
|
||||
Request::Request(asio::io_context& ctx, const std::string host, const std::string service,
|
||||
const bool resolve, std::shared_ptr<dht::Logger> logger):
|
||||
id_(++ids_), resolver_(ctx), logger_(logger)
|
||||
{
|
||||
if (resolve)
|
||||
resolve(host, service);
|
||||
}
|
||||
|
||||
Request::~Request()
|
||||
{
|
||||
terminate();
|
||||
}
|
||||
|
||||
void
|
||||
Request::set_logger(std::shared_ptr<dht::Logger> logger)
|
||||
{
|
||||
logger_ = logger;
|
||||
}
|
||||
|
||||
void
|
||||
Request::terminate()
|
||||
{
|
||||
if (parser_)
|
||||
// ensure on_message_complete callback is called
|
||||
http_parser_execute(parser_.get(), parser_s_.get(), "", 0);
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] done", id_);
|
||||
}
|
||||
|
||||
bool
|
||||
Request::resolved()
|
||||
{
|
||||
return !endpoints_.empty();
|
||||
}
|
||||
|
||||
void
|
||||
Request::resolve(const std::string host, const std::string service, HandlerCb cb)
|
||||
{
|
||||
// build the query
|
||||
asio::ip::tcp::resolver::query query(host, service);
|
||||
|
||||
// resolve the query to the server
|
||||
resolver_.async_resolve(query, [this, host, service, cb]
|
||||
(const asio::error_code& ec, asio::ip::tcp::resolver::results_type endpoints)
|
||||
{
|
||||
if (ec){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] error resolving %s:%s: %s",
|
||||
id_, host.c_str(), service.c_str(), ec.message().c_str());
|
||||
}
|
||||
else {
|
||||
for (auto it = endpoints.begin(); it != endpoints.end(); ++it){
|
||||
if (logger_){
|
||||
asio::ip::tcp::endpoint endpoint = *it;
|
||||
logger_->d("[http:request:%i] resolved %s:%s: address=%s ipv%i",
|
||||
id_, host.c_str(), service.c_str(), endpoint.address().to_string().c_str(),
|
||||
endpoint.address().is_v6() ? 6 : 4);
|
||||
}
|
||||
}
|
||||
endpoints_ = endpoints;
|
||||
}
|
||||
if (cb)
|
||||
cb(ec);
|
||||
});
|
||||
}
|
||||
|
||||
std::string
|
||||
Request::build(const restinio::http_request_header_t header,
|
||||
const restinio::http_header_fields_t header_fields,
|
||||
const restinio::http_connection_header_t connection, const std::string body)
|
||||
{
|
||||
std::stringstream request;
|
||||
|
||||
// first header
|
||||
request << header.method().c_str() << " " << header.request_target() << " " <<
|
||||
"HTTP/" << header.http_major() << "." << header.http_minor() << "\r\n";
|
||||
|
||||
// other headers
|
||||
for (auto header_field: header_fields)
|
||||
request << header_field.name() << ": " << header_field.value() << "\r\n";
|
||||
|
||||
// last connection header
|
||||
std::string conn_str;
|
||||
switch (connection){
|
||||
case restinio::http_connection_header_t::keep_alive:
|
||||
conn_str = "keep-alive";
|
||||
break;
|
||||
case restinio::http_connection_header_t::close:
|
||||
conn_str = "close";
|
||||
break;
|
||||
case restinio::http_connection_header_t::upgrade:
|
||||
throw std::invalid_argument("upgrade");
|
||||
break;
|
||||
}
|
||||
request << "Connection: " << conn_str << "\r\n";
|
||||
|
||||
// body & content-length
|
||||
if (!body.empty()){
|
||||
request << "Content-Length: " << body.size() << "\r\n\r\n";
|
||||
request << body;
|
||||
}
|
||||
|
||||
// last delim
|
||||
request << "\r\n";
|
||||
return request.str();
|
||||
}
|
||||
|
||||
void
|
||||
Request::connect(ConnectionCb cb)
|
||||
{
|
||||
if (endpoints_.empty()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request] [connect] host not resolved");
|
||||
if (cb)
|
||||
cb(asio::error::connection_aborted, nullptr);
|
||||
return;
|
||||
}
|
||||
auto socket = asio::ip::tcp::socket{resolver_.get_io_context()};
|
||||
conn_ = std::make_shared<Connection>(std::move(socket));
|
||||
|
||||
// try to connect to any until one works
|
||||
asio::async_connect(conn_->socket_, endpoints_, [this, conn, cb]
|
||||
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
|
||||
if (ec){ // all endpoints failed
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [connect] failed to connect to any endpoints", id_);
|
||||
}
|
||||
else {
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] [connect] success", id_);
|
||||
// save the associated endpoint
|
||||
conn_->endpoint_ = endpoint;
|
||||
}
|
||||
if (cb)
|
||||
cb(ec, conn_);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Request::send(std::string request, std::unique_ptr<http_parser> parser,
|
||||
std::unique_ptr<http_parser_settings> parser_s, HandlerCb cb)
|
||||
{
|
||||
if (endpoints_.empty()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [send] unresolved destination", id_);
|
||||
if (cb)
|
||||
cb(asio::error::addrinfo_errors::service_not_found);
|
||||
}
|
||||
if (!conn_){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [send] uninitialized connection", id_);
|
||||
if (cb)
|
||||
cb(asio::error::not_connected);
|
||||
}
|
||||
else if (!conn_->is_open()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request] [send] closed connection");
|
||||
if (cb)
|
||||
cb(asio::error::not_connected);
|
||||
}
|
||||
else {
|
||||
// save the request context
|
||||
request_ = request;
|
||||
parser_ = std::move(parser);
|
||||
parser_s_ = std::move(parser_s);
|
||||
|
||||
// write the request to buffer
|
||||
std::ostream request_stream(&conn_->request_);
|
||||
request_stream << request;
|
||||
|
||||
// send the request
|
||||
asio::async_write(conn_->socket_, conn_->request_,
|
||||
std::bind(&Request::handle_request, this, std::placeholders::_1, cb));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Request::handle_request(const asio::error_code& ec, HandlerCb cb)
|
||||
{
|
||||
if (!conn_->is_open()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [write] closed connection", id_);
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(asio::error::not_connected);
|
||||
return;
|
||||
}
|
||||
if (ec and ec != asio::error::eof){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [write] error: %s", id_, ec.message().c_str());
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] [write] success", id_);
|
||||
|
||||
// read response
|
||||
asio::async_read_until(conn_->socket_, conn_->response_chunk_, "\r\n\r\n",
|
||||
std::bind(&Request::handle_response_header, this,
|
||||
std::placeholders::_1, std::placeholders::_2, cb));
|
||||
}
|
||||
|
||||
void
|
||||
Request::handle_response_header(const asio::error_code& ec, const size_t bytes, HandlerCb cb)
|
||||
{
|
||||
if (!conn_->is_open()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [read:header] closed connection", id_);
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(asio::error::not_connected);
|
||||
return;
|
||||
}
|
||||
if (ec && ec != asio::error::eof){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [read:header] error: %s", id_, ec.message().c_str());
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
else if ((ec == asio::error::eof) || (ec == asio::error::connection_reset)){
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
// read the response buffer
|
||||
std::ostringstream str_s;
|
||||
str_s << &conn_->response_chunk_;
|
||||
auto chunk = str_s.str();
|
||||
auto header = chunk.substr(0, bytes);
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] [read:header]:\n%s", id_, header.c_str());
|
||||
// parse the header right away
|
||||
parse_request(header, conn_->id());
|
||||
|
||||
unsigned int content_length = get_content_length(header);
|
||||
// has body size
|
||||
if (content_length){
|
||||
// append current body chunk
|
||||
auto body_chunk = chunk.substr(bytes, std::string::npos);
|
||||
conn_->response_body_.append(body_chunk);
|
||||
// read the rest of body
|
||||
asio::async_read(conn_->socket_, conn_->response_chunk_,
|
||||
asio::transfer_exactly(content_length - (body_chunk.size())),
|
||||
std::bind(&Request::handle_response_body, this,
|
||||
std::placeholders::_1, content_length, conn, cb));
|
||||
return;
|
||||
}
|
||||
// has potential body but no content-length (current proxy behavior on key get/listen)
|
||||
else if (header.find("Content-Type: application/json") != std::string::npos){
|
||||
auto body_chunk = chunk.substr(bytes, std::string::npos);
|
||||
if (!body_chunk.empty()){
|
||||
parse_request(body_chunk, conn_->id());
|
||||
}
|
||||
// keep reading
|
||||
asio::async_read(conn_->socket_, conn_->response_chunk_, asio::transfer_at_least(1),
|
||||
std::bind(&Request::handle_response_body, this,
|
||||
std::placeholders::_1, std::placeholders::_2, conn, cb));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Request::handle_response_body(const asio::error_code& ec, const size_t bytes,
|
||||
std::shared_ptr<Connection> conn, HandlerCb cb)
|
||||
{
|
||||
if (!conn_->is_open()){
|
||||
if (logger_)
|
||||
logger_->e("[http:request] [read:body] closed connection");
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(asio::error::not_connected);
|
||||
return;
|
||||
}
|
||||
if (ec && ec != asio::error::eof){
|
||||
if (logger_)
|
||||
logger_->e("[http:request:%i] [read:body] error: %s", id_, ec.message().c_str());
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
else if ((ec == asio::error::eof) || (ec == asio::error::connection_reset)){
|
||||
terminate();
|
||||
if (cb)
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
std::string body;
|
||||
if (!conn_->response_body_.empty()){
|
||||
// append previous incomplete chunk from header
|
||||
body.append(conn_->response_body_);
|
||||
}
|
||||
// read the response buffer
|
||||
std::ostringstream str_s;
|
||||
str_s << &conn_->response_chunk_;
|
||||
body.append(str_s.str().substr(0, bytes));
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] [read:body] success:\n%s", id_, body.c_str());
|
||||
|
||||
parse_request(body);
|
||||
conn_->response_body_.clear();
|
||||
|
||||
asio::async_read(conn_->socket_, conn_->response_chunk_, asio::transfer_at_least(1),
|
||||
std::bind(&Request::handle_response_body, this,
|
||||
std::placeholders::_1, std::placeholders::_2, conn, cb));
|
||||
}
|
||||
|
||||
void
|
||||
Request::parse_request(const std::string request)
|
||||
{
|
||||
http_parser_execute(parser_.get(), parser_s_.get(), request.c_str(), request.size());
|
||||
// detect parsing errors
|
||||
if (HPE_OK != parser_->http_errno && HPE_PAUSED != parser_->http_errno){
|
||||
if (logger_){
|
||||
auto err = HTTP_PARSER_ERRNO(parser_.get());
|
||||
logger_->e("[http:request:%i] [parse] error: %s", id_, http_errno_name(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
Request::get_content_length(const std::string str)
|
||||
{
|
||||
size_t content_length = 0;
|
||||
auto content_length_i = str.find(HTTP_HEADER_CONTENT_LENGTH);
|
||||
if (content_length_i != std::string::npos){
|
||||
auto content_length_str = str.substr(content_length_i + std::strlen(HTTP_HEADER_CONTENT_LENGTH) + 1,
|
||||
str.find("\r\n", content_length_i));
|
||||
try {
|
||||
content_length = atoi(content_length_str.c_str());
|
||||
}
|
||||
catch (const std::exception& e){
|
||||
if (logger_)
|
||||
logger_->d("[http:request:%i] [content-length] invalid '%s': %s",
|
||||
id_, content_length_str.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
return content_length;
|
||||
}
|
||||
|
||||
|
||||
Resolver::Resolver(asio::io_context& ctx, const std::string& host, const std::string& service)
|
||||
{
|
||||
resolver_.async_resolve({host, service}, [this]
|
||||
(const asio::error_code& ec, asio::ip::tcp::resolver::results_type endpoints)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(cbsMutex_);
|
||||
while (not cbs_.empty()) {
|
||||
cbs_.front()(ec, endpoints);
|
||||
cbs_.pop();
|
||||
}
|
||||
error_ = ec;
|
||||
endpoints_ = endpoints;
|
||||
completed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Resolver::addOnResolved(ResolvedCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(cbsMutex_);
|
||||
if (completed_) {
|
||||
cb(error_, endpoints_);
|
||||
} else {
|
||||
cbs_.push(std::move(cb));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private:
|
||||
std::mutex cbsMutex_;
|
||||
std::queue<ResolvedCb> cbs_;
|
||||
|
||||
asio::ip::tcp::resolver resolver_;
|
||||
asio::error_code error_;
|
||||
asio::ip::basic_resolver_results<asio::ip::tcp> endpoints_;
|
||||
} */
|
||||
|
||||
|
||||
} // namespace http
|
||||
+31
-14
@@ -55,9 +55,9 @@ printLog(std::ostream& s, char const *m, va_list args) {
|
||||
s << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
enableLogging(dht::DhtRunner &dht) {
|
||||
dht.setLoggers(
|
||||
std::unique_ptr<Logger>
|
||||
getStdLogger() {
|
||||
return std::unique_ptr<Logger>(new Logger(
|
||||
[](char const *m, va_list args) {
|
||||
std::cerr << red;
|
||||
printLog(std::cerr, m, args);
|
||||
@@ -69,23 +69,23 @@ enableLogging(dht::DhtRunner &dht) {
|
||||
std::cout << def;
|
||||
},
|
||||
[](char const *m, va_list args) { printLog(std::cout, m, args); }
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
void
|
||||
enableFileLogging(dht::DhtRunner &dht, const std::string &path) {
|
||||
auto logfile = std::make_shared<std::fstream>();
|
||||
std::unique_ptr<Logger>
|
||||
getFileLogger(const std::string &path) {
|
||||
auto logfile = std::make_shared<std::ofstream>();
|
||||
logfile->open(path, std::ios::out);
|
||||
|
||||
dht.setLoggers(
|
||||
return std::unique_ptr<Logger>(new Logger(
|
||||
[=](char const *m, va_list args) { printLog(*logfile, m, args); },
|
||||
[=](char const *m, va_list args) { printLog(*logfile, m, args); },
|
||||
[=](char const *m, va_list args) { printLog(*logfile, m, args); }
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
OPENDHT_PUBLIC void
|
||||
enableSyslog(dht::DhtRunner &dht, const char* name) {
|
||||
std::unique_ptr<Logger>
|
||||
getSyslogLogger(const char* name) {
|
||||
#ifndef _WIN32
|
||||
struct Syslog {
|
||||
Syslog(const char* n) {
|
||||
@@ -102,17 +102,34 @@ enableSyslog(dht::DhtRunner &dht, const char* name) {
|
||||
logfile = std::make_shared<Syslog>(name);
|
||||
opened_logfile = logfile;
|
||||
}
|
||||
dht.setLoggers(
|
||||
return std::unique_ptr<Logger>(new Logger(
|
||||
[logfile](char const *m, va_list args) { vsyslog(LOG_ERR, m, args); },
|
||||
[logfile](char const *m, va_list args) { vsyslog(LOG_WARNING, m, args); },
|
||||
[logfile](char const *m, va_list args) { vsyslog(LOG_INFO, m, args); }
|
||||
);
|
||||
));
|
||||
#else
|
||||
return std::unique_ptr<Logger>(new Logger());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
enableLogging(dht::DhtRunner &dht) {
|
||||
dht.setLogger(*getStdLogger());
|
||||
}
|
||||
|
||||
void
|
||||
enableFileLogging(dht::DhtRunner &dht, const std::string &path) {
|
||||
dht.setLogger(*getFileLogger(path));
|
||||
}
|
||||
|
||||
OPENDHT_PUBLIC void
|
||||
enableSyslog(dht::DhtRunner &dht, const char* name) {
|
||||
dht.setLogger(*getSyslogLogger(name));
|
||||
}
|
||||
|
||||
void
|
||||
disableLogging(dht::DhtRunner &dht) {
|
||||
dht.setLoggers(dht::NOLOG, dht::NOLOG, dht::NOLOG);
|
||||
dht.setLogger({});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
-51
@@ -43,9 +43,7 @@ constexpr std::chrono::seconds NetworkEngine::RX_TIMEOUT;
|
||||
const std::string NetworkEngine::my_v {"RNG1"};
|
||||
constexpr size_t NetworkEngine::MAX_REQUESTS_PER_SEC;
|
||||
|
||||
static constexpr uint8_t v4prefix[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0
|
||||
};
|
||||
static constexpr uint8_t v4prefix[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0};
|
||||
|
||||
constexpr unsigned SEND_NODES {8};
|
||||
|
||||
@@ -101,11 +99,11 @@ RequestAnswer::RequestAnswer(ParsedMessage&& msg)
|
||||
nodes6(std::move(msg.nodes6))
|
||||
{}
|
||||
|
||||
NetworkEngine::NetworkEngine(Logger& log, Scheduler& scheduler, const int& s, const int& s6)
|
||||
: myid(zeroes), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
|
||||
NetworkEngine::NetworkEngine(Logger& log, Scheduler& scheduler, std::unique_ptr<DatagramSocket>&& sock)
|
||||
: myid(zeroes), dht_socket(std::move(sock)), DHT_LOG(log), scheduler(scheduler)
|
||||
{}
|
||||
|
||||
NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, const int& s, const int& s6, Logger& log, Scheduler& scheduler,
|
||||
NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, std::unique_ptr<DatagramSocket>&& sock, Logger& log, Scheduler& scheduler,
|
||||
decltype(NetworkEngine::onError)&& onError,
|
||||
decltype(NetworkEngine::onNewNode)&& onNewNode,
|
||||
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
|
||||
@@ -124,7 +122,7 @@ NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, const int& s, const int&
|
||||
onListen(std::move(onListen)),
|
||||
onAnnounce(std::move(onAnnounce)),
|
||||
onRefresh(std::move(onRefresh)),
|
||||
myid(myid), network(net), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
|
||||
myid(myid), network(net), dht_socket(std::move(sock)), DHT_LOG(log), scheduler(scheduler)
|
||||
{}
|
||||
|
||||
NetworkEngine::~NetworkEngine() {
|
||||
@@ -172,7 +170,7 @@ NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&,
|
||||
}
|
||||
|
||||
// send response
|
||||
send(buffer.data(), buffer.size(), 0, n->getAddr());
|
||||
send(n->getAddr(), buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -202,7 +200,7 @@ NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, c
|
||||
}
|
||||
|
||||
// send response
|
||||
send(buffer.data(), buffer.size(), 0, n->getAddr());
|
||||
send(n->getAddr(), buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -211,11 +209,11 @@ NetworkEngine::isRunning(sa_family_t af) const
|
||||
{
|
||||
switch (af) {
|
||||
case 0:
|
||||
return dht_socket >= 0 || dht_socket6 >= 0;
|
||||
return dht_socket->hasIPv4() or dht_socket->hasIPv6();
|
||||
case AF_INET:
|
||||
return dht_socket >= 0;
|
||||
return dht_socket->hasIPv4();
|
||||
case AF_INET6:
|
||||
return dht_socket6 >= 0;
|
||||
return dht_socket->hasIPv6();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -256,9 +254,7 @@ NetworkEngine::requestStep(Sp<Request> sreq)
|
||||
req.on_expired(req, false);
|
||||
}
|
||||
|
||||
auto err = send((char*)req.msg.data(), req.msg.size(),
|
||||
(node.getReplyTime() >= now - UDP_REPLY_TIME) ? 0 : MSG_CONFIRM,
|
||||
node.getAddr());
|
||||
auto err = send(node.getAddr(), (char*)req.msg.data(), req.msg.size(), node.getReplyTime() < now - UDP_REPLY_TIME);
|
||||
if (err == ENETUNREACH ||
|
||||
err == EHOSTUNREACH ||
|
||||
err == EAFNOSUPPORT ||
|
||||
@@ -288,11 +284,11 @@ NetworkEngine::requestStep(Sp<Request> sreq)
|
||||
void
|
||||
NetworkEngine::sendRequest(const Sp<Request>& request)
|
||||
{
|
||||
auto& node = request->node;
|
||||
if (not node->id)
|
||||
auto& node = *request->node;
|
||||
if (not node.id)
|
||||
requests.emplace(request->tid, request);
|
||||
request->start = scheduler.time();
|
||||
node->requested(request);
|
||||
node.requested(request);
|
||||
requestStep(request);
|
||||
}
|
||||
|
||||
@@ -361,8 +357,9 @@ NetworkEngine::isNodeBlacklisted(const SockAddr& addr) const
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, const SockAddr& from)
|
||||
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());
|
||||
return;
|
||||
@@ -612,33 +609,9 @@ insertAddr(msgpack::packer<msgpack::sbuffer>& pk, const SockAddr& addr)
|
||||
}
|
||||
|
||||
int
|
||||
NetworkEngine::send(const char *buf, size_t len, int flags, const SockAddr& addr)
|
||||
NetworkEngine::send(const SockAddr& addr, const char *buf, size_t len, bool confirmed)
|
||||
{
|
||||
if (not addr)
|
||||
return EFAULT;
|
||||
|
||||
int s;
|
||||
if (addr.getFamily() == AF_INET)
|
||||
s = dht_socket;
|
||||
else if (addr.getFamily() == AF_INET6)
|
||||
s = dht_socket6;
|
||||
else
|
||||
s = -1;
|
||||
|
||||
if (s < 0)
|
||||
return EAFNOSUPPORT;
|
||||
#ifdef MSG_NOSIGNAL
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
if (sendto(s, buf, len, flags, addr.get(), addr.getLength()) == -1) {
|
||||
int err = errno;
|
||||
DHT_LOG.e("Can't send message to %s: %s", addr.toString().c_str(), strerror(err));
|
||||
if (err == EPIPE) {
|
||||
throw SocketException(EPIPE);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
return dht_socket ? dht_socket->sendTo(addr, (const uint8_t*)buf, len, confirmed) : ENOTCONN;
|
||||
}
|
||||
|
||||
Sp<Request>
|
||||
@@ -698,7 +671,7 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
|
||||
pk.pack(KEY_NETID); pk.pack(network);
|
||||
}
|
||||
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
Sp<Request>
|
||||
@@ -900,7 +873,7 @@ NetworkEngine::sendValueParts(const TransId& tid, const std::vector<Blob>& svals
|
||||
pk.pack(std::string("o")); pk.pack(start);
|
||||
pk.pack(std::string("d")); pk.pack_bin(end-start);
|
||||
pk.pack_bin_body((const char*)v.data()+start, end-start);
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
start = end;
|
||||
} while (start != v.size());
|
||||
i++;
|
||||
@@ -959,7 +932,7 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
|
||||
}
|
||||
|
||||
// send response
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
|
||||
// send parts
|
||||
if (not svals.empty())
|
||||
@@ -1102,7 +1075,7 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
|
||||
pk.pack(KEY_NETID); pk.pack(network);
|
||||
}
|
||||
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
Sp<Request>
|
||||
@@ -1236,7 +1209,7 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
|
||||
pk.pack(KEY_NETID); pk.pack(network);
|
||||
}
|
||||
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1268,7 +1241,7 @@ NetworkEngine::sendError(const SockAddr& addr,
|
||||
pk.pack(KEY_NETID); pk.pack(network);
|
||||
}
|
||||
|
||||
send(buffer.data(), buffer.size(), 0, addr);
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+254
-2
@@ -20,7 +20,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "utils.h"
|
||||
#include "sockaddr.h"
|
||||
#include <io.h>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
@@ -30,11 +29,40 @@
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace dht {
|
||||
namespace net {
|
||||
|
||||
int
|
||||
bindSocket(const SockAddr& addr, SockAddr& bound)
|
||||
{
|
||||
bool is_ipv6 = addr.getFamily() == AF_INET6;
|
||||
int sock = socket(is_ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
throw DhtException(std::string("Can't open socket: ") + strerror(sock));
|
||||
int set = 1;
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&set, sizeof(set));
|
||||
#endif
|
||||
if (is_ipv6)
|
||||
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&set, sizeof(set));
|
||||
net::setNonblocking(sock);
|
||||
int rc = bind(sock, addr.get(), addr.getLength());
|
||||
if (rc < 0) {
|
||||
rc = errno;
|
||||
close(sock);
|
||||
throw DhtException("Can't bind socket on " + addr.toString() + " " + strerror(rc));
|
||||
}
|
||||
sockaddr_storage ss;
|
||||
socklen_t ss_len = sizeof(ss);
|
||||
getsockname(sock, (sockaddr*)&ss, &ss_len);
|
||||
bound = {ss, ss_len};
|
||||
return sock;
|
||||
}
|
||||
|
||||
bool
|
||||
set_nonblocking(int fd, bool nonblocking)
|
||||
setNonblocking(int fd, bool nonblocking)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
unsigned long mode = !!nonblocking;
|
||||
@@ -77,5 +105,229 @@ void udpPipe(int fds[2])
|
||||
}
|
||||
#endif
|
||||
|
||||
UdpSocket::UdpSocket(in_port_t port, const Logger& l) : logger(l) {
|
||||
SockAddr bind4;
|
||||
bind4.setFamily(AF_INET);
|
||||
bind4.setPort(port);
|
||||
SockAddr bind6;
|
||||
bind6.setFamily(AF_INET6);
|
||||
bind6.setPort(port);
|
||||
openSockets(bind4, bind6);
|
||||
}
|
||||
|
||||
UdpSocket::UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const Logger& l) : logger(l)
|
||||
{
|
||||
openSockets(bind4, bind6);
|
||||
}
|
||||
|
||||
UdpSocket::~UdpSocket() {
|
||||
stop();
|
||||
if (rcv_thread.joinable())
|
||||
rcv_thread.join();
|
||||
}
|
||||
|
||||
int
|
||||
UdpSocket::sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) {
|
||||
if (not dest)
|
||||
return EFAULT;
|
||||
|
||||
int s;
|
||||
switch (dest.getFamily()) {
|
||||
case AF_INET: s = s4; break;
|
||||
case AF_INET6: s = s6; break;
|
||||
default: s = -1; break;
|
||||
}
|
||||
|
||||
if (s < 0)
|
||||
return EAFNOSUPPORT;
|
||||
|
||||
int flags = 0;
|
||||
#ifdef MSG_CONFIRM
|
||||
if (replied)
|
||||
flags |= MSG_CONFIRM;
|
||||
#endif
|
||||
#ifdef MSG_NOSIGNAL
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
|
||||
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 (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
auto bind4 = std::move(bound4), bind6 = std::move(bound6);
|
||||
openSockets(bind4, bind6);
|
||||
return sendTo(dest, data, size, false);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
{
|
||||
stop();
|
||||
if (rcv_thread.joinable())
|
||||
rcv_thread.join();
|
||||
|
||||
int stopfds[2];
|
||||
#ifndef _WIN32
|
||||
auto status = pipe(stopfds);
|
||||
if (status == -1) {
|
||||
throw DhtException(std::string("Can't open pipe: ") + strerror(errno));
|
||||
}
|
||||
#else
|
||||
udpPipe(stopfds);
|
||||
#endif
|
||||
int stop_readfd = stopfds[0];
|
||||
stopfd = stopfds[1];
|
||||
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
|
||||
bound4 = {};
|
||||
if (bind4) {
|
||||
try {
|
||||
s4 = bindSocket(bind4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
bound6 = {};
|
||||
if (bind6) {
|
||||
if (bind6.getPort() == 0) {
|
||||
// Attempt to use the same port as IPv4 with IPv6
|
||||
if (auto p4 = bound4.getPort()) {
|
||||
auto b6 = bind6;
|
||||
b6.setPort(p4);
|
||||
try {
|
||||
s6 = bindSocket(b6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s6 == -1) {
|
||||
try {
|
||||
s6 = bindSocket(bind6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s4 == -1 && s6 == -1) {
|
||||
throw DhtException("Can't bind socket");
|
||||
}
|
||||
|
||||
running = true;
|
||||
rcv_thread = std::thread([this, stop_readfd]() {
|
||||
int selectFd = std::max({s4, s6, stop_readfd}) + 1;
|
||||
try {
|
||||
while (running) {
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(stop_readfd, &readfds);
|
||||
if(s4 >= 0)
|
||||
FD_SET(s4, &readfds);
|
||||
if(s6 >= 0)
|
||||
FD_SET(s6, &readfds);
|
||||
|
||||
int rc = select(selectFd, &readfds, nullptr, nullptr, nullptr);
|
||||
if (rc < 0) {
|
||||
if (errno != EINTR) {
|
||||
logger.e("Select error: %s", strerror(errno));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (not running)
|
||||
break;
|
||||
|
||||
if (rc > 0) {
|
||||
std::array<uint8_t, 1024 * 64> buf;
|
||||
sockaddr_storage from;
|
||||
socklen_t from_len = sizeof(from);
|
||||
|
||||
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));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (s4 >= 0 && FD_ISSET(s4, &readfds))
|
||||
rc = recvfrom(s4, (char*)buf.data(), buf.size(), 0, (sockaddr*)&from, &from_len);
|
||||
else if (s6 >= 0 && FD_ISSET(s6, &readfds))
|
||||
rc = recvfrom(s6, (char*)buf.data(), buf.size(), 0, (sockaddr*)&from, &from_len);
|
||||
else
|
||||
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));
|
||||
} else if (rc == -1) {
|
||||
logger.e("Error receiving packet: %s", strerror(errno));
|
||||
int err = errno;
|
||||
if (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
if (s4 >= 0) {
|
||||
close(s4);
|
||||
try {
|
||||
s4 = bindSocket(bound4, bound4);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
if (s6 >= 0) {
|
||||
close(s6);
|
||||
try {
|
||||
s6 = bindSocket(bound6, bound6);
|
||||
} catch (const DhtException& e) {
|
||||
logger.e("Can't bind inet6 socket: %s", e.what());
|
||||
}
|
||||
}
|
||||
if (s4 < 0 && s6 < 0)
|
||||
break;
|
||||
selectFd = std::max({s4, s6, stop_readfd}) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
logger.e("Error in UdpSocket rx thread: %s", e.what());
|
||||
}
|
||||
if (s4 >= 0)
|
||||
close(s4);
|
||||
if (s6 >= 0)
|
||||
close(s6);
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
bound4 = {};
|
||||
bound6 = {};
|
||||
if (stop_readfd != -1)
|
||||
close(stop_readfd);
|
||||
if (stopfd != -1)
|
||||
close(stopfd);
|
||||
stopfd = -1;
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -105,14 +105,11 @@ public:
|
||||
void onValuesExpired(const std::vector<Sp<Value>>& vals);
|
||||
|
||||
bool addListener(size_t token, const ValueCallback& cb, const Sp<Query>& q, const Value::Filter& filter) {
|
||||
listeners.emplace(token, LocalListener{q, filter, cb});
|
||||
auto cached = cache.get(filter);
|
||||
if (not cached.empty()) {
|
||||
auto ret = cb(cached, false);
|
||||
if (not ret)
|
||||
listeners.erase(token);
|
||||
return ret;
|
||||
if (not cached.empty() and not cb(cached, false)) {
|
||||
return false;
|
||||
}
|
||||
listeners.emplace(token, LocalListener{q, filter, cb});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+371
-111
@@ -18,32 +18,145 @@
|
||||
|
||||
#include "peer_discovery.h"
|
||||
#include "network_utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Ws2tcpip.h> // needed for ip_mreq definition for multicast
|
||||
#include <Windows.h>
|
||||
#include <cstring>
|
||||
#if defined(_MSC_VER)
|
||||
#include <BaseTsd.h>
|
||||
typedef SSIZE_T ssize_t;
|
||||
#endif
|
||||
#define close(x) closesocket(x)
|
||||
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef IPV6_JOIN_GROUP
|
||||
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
|
||||
constexpr char MULTICAST_ADDRESS_IPV4[10] = "224.0.0.1";
|
||||
constexpr char MULTICAST_ADDRESS_IPV6[8] = "ff05::2"; // Site-local multicast
|
||||
// Organization-local Scope multicast
|
||||
constexpr char MULTICAST_ADDRESS_IPV4[12] = "239.192.0.1";
|
||||
constexpr char MULTICAST_ADDRESS_IPV6[10] = "ff08::101";
|
||||
|
||||
PeerDiscovery::PeerDiscovery(sa_family_t domain, in_port_t port)
|
||||
|
||||
class PeerDiscovery::DomainPeerDiscovery
|
||||
{
|
||||
public:
|
||||
DomainPeerDiscovery(sa_family_t domain, in_port_t port);
|
||||
~DomainPeerDiscovery();
|
||||
|
||||
/**
|
||||
* startDiscovery - Keep Listening data from the sender until node is joinned or stop is called
|
||||
*/
|
||||
void startDiscovery(const std::string &type, ServiceDiscoveredCallback callback);
|
||||
|
||||
/**
|
||||
* startPublish - Keeping sending data until node is joinned or stop is called - msgpack
|
||||
*/
|
||||
void startPublish(const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
|
||||
/**
|
||||
* Thread Stopper
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Remove possible callBack to discovery
|
||||
*/
|
||||
bool stopDiscovery(const std::string &type);
|
||||
|
||||
/**
|
||||
* Remove different serivce message to send
|
||||
*/
|
||||
bool stopPublish(const std::string &type);
|
||||
|
||||
/**
|
||||
* Configure the sockopt to be able to listen multicast group
|
||||
*/
|
||||
static void socketJoinMulticast(int sockfd, sa_family_t family);
|
||||
|
||||
/**
|
||||
* Join the threads
|
||||
*/
|
||||
void join() {
|
||||
if(running_listen_.joinable()) running_listen_.join();
|
||||
if(running_send_.joinable()) running_send_.join();
|
||||
}
|
||||
private:
|
||||
//dmtx_ for callbackmap_ and drunning_ (write)
|
||||
std::mutex dmtx_;
|
||||
//mtx_ for messages_ and lrunning (listen)
|
||||
std::mutex mtx_;
|
||||
std::condition_variable cv_;
|
||||
bool lrunning_ {false};
|
||||
bool drunning_ {false};
|
||||
sa_family_t domain_ {AF_UNSPEC};
|
||||
int port_;
|
||||
int sockfd_ {-1};
|
||||
int stop_writefd_ {-1};
|
||||
|
||||
SockAddr sockAddrSend_;
|
||||
|
||||
//Thread export to be joined
|
||||
std::thread running_listen_;
|
||||
std::thread running_send_;
|
||||
|
||||
msgpack::sbuffer sbuf_;
|
||||
std::map<std::string, msgpack::sbuffer> messages_;
|
||||
std::map<std::string, ServiceDiscoveredCallback> callbackmap_;
|
||||
|
||||
/**
|
||||
* Multicast Socket Initialization, accept IPV4, IPV6
|
||||
*/
|
||||
static int initialize_socket(sa_family_t domain);
|
||||
|
||||
/**
|
||||
* Receive messages
|
||||
*/
|
||||
std::pair<SockAddr, msgpack::object_handle> recvFrom();
|
||||
|
||||
/**
|
||||
* Listener pack thread loop
|
||||
*/
|
||||
void listenerpack_thread();
|
||||
|
||||
/**
|
||||
* Listener Parameters Setup
|
||||
*/
|
||||
void listener_setup();
|
||||
|
||||
/**
|
||||
* Sender Parameters Setup
|
||||
*/
|
||||
void sender_setup();
|
||||
/**
|
||||
* Sender Parameters Setup
|
||||
*/
|
||||
void messages_reload();
|
||||
|
||||
void stopDiscovery();
|
||||
void stopPublish();
|
||||
};
|
||||
|
||||
PeerDiscovery::DomainPeerDiscovery::DomainPeerDiscovery(sa_family_t domain, in_port_t port)
|
||||
: domain_(domain), port_(port), sockfd_(initialize_socket(domain))
|
||||
{
|
||||
socketJoinMulticast(sockfd_, domain);
|
||||
listener_setup();
|
||||
sender_setup();
|
||||
}
|
||||
|
||||
PeerDiscovery::~PeerDiscovery()
|
||||
PeerDiscovery::DomainPeerDiscovery::~DomainPeerDiscovery()
|
||||
{
|
||||
stop();
|
||||
join();
|
||||
if (sockfd_ != -1)
|
||||
close(sockfd_);
|
||||
|
||||
@@ -53,7 +166,7 @@ PeerDiscovery::~PeerDiscovery()
|
||||
}
|
||||
|
||||
int
|
||||
PeerDiscovery::initialize_socket(sa_family_t domain)
|
||||
PeerDiscovery::DomainPeerDiscovery::initialize_socket(sa_family_t domain)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
@@ -66,12 +179,12 @@ PeerDiscovery::initialize_socket(sa_family_t domain)
|
||||
if (sockfd < 0) {
|
||||
throw std::runtime_error(std::string("Socket Creation Error: ") + strerror(errno));
|
||||
}
|
||||
net::set_nonblocking(sockfd);
|
||||
net::setNonblocking(sockfd);
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::listener_setup()
|
||||
PeerDiscovery::DomainPeerDiscovery::listener_setup()
|
||||
{
|
||||
SockAddr sockAddrListen_;
|
||||
sockAddrListen_.setFamily(domain_);
|
||||
@@ -79,12 +192,14 @@ PeerDiscovery::listener_setup()
|
||||
sockAddrListen_.setAny();
|
||||
|
||||
unsigned int opt = 1;
|
||||
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0) {
|
||||
std::cerr << "setsockopt SO_REUSEADDR failed: " << strerror(errno) << std::endl;
|
||||
}
|
||||
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(sockfd_, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)) < 0) {
|
||||
std::cerr << "setsockopt SO_REUSEPORT failed: " << strerror(errno) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// bind to receive address
|
||||
if (bind(sockfd_, sockAddrListen_.get(), sockAddrListen_.getLength()) < 0){
|
||||
@@ -93,7 +208,7 @@ PeerDiscovery::listener_setup()
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
|
||||
PeerDiscovery::DomainPeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
|
||||
{
|
||||
switch (family)
|
||||
{
|
||||
@@ -103,14 +218,14 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
|
||||
//This option can be used to set the interface for sending outbound
|
||||
//multicast datagrams from the sockets application.
|
||||
config_ipv4.imr_interface.s_addr = htonl(INADDR_ANY);
|
||||
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) {
|
||||
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (char*)&config_ipv4.imr_interface, sizeof( struct in_addr )) < 0 ) {
|
||||
throw std::runtime_error(std::string("Bound Network Interface IPv4 Error: ") + strerror(errno));
|
||||
}
|
||||
|
||||
//The IP_MULTICAST_TTL socket option allows the application to primarily
|
||||
//limit the lifetime of the packet in the Internet and prevent it from circulating indefinitely
|
||||
unsigned char ttl4 = 20;
|
||||
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl4, sizeof( ttl4 )) < 0 ) {
|
||||
if( setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl4, sizeof( ttl4 )) < 0 ) {
|
||||
throw std::runtime_error(std::string("TTL Sockopt Error: ") + strerror(errno));
|
||||
}
|
||||
|
||||
@@ -131,13 +246,13 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
|
||||
} */
|
||||
|
||||
unsigned int ttl6 = 20;
|
||||
if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl6, sizeof( ttl6 )) < 0 ) {
|
||||
if( setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl6, sizeof( ttl6 )) < 0 ) {
|
||||
throw std::runtime_error(std::string("Hop Count Set Error: ") + strerror(errno));
|
||||
}
|
||||
|
||||
config_ipv6.ipv6mr_interface = 0;
|
||||
inet_pton(AF_INET6, MULTICAST_ADDRESS_IPV6, &config_ipv6.ipv6mr_multiaddr);
|
||||
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &config_ipv6, sizeof(config_ipv6)) < 0){
|
||||
if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*)&config_ipv6, sizeof(config_ipv6)) < 0){
|
||||
throw std::runtime_error(std::string("Member Addition IPv6 Error: ") + strerror(errno));
|
||||
}
|
||||
break;
|
||||
@@ -146,78 +261,39 @@ PeerDiscovery::socketJoinMulticast(int sockfd, sa_family_t family)
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::sendTo(uint8_t *buf, size_t buf_size)
|
||||
PeerDiscovery::DomainPeerDiscovery::startDiscovery(const std::string &type, ServiceDiscoveredCallback callback)
|
||||
{
|
||||
ssize_t nbytes = sendto(
|
||||
sockfd_,
|
||||
buf,
|
||||
buf_size,
|
||||
0,
|
||||
sockAddrSend_.get(),
|
||||
sockAddrSend_.getLength()
|
||||
);
|
||||
if (nbytes < 0) {
|
||||
throw std::runtime_error(std::string("Error sending packet: ") + strerror(errno));
|
||||
std::unique_lock<std::mutex> lck(dmtx_);
|
||||
callbackmap_[type] = callback;
|
||||
if (not drunning_) {
|
||||
if (running_listen_.joinable())
|
||||
running_listen_.join();
|
||||
drunning_ = true;
|
||||
running_listen_ = std::thread(&DomainPeerDiscovery::listenerpack_thread, this);
|
||||
}
|
||||
}
|
||||
|
||||
SockAddr
|
||||
PeerDiscovery::recvFrom(uint8_t *buf, size_t& buf_size)
|
||||
std::pair<SockAddr, msgpack::object_handle>
|
||||
PeerDiscovery::DomainPeerDiscovery::recvFrom()
|
||||
{
|
||||
sockaddr_storage storeage_recv;
|
||||
socklen_t sa_len = sizeof(storeage_recv);
|
||||
sockaddr_storage sa;
|
||||
socklen_t sa_len = sizeof(sa);
|
||||
|
||||
std::array<uint8_t, 64 * 1024> buf;
|
||||
ssize_t nbytes = recvfrom(
|
||||
sockfd_,
|
||||
buf,
|
||||
buf_size,
|
||||
(char*)buf.data(), buf.size(),
|
||||
0,
|
||||
(sockaddr*)&storeage_recv,
|
||||
&sa_len
|
||||
(sockaddr*)&sa, &sa_len
|
||||
);
|
||||
if (nbytes < 0) {
|
||||
if (nbytes < 0)
|
||||
throw std::runtime_error(std::string("Error receiving packet: ") + strerror(errno));
|
||||
}
|
||||
|
||||
buf_size = nbytes;
|
||||
SockAddr ret {storeage_recv, sa_len};
|
||||
return ret;
|
||||
return { SockAddr { sa, sa_len }, msgpack::unpack(reinterpret_cast<char*>(buf.data()), nbytes) };
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::sender_setup(const dht::InfoHash& nodeId, in_port_t port_to_send)
|
||||
{
|
||||
nodeId_ = nodeId;
|
||||
// Setup sender address
|
||||
sockAddrSend_.setFamily(domain_);
|
||||
sockAddrSend_.setAddress(domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6);
|
||||
sockAddrSend_.setPort(port_);
|
||||
|
||||
// Setup sent data
|
||||
std::copy_n(nodeId.cbegin(), nodeId.size(), data_send_.begin());
|
||||
auto portAddr = reinterpret_cast<in_port_t*>(data_send_.data() + dht::InfoHash::size());
|
||||
*portAddr = htons(port_to_send);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::sender_thread()
|
||||
{
|
||||
while(true) {
|
||||
try {
|
||||
sendTo(data_send_.data(), data_send_.size());
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
if (cv_.wait_for(lck,std::chrono::seconds(3),[&]{ return !running_; }))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
|
||||
PeerDiscovery::DomainPeerDiscovery::listenerpack_thread()
|
||||
{
|
||||
int stopfds_pipe[2];
|
||||
#ifndef _WIN32
|
||||
@@ -229,18 +305,24 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
|
||||
int stop_readfd = stopfds_pipe[0];
|
||||
stop_writefd_ = stopfds_pipe[1];
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
if (not drunning_)
|
||||
break;
|
||||
}
|
||||
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(stop_readfd, &readfds);
|
||||
FD_SET(sockfd_, &readfds);
|
||||
|
||||
int data_coming = select(sockfd_ > stop_readfd ? sockfd_ + 1 : stop_readfd + 1, &readfds, nullptr, nullptr, nullptr);
|
||||
int data_coming = select(std::max(sockfd_, stop_readfd) + 1, &readfds, nullptr, nullptr, nullptr);
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
if (not running_)
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
if (not drunning_)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -249,31 +331,35 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
|
||||
perror("Select Error");
|
||||
std::this_thread::sleep_for( std::chrono::seconds(1) );
|
||||
}
|
||||
}
|
||||
|
||||
if (data_coming > 0) {
|
||||
} else if (data_coming > 0) {
|
||||
if (FD_ISSET(stop_readfd, &readfds)) {
|
||||
std::array<uint8_t, 64 * 1024> buf;
|
||||
recv(stop_readfd, buf.data(), buf.size(), 0);
|
||||
recv(stop_readfd, (char*)buf.data(), buf.size(), 0);
|
||||
}
|
||||
|
||||
std::array<uint8_t,dht::InfoHash::size() + sizeof(in_port_t)> data_receive;
|
||||
size_t data_receive_size = data_receive.size();
|
||||
auto from = recvFrom(data_receive.data(), data_receive_size);
|
||||
try {
|
||||
auto rcv = recvFrom();
|
||||
msgpack::object obj = rcv.second.get();
|
||||
|
||||
// Data_receive_size as a value-result member will hlep to filter packs
|
||||
if(data_receive_size != data_receive.size()){
|
||||
// std::cerr << "Received invalid peer discovery packet" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
dht::InfoHash nodeId;
|
||||
std::copy_n(data_receive.begin(), dht::InfoHash::size(), nodeId.begin());
|
||||
auto portAddr = reinterpret_cast<in_port_t*>(data_receive.data() + dht::InfoHash::size());
|
||||
auto port = ntohs(*portAddr);
|
||||
if (nodeId != nodeId_){
|
||||
from.setPort(port);
|
||||
callback(nodeId, from);
|
||||
if (obj.type != msgpack::type::MAP)
|
||||
continue;
|
||||
for (unsigned i = 0; i < obj.via.map.size; i++) {
|
||||
auto& o = obj.via.map.ptr[i];
|
||||
if (o.key.type != msgpack::type::STR)
|
||||
continue;
|
||||
auto key = o.key.as<std::string>();
|
||||
ServiceDiscoveredCallback cb;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
auto callback = callbackmap_.find(key);
|
||||
if (callback != callbackmap_.end())
|
||||
cb = callback->second;
|
||||
}
|
||||
if (cb)
|
||||
cb(std::move(o.val), std::move(rcv.first));
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error receiving packet: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,32 +372,206 @@ PeerDiscovery::listener_thread(PeerDiscoveredCallback callback)
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startDiscovery(PeerDiscoveredCallback callback)
|
||||
PeerDiscovery::DomainPeerDiscovery::sender_setup()
|
||||
{
|
||||
listener_setup();
|
||||
running_listen = std::thread(&PeerDiscovery::listener_thread, this, callback);
|
||||
// Setup sender address
|
||||
sockAddrSend_.setFamily(domain_);
|
||||
sockAddrSend_.setAddress(domain_ == AF_INET ? MULTICAST_ADDRESS_IPV4 : MULTICAST_ADDRESS_IPV6);
|
||||
sockAddrSend_.setPort(port_);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startPublish(const dht::InfoHash& nodeId, in_port_t port_to_send)
|
||||
PeerDiscovery::DomainPeerDiscovery::startPublish(const std::string &type, const msgpack::sbuffer &pack_buf)
|
||||
{
|
||||
sender_setup(nodeId, port_to_send);
|
||||
running_send = std::thread(&PeerDiscovery::sender_thread, this);
|
||||
//Set up New Sending pack
|
||||
msgpack::sbuffer pack_buf_c;
|
||||
pack_buf_c.write(pack_buf.data(),pack_buf.size());
|
||||
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
messages_[type] = std::move(pack_buf_c);
|
||||
messages_reload();
|
||||
if (not lrunning_) {
|
||||
if (running_send_.joinable())
|
||||
running_send_.join();
|
||||
lrunning_ = true;
|
||||
running_send_ = std::thread([this](){
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
while (lrunning_) {
|
||||
ssize_t nbytes = sendto(
|
||||
sockfd_,
|
||||
sbuf_.data(),
|
||||
sbuf_.size(),
|
||||
0,
|
||||
sockAddrSend_.get(),
|
||||
sockAddrSend_.getLength()
|
||||
);
|
||||
if (nbytes < 0) {
|
||||
std::cerr << "Error sending packet: " << strerror(errno) << std::endl;
|
||||
}
|
||||
if (cv_.wait_for(lck,std::chrono::seconds(3),[&]{ return !lrunning_; }))
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopDiscovery(const std::string &type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
if (callbackmap_.erase(type) > 0) {
|
||||
if (callbackmap_.empty())
|
||||
stopDiscovery();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopPublish(const std::string &type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
if (messages_.erase(type) > 0) {
|
||||
if (messages_.empty())
|
||||
stopPublish();
|
||||
else
|
||||
messages_reload();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::stopDiscovery()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#define write(s, b, f) send((s), (b), (f), 0)
|
||||
#endif
|
||||
if (drunning_) {
|
||||
drunning_ = false;
|
||||
if (stop_writefd_ != -1) {
|
||||
if (write(stop_writefd_, "\0", 1) == -1) {
|
||||
std::cerr << "Can't send stop message: " << strerror(errno) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#undef write
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::stopPublish()
|
||||
{
|
||||
if (lrunning_) {
|
||||
lrunning_ = false;
|
||||
cv_.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::stop()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(dmtx_);
|
||||
stopDiscovery();
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
stopPublish();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::messages_reload()
|
||||
{
|
||||
sbuf_.clear();
|
||||
msgpack::packer<msgpack::sbuffer> pk(&sbuf_);
|
||||
pk.pack_map(messages_.size());
|
||||
for (const auto& m : messages_) {
|
||||
pk.pack(m.first);
|
||||
sbuf_.write(m.second.data(), m.second.size());
|
||||
}
|
||||
}
|
||||
|
||||
PeerDiscovery::PeerDiscovery(in_port_t port)
|
||||
{
|
||||
try {
|
||||
peerDiscovery4_.reset(new DomainPeerDiscovery(AF_INET, port));
|
||||
} catch(const std::exception& e){
|
||||
std::cerr << "Can't start peer discovery (IPv4): " << e.what() << std::endl;
|
||||
}
|
||||
try {
|
||||
peerDiscovery6_.reset(new DomainPeerDiscovery(AF_INET6, port));
|
||||
} catch(const std::exception& e) {
|
||||
std::cerr << "Can't start peer discovery (IPv6): " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
PeerDiscovery::~PeerDiscovery(){}
|
||||
|
||||
void
|
||||
PeerDiscovery::startDiscovery(const std::string &type, ServiceDiscoveredCallback callback)
|
||||
{
|
||||
if(peerDiscovery4_) peerDiscovery4_->startDiscovery(type, callback);
|
||||
if(peerDiscovery6_) peerDiscovery6_->startDiscovery(type, callback);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startPublish(const std::string &type, const msgpack::sbuffer &pack_buf)
|
||||
{
|
||||
if(peerDiscovery4_) peerDiscovery4_->startPublish(type, pack_buf);
|
||||
if(peerDiscovery6_) peerDiscovery6_->startPublish(type, pack_buf);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startPublish(sa_family_t domain, const std::string &type, const msgpack::sbuffer &pack_buf)
|
||||
{
|
||||
if (domain == AF_INET) {
|
||||
if (peerDiscovery4_) peerDiscovery4_->startPublish(type, pack_buf);
|
||||
} else if (domain == AF_INET6) {
|
||||
if (peerDiscovery6_) peerDiscovery6_->startPublish(type, pack_buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::stop()
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(mtx_);
|
||||
running_ = false;
|
||||
}
|
||||
cv_.notify_all();
|
||||
if (stop_writefd_ != -1) {
|
||||
if (write(stop_writefd_, "\0", 1) == -1) {
|
||||
perror("write");
|
||||
}
|
||||
if(peerDiscovery4_) peerDiscovery4_->stop();
|
||||
if(peerDiscovery6_) peerDiscovery6_->stop();
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopDiscovery(const std::string &type)
|
||||
{
|
||||
bool stopped4 = peerDiscovery4_ and peerDiscovery4_->stopDiscovery(type);
|
||||
bool stopped6 = peerDiscovery6_ and peerDiscovery6_->stopDiscovery(type);
|
||||
return stopped4 or stopped6;
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopPublish(const std::string &type)
|
||||
{
|
||||
bool stopped4 = peerDiscovery4_ and peerDiscovery4_->stopPublish(type);
|
||||
bool stopped6 = peerDiscovery6_ and peerDiscovery6_->stopPublish(type);
|
||||
return stopped4 or stopped6;
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopPublish(sa_family_t domain, const std::string &type)
|
||||
{
|
||||
if (domain == AF_INET) {
|
||||
return peerDiscovery4_ and peerDiscovery4_->stopPublish(type);
|
||||
} else if (domain == AF_INET6) {
|
||||
return peerDiscovery6_ and peerDiscovery6_->stopPublish(type);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::join() {
|
||||
if(peerDiscovery4_) peerDiscovery4_->join();
|
||||
if(peerDiscovery6_) peerDiscovery6_->join();
|
||||
}
|
||||
|
||||
}
|
||||
+19
-19
@@ -54,9 +54,9 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf)
|
||||
CERTIFICATE_TYPE,
|
||||
*certificate_,
|
||||
1
|
||||
}, [this](bool ok) {
|
||||
}, [this, certId](bool ok) {
|
||||
if (ok)
|
||||
DHT_LOG.DBG("SecureDht: public key announced successfully");
|
||||
DHT_LOG.d(certId, "SecureDht: public key announced successfully");
|
||||
}, {}, true);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ SecureDht::secureType(ValueType&& type)
|
||||
v->signatureValid = v->owner and v->owner->checkSignature(v->getToSign(), v->signature);
|
||||
}
|
||||
if (!v->signatureValid) {
|
||||
DHT_LOG.WARN("Signature verification failed");
|
||||
DHT_LOG.w("Signature verification failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ SecureDht::secureType(ValueType&& type)
|
||||
if (!o->isSigned())
|
||||
return type.editPolicy(id, o, n, nid, a);
|
||||
if (o->owner != n->owner) {
|
||||
DHT_LOG.WARN("Edition forbidden: owner changed.");
|
||||
DHT_LOG.w("Edition forbidden: owner changed.");
|
||||
return false;
|
||||
}
|
||||
if (!n->signatureChecked) {
|
||||
@@ -91,14 +91,14 @@ SecureDht::secureType(ValueType&& type)
|
||||
n->signatureValid = o->owner and o->owner->checkSignature(n->getToSign(), n->signature);
|
||||
}
|
||||
if (!n->signatureValid) {
|
||||
DHT_LOG.WARN("Edition forbidden: signature verification failed.");
|
||||
DHT_LOG.w("Edition forbidden: signature verification failed.");
|
||||
return false;
|
||||
}
|
||||
if (o->seq == n->seq) {
|
||||
// If the data is exactly the same,
|
||||
// it can be reannounced, possibly by someone else.
|
||||
if (o->getToSign() != n->getToSign()) {
|
||||
DHT_LOG.WARN("Edition forbidden: sequence number must be increasing.");
|
||||
DHT_LOG.w("Edition forbidden: sequence number must be increasing.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
}
|
||||
InfoHash h = crt->getPublicKey().getId();
|
||||
if (node == h) {
|
||||
DHT_LOG.DBG("Registering certificate for %s", h.toString().c_str());
|
||||
DHT_LOG.d("Registering certificate for %s", h.toString().c_str());
|
||||
auto it = nodesCertificates_.find(h);
|
||||
if (it == nodesCertificates_.end())
|
||||
std::tie(it, std::ignore) = nodesCertificates_.emplace(h, std::move(crt));
|
||||
@@ -152,7 +152,7 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
it->second = std::move(crt);
|
||||
return it->second;
|
||||
} else {
|
||||
DHT_LOG.WARN("Certificate %s for node %s does not match node id !", h.toString().c_str(), node.toString().c_str());
|
||||
DHT_LOG.w("Certificate %s for node %s does not match node id !", h.toString().c_str(), node.toString().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ SecureDht::findCertificate(const InfoHash& node, const std::function<void(const
|
||||
{
|
||||
Sp<crypto::Certificate> b = getCertificate(node);
|
||||
if (b && *b) {
|
||||
DHT_LOG.DBG("Using certificate from cache for %s", node.toString().c_str());
|
||||
DHT_LOG.d("Using certificate from cache for %s", node.toString().c_str());
|
||||
if (cb)
|
||||
cb(b);
|
||||
return;
|
||||
@@ -177,7 +177,7 @@ SecureDht::findCertificate(const InfoHash& node, const std::function<void(const
|
||||
if (localQueryMethod_) {
|
||||
auto res = localQueryMethod_(node);
|
||||
if (not res.empty()) {
|
||||
DHT_LOG.DBG("Registering certificate from local store for %s", node.toString().c_str());
|
||||
DHT_LOG.d("Registering certificate from local store for %s", node.toString().c_str());
|
||||
nodesCertificates_.emplace(node, res.front());
|
||||
if (cb)
|
||||
cb(res.front());
|
||||
@@ -192,7 +192,7 @@ SecureDht::findCertificate(const InfoHash& node, const std::function<void(const
|
||||
for (const auto& v : vals) {
|
||||
if (auto cert = registerCertificate(node, v->data)) {
|
||||
*found = true;
|
||||
DHT_LOG.DBG("Found certificate for %s", node.toString().c_str());
|
||||
DHT_LOG.d("Found certificate for %s", node.toString().c_str());
|
||||
if (cb)
|
||||
cb(cert);
|
||||
return false;
|
||||
@@ -210,7 +210,7 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp
|
||||
{
|
||||
auto pk = getPublicKey(node);
|
||||
if (pk && *pk) {
|
||||
DHT_LOG.DBG("Found public key from cache for %s", node.toString().c_str());
|
||||
DHT_LOG.d("Found public key from cache for %s", node.toString().c_str());
|
||||
if (cb)
|
||||
cb(pk);
|
||||
return;
|
||||
@@ -254,7 +254,7 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
}
|
||||
// Ignore values belonging to other people
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.WARN("Could not decrypt value %s : %s", v->toString().c_str(), e.what());
|
||||
DHT_LOG.w("Could not decrypt value %s : %s", v->toString().c_str(), e.what());
|
||||
}
|
||||
}
|
||||
// Check signed values
|
||||
@@ -269,7 +269,7 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
return v;
|
||||
}
|
||||
else
|
||||
DHT_LOG.WARN("Signature verification failed for %s", v->toString().c_str());
|
||||
DHT_LOG.w("Signature verification failed for %s", v->toString().c_str());
|
||||
}
|
||||
// Forward normal values
|
||||
else {
|
||||
@@ -352,12 +352,12 @@ SecureDht::putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback,
|
||||
// Check if data already exists on the dht
|
||||
get(hash,
|
||||
[val,this] (const std::vector<Sp<Value>>& vals) {
|
||||
DHT_LOG.DBG("Found online previous value being announced.");
|
||||
DHT_LOG.d("Found online previous value being announced.");
|
||||
for (const auto& v : vals) {
|
||||
if (!v->isSigned())
|
||||
DHT_LOG.ERR("Existing non-signed value seems to exists at this location.");
|
||||
DHT_LOG.e("Existing non-signed value seems to exists at this location.");
|
||||
else if (not v->owner or v->owner->getId() != getId())
|
||||
DHT_LOG.ERR("Existing signed value belonging to someone else seems to exists at this location.");
|
||||
DHT_LOG.e("Existing signed value belonging to someone else seems to exists at this location.");
|
||||
else if (val->seq <= v->seq)
|
||||
val->seq = v->seq + 1;
|
||||
}
|
||||
@@ -381,11 +381,11 @@ SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val,
|
||||
callback(false, {});
|
||||
return;
|
||||
}
|
||||
DHT_LOG.WARN("Encrypting data for PK: %s", pk->getId().toString().c_str());
|
||||
DHT_LOG.w("Encrypting data for PK: %s", pk->getId().toString().c_str());
|
||||
try {
|
||||
dht_->put(hash, encrypt(*val, *pk), callback, time_point::max(), permanent);
|
||||
} catch (const std::exception& e) {
|
||||
DHT_LOG.ERR("Error putting encrypted data: %s", e.what());
|
||||
DHT_LOG.e("Error putting encrypted data: %s", e.what());
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
}
|
||||
|
||||
+42
-1
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include <iostream>
|
||||
#include <ciso646> // fix windows compiler bug
|
||||
|
||||
namespace dht {
|
||||
@@ -97,6 +97,7 @@ ThreadPool::run(std::function<void()>&& cb)
|
||||
task();
|
||||
} catch (const std::exception& e) {
|
||||
// LOG_ERR("Exception running task: %s", e.what());
|
||||
std::cerr << "Exception running task: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -131,4 +132,44 @@ ThreadPool::join()
|
||||
threads_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Executor::run(std::function<void()>&& task)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lock_);
|
||||
if (current_ < maxConcurrent_) {
|
||||
run_(std::move(task));
|
||||
} else {
|
||||
tasks_.emplace(std::move(task));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Executor::run_(std::function<void()>&& task)
|
||||
{
|
||||
current_++;
|
||||
std::weak_ptr<Executor> w = shared_from_this();
|
||||
threadPool_.get().run([w,task] {
|
||||
try {
|
||||
task();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Exception running task: " << e.what() << std::endl;
|
||||
}
|
||||
if (auto sthis = w.lock()) {
|
||||
auto& this_ = *sthis;
|
||||
std::lock_guard<std::mutex> l(this_.lock_);
|
||||
this_.current_--;
|
||||
this_.schedule();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Executor::schedule()
|
||||
{
|
||||
if (not tasks_.empty() and current_ < maxConcurrent_) {
|
||||
run_(std::move(tasks_.front()));
|
||||
tasks_.pop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+27
-5
@@ -16,6 +16,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "utils.h"
|
||||
#include "sockaddr.h"
|
||||
#include "default_types.h"
|
||||
@@ -93,9 +97,11 @@ SockAddr::setAddress(const char* address)
|
||||
case AF_INET6:
|
||||
addr = &getIPv6().sin6_addr;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown address family");
|
||||
}
|
||||
if (not addr or inet_pton(family, address, addr) <= 0)
|
||||
throw std::runtime_error("Can't parse IP address");
|
||||
if (inet_pton(family, address, addr) <= 0)
|
||||
throw std::runtime_error(std::string("Can't parse IP address: ") + strerror(errno));
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -104,7 +110,7 @@ print_addr(const sockaddr* sa, socklen_t slen)
|
||||
char hbuf[NI_MAXHOST];
|
||||
char sbuf[NI_MAXSERV];
|
||||
std::stringstream out;
|
||||
if (!getnameinfo(sa, slen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
|
||||
if (sa and slen and !getnameinfo(sa, slen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
|
||||
if (sa->sa_family == AF_INET6)
|
||||
out << "[" << hbuf << "]";
|
||||
else
|
||||
@@ -195,10 +201,10 @@ SockAddr::isMappedIPv4() const
|
||||
}
|
||||
|
||||
SockAddr
|
||||
SockAddr::getMappedIPv4() const
|
||||
SockAddr::getMappedIPv4()
|
||||
{
|
||||
if (not isMappedIPv4())
|
||||
return *this;
|
||||
return std::move(*this);
|
||||
SockAddr ret;
|
||||
ret.setFamily(AF_INET);
|
||||
ret.setPort(getPort());
|
||||
@@ -209,6 +215,22 @@ SockAddr::getMappedIPv4() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
SockAddr
|
||||
SockAddr::getMappedIPv6()
|
||||
{
|
||||
auto family = getFamily();
|
||||
if (family != AF_INET)
|
||||
return std::move(*this);
|
||||
SockAddr ret;
|
||||
ret.setFamily(AF_INET6);
|
||||
ret.setPort(getPort());
|
||||
auto addr4 = reinterpret_cast<const uint8_t*>(&getIPv4().sin_addr);
|
||||
auto addr6 = reinterpret_cast<uint8_t*>(&ret.getIPv6().sin6_addr);
|
||||
std::copy(MAPPED_IPV4_PREFIX.begin(), MAPPED_IPV4_PREFIX.end(), addr6);
|
||||
std::copy_n(addr4, sizeof(in_addr), addr6 + MAPPED_IPV4_PREFIX.size());
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator==(const SockAddr& a, const SockAddr& b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
+47
-32
@@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Sébastien Blin <sebastien.blin@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
|
||||
@@ -32,26 +33,32 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DhtProxyTester);
|
||||
|
||||
void
|
||||
DhtProxyTester::setUp() {
|
||||
nodePeer.run(42222, {}, true);
|
||||
logger = dht::log::getStdLogger();
|
||||
|
||||
nodePeer.run(0, /*identity*/{}, /*threaded*/true);
|
||||
|
||||
nodeProxy = std::make_shared<dht::DhtRunner>();
|
||||
nodeClient = std::make_shared<dht::DhtRunner>();
|
||||
|
||||
nodeProxy->run(42232, {}, true);
|
||||
nodeProxy->run(0, /*identity*/{}, /*threaded*/true);
|
||||
nodeProxy->bootstrap(nodePeer.getBound());
|
||||
server = std::unique_ptr<dht::DhtProxyServer>(new dht::DhtProxyServer(nodeProxy, 8080));
|
||||
serverProxy = std::unique_ptr<dht::DhtProxyServer>(new dht::DhtProxyServer(
|
||||
nodeProxy, 8080, /*pushServer*/"127.0.0.1:8090", logger));
|
||||
|
||||
nodeClient->run(42242, {}, true);
|
||||
nodeClient = std::make_shared<dht::DhtRunner>();
|
||||
nodeClient->run(0, /*identity*/{}, /*threaded*/true);
|
||||
nodeClient->bootstrap(nodePeer.getBound());
|
||||
nodeClient->setProxyServer("127.0.0.1:8080");
|
||||
nodeClient->enableProxy(true);
|
||||
nodeClient->enableProxy(true); // creates DhtProxyClient
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyTester::tearDown() {
|
||||
logger->d("[tester:proxy] stopping peer node");
|
||||
nodePeer.join();
|
||||
nodeClient->join();
|
||||
server->stop();
|
||||
server = nullptr;
|
||||
logger->d("[tester:proxy] stopping proxy server");
|
||||
serverProxy->stop();
|
||||
serverProxy = nullptr;
|
||||
logger->d("[tester:proxy] stopping proxy node");
|
||||
nodeProxy->join();
|
||||
}
|
||||
|
||||
@@ -65,12 +72,15 @@ DhtProxyTester::testGetPut() {
|
||||
dht::Value val {"Hey! It's been a long time. How have you been?"};
|
||||
auto val_data = val.data;
|
||||
|
||||
nodePeer.put(key, std::move(val), [&](bool) {
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
nodePeer.put(key, std::move(val), [&](bool) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
}
|
||||
|
||||
auto vals = nodeClient->get(key).get();
|
||||
CPPUNIT_ASSERT(not vals.empty());
|
||||
@@ -79,33 +89,37 @@ DhtProxyTester::testGetPut() {
|
||||
|
||||
void
|
||||
DhtProxyTester::testListen() {
|
||||
bool done = false;
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
auto key = dht::InfoHash::get("GLaDOs");
|
||||
bool done = false;
|
||||
|
||||
// If a peer send a value, the listen operation from the client
|
||||
// should retrieve this value
|
||||
dht::Value firstVal {"Hey! It's been a long time. How have you been?"};
|
||||
auto firstVal_data = firstVal.data;
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool) {
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool ok) {
|
||||
CPPUNIT_ASSERT(ok);
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
done = false;
|
||||
|
||||
auto values = std::vector<dht::Blob>();
|
||||
nodeClient->listen(key, [&](const std::vector<std::shared_ptr<dht::Value>>& v, bool) {
|
||||
for (const auto& value : v)
|
||||
values.emplace_back(value->data);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
std::vector<dht::Blob> values;
|
||||
auto token = nodeClient->listen(key, [&](const std::vector<std::shared_ptr<dht::Value>>& v, bool expired) {
|
||||
if (not expired) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
for (const auto& value : v)
|
||||
values.emplace_back(value->data);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
done = false;
|
||||
// Here values should contains 1 values
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<int>(values.size()), 1);
|
||||
@@ -116,7 +130,8 @@ DhtProxyTester::testListen() {
|
||||
dht::Value secondVal {"You're a monster"};
|
||||
auto secondVal_data = secondVal.data;
|
||||
nodePeer.put(key, std::move(secondVal));
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
nodeClient->cancelListen(key, std::move(token));
|
||||
// Here values should contains 2 values
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<int>(values.size()), 2);
|
||||
CPPUNIT_ASSERT(values.back() == secondVal_data);
|
||||
@@ -137,10 +152,11 @@ DhtProxyTester::testResubscribeGetValues() {
|
||||
dht::Value firstVal {"Hey! It's been a long time. How have you been?"};
|
||||
auto firstVal_data = firstVal.data;
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
done = false;
|
||||
|
||||
// Send a first subscribe, the value is sent via a push notification
|
||||
@@ -152,7 +168,7 @@ DhtProxyTester::testResubscribeGetValues() {
|
||||
|
||||
// Reboot node (to avoid cache)
|
||||
nodeClient->join();
|
||||
nodeClient->run(42242, {}, true);
|
||||
nodeClient->run(0, {}, true);
|
||||
nodeClient->bootstrap(nodePeer.getBound());
|
||||
nodeClient->setProxyServer("127.0.0.1:8080");
|
||||
nodeClient->enableProxy(true);
|
||||
@@ -166,16 +182,15 @@ DhtProxyTester::testResubscribeGetValues() {
|
||||
for (const auto& value : v)
|
||||
values.emplace_back(value->data);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
cv.notify_all();
|
||||
return true;
|
||||
});
|
||||
|
||||
cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; });
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(10), [&]{ return done; }));
|
||||
auto token = ftoken.get();
|
||||
CPPUNIT_ASSERT(token);
|
||||
nodeClient->cancelListen(key, token);
|
||||
done = false;
|
||||
// Here values should still contains 1 values
|
||||
CPPUNIT_ASSERT_EQUAL((size_t)1u, values.size());
|
||||
CPPUNIT_ASSERT(firstVal_data == values.front());
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <opendht/dhtrunner.h>
|
||||
#include <opendht/dht_proxy_server.h>
|
||||
#include <opendht/log.h>
|
||||
|
||||
namespace test {
|
||||
|
||||
@@ -61,11 +62,14 @@ class DhtProxyTester : public CppUnit::TestFixture {
|
||||
void testResubscribeGetValues();
|
||||
|
||||
private:
|
||||
dht::DhtRunner nodePeer {};
|
||||
dht::DhtRunner nodePeer;
|
||||
|
||||
std::shared_ptr<dht::DhtRunner> nodeClient;
|
||||
std::shared_ptr<dht::DhtRunner> nodeProxy;
|
||||
std::unique_ptr<dht::DhtProxyServer> server;
|
||||
std::unique_ptr<dht::DhtProxyServer> serverProxy;
|
||||
|
||||
dht::DhtRunner::Config config {};
|
||||
std::shared_ptr<dht::Logger> logger {};
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -18,71 +18,92 @@
|
||||
*/
|
||||
|
||||
#include "peerdiscoverytester.h"
|
||||
#include "opendht/value.h"
|
||||
|
||||
namespace test {
|
||||
|
||||
struct NodeInsertion {
|
||||
dht::InfoHash nodeid;
|
||||
in_port_t node_port;
|
||||
dht::NetId nid;
|
||||
MSGPACK_DEFINE(nodeid, node_port, nid)
|
||||
};
|
||||
|
||||
struct TestPack {
|
||||
int num;
|
||||
char cha;
|
||||
std::string str;
|
||||
MSGPACK_DEFINE(num, cha, str)
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(PeerDiscoveryTester);
|
||||
|
||||
void PeerDiscoveryTester::setUp(){}
|
||||
|
||||
void PeerDiscoveryTester::testTransmission_ipv4(){
|
||||
|
||||
void PeerDiscoveryTester::testTransmission()
|
||||
{
|
||||
// Node for getnode id
|
||||
dht::InfoHash data_n = dht::InfoHash::get("applepin");
|
||||
int port = 2222;
|
||||
in_port_t port_n = 50000;
|
||||
try{
|
||||
dht::PeerDiscovery test_n(AF_INET, port);
|
||||
dht::PeerDiscovery test_s(AF_INET, port);
|
||||
try{
|
||||
test_s.startDiscovery([&](const dht::InfoHash& node, const dht::SockAddr& addr){
|
||||
CPPUNIT_ASSERT_EQUAL(data_n, node);
|
||||
CPPUNIT_ASSERT_EQUAL(port_n, addr.getPort());
|
||||
});
|
||||
const std::string type {"dht"};
|
||||
const std::string test_type {"pdd"};
|
||||
constexpr int MULTICAST_PORT = 2222;
|
||||
|
||||
test_n.startPublish(data_n,port_n);
|
||||
NodeInsertion adc;
|
||||
adc.nid = 10;
|
||||
adc.node_port = 50000;
|
||||
adc.nodeid = dht::InfoHash::get("applepin");
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
test_n.stop();
|
||||
test_s.stop();
|
||||
test_n.join();
|
||||
test_s.join();
|
||||
} catch(std::exception &exception){
|
||||
perror(exception.what());
|
||||
CPPUNIT_ASSERT(false);
|
||||
}
|
||||
} catch(std::exception &exception){
|
||||
perror(exception.what());
|
||||
}
|
||||
}
|
||||
TestPack pdd;
|
||||
pdd.num = 100;
|
||||
pdd.cha = 'a';
|
||||
pdd.str = "apple";
|
||||
|
||||
void PeerDiscoveryTester::testTransmission_ipv6(){
|
||||
std::mutex lock;
|
||||
std::condition_variable cv;
|
||||
unsigned count_node {0};
|
||||
unsigned count_test {0};
|
||||
|
||||
// Node for getnode id
|
||||
dht::InfoHash data_n = dht::InfoHash::get("applepin");
|
||||
int port = 3333;
|
||||
in_port_t port_n = 50001;
|
||||
try{
|
||||
dht::PeerDiscovery test_n(AF_INET6, port);
|
||||
dht::PeerDiscovery test_s(AF_INET6, port);
|
||||
{
|
||||
std::unique_lock<std::mutex> l(lock);
|
||||
dht::PeerDiscovery test_n(MULTICAST_PORT);
|
||||
dht::PeerDiscovery test_s(MULTICAST_PORT);
|
||||
|
||||
try{
|
||||
test_s.startDiscovery([&](const dht::InfoHash& node, const dht::SockAddr& addr){
|
||||
CPPUNIT_ASSERT_EQUAL(data_n, node);
|
||||
CPPUNIT_ASSERT_EQUAL(port_n, addr.getPort());
|
||||
});
|
||||
test_s.startDiscovery<NodeInsertion>(type,[&](NodeInsertion&& v, dht::SockAddr&& add){
|
||||
CPPUNIT_ASSERT_EQUAL(adc.node_port, v.node_port);
|
||||
CPPUNIT_ASSERT_EQUAL(adc.nodeid, v.nodeid);
|
||||
CPPUNIT_ASSERT_EQUAL(adc.nid, v.nid);
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lock);
|
||||
count_node++;
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
test_n.startPublish(data_n,port_n);
|
||||
test_s.startDiscovery(test_type,[&](msgpack::object&& obj, dht::SockAddr&& add){
|
||||
auto v = obj.as<TestPack>();
|
||||
CPPUNIT_ASSERT_EQUAL(pdd.num, v.num);
|
||||
CPPUNIT_ASSERT_EQUAL(pdd.cha, v.cha);
|
||||
CPPUNIT_ASSERT_EQUAL(pdd.str, v.str);
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lock);
|
||||
count_test++;
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||
test_n.stop();
|
||||
test_s.stop();
|
||||
test_n.join();
|
||||
test_s.join();
|
||||
} catch(std::exception &exception){
|
||||
CPPUNIT_ASSERT(false);
|
||||
}
|
||||
} catch(std::exception &exception) {
|
||||
test_n.startPublish(type, adc);
|
||||
CPPUNIT_ASSERT(cv.wait_for(l, std::chrono::seconds(5), [&]{
|
||||
return count_node > 0;
|
||||
}));
|
||||
|
||||
test_n.startPublish(test_type, pdd);
|
||||
CPPUNIT_ASSERT(cv.wait_for(l, std::chrono::seconds(5), [&]{
|
||||
return count_node > 1 and count_test > 0;
|
||||
}));
|
||||
l.unlock();
|
||||
test_n.stopPublish(type);
|
||||
test_n.stopPublish(test_type);
|
||||
test_s.stopDiscovery(type);
|
||||
test_s.stopDiscovery(test_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,10 @@
|
||||
|
||||
namespace test {
|
||||
|
||||
class PeerDiscoveryTester : public CppUnit::TestFixture {
|
||||
class OPENDHT_PUBLIC PeerDiscoveryTester : public CppUnit::TestFixture {
|
||||
|
||||
CPPUNIT_TEST_SUITE(PeerDiscoveryTester);
|
||||
CPPUNIT_TEST(testTransmission_ipv4);
|
||||
CPPUNIT_TEST(testTransmission_ipv6);
|
||||
CPPUNIT_TEST(testTransmission);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -45,12 +44,7 @@ class PeerDiscoveryTester : public CppUnit::TestFixture {
|
||||
/**
|
||||
* Test Multicast Transmission Ipv4
|
||||
*/
|
||||
void testTransmission_ipv4();
|
||||
/**
|
||||
* Test Multicast Transmission Ipv6
|
||||
*/
|
||||
void testTransmission_ipv6();
|
||||
|
||||
void testTransmission();
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@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 "threadpooltester.h"
|
||||
|
||||
#include "opendht/thread_pool.h"
|
||||
#include <atomic>
|
||||
|
||||
namespace test {
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(ThreadPoolTester);
|
||||
using clock = std::chrono::steady_clock;
|
||||
|
||||
void
|
||||
ThreadPoolTester::setUp() {
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::testThreadPool() {
|
||||
dht::ThreadPool pool(16);
|
||||
|
||||
constexpr unsigned N = 64 * 1024;
|
||||
std::atomic_uint count {0};
|
||||
for (unsigned i=0; i<N; i++)
|
||||
pool.run([&] {
|
||||
count++;
|
||||
});
|
||||
|
||||
auto start = clock::now();
|
||||
while (count.load() != N && clock::now() - start < std::chrono::seconds(10))
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
pool.join();
|
||||
CPPUNIT_ASSERT(count.load() == N);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::testExecutor()
|
||||
{
|
||||
dht::ThreadPool pool(8);
|
||||
auto executor1 = std::make_shared<dht::Executor>(pool, 1);
|
||||
auto executor4 = std::make_shared<dht::Executor>(pool, 4);
|
||||
auto executor8 = std::make_shared<dht::Executor>(pool, 8);
|
||||
|
||||
constexpr unsigned N = 64 * 1024;
|
||||
std::atomic_uint count1 {0};
|
||||
std::atomic_uint count4 {0};
|
||||
std::atomic_uint count8 {0};
|
||||
for (unsigned i=0; i<N; i++) {
|
||||
executor1->run([&] { count1++; });
|
||||
executor4->run([&] { count4++; });
|
||||
executor8->run([&] { count8++; });
|
||||
}
|
||||
|
||||
auto start = clock::now();
|
||||
while ((count1.load() != N ||
|
||||
count4.load() != N ||
|
||||
count8.load() != N) && clock::now() - start < std::chrono::seconds(20))
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
executor1.reset();
|
||||
executor4.reset();
|
||||
executor8.reset();
|
||||
CPPUNIT_ASSERT_EQUAL(N, count1.load());
|
||||
CPPUNIT_ASSERT_EQUAL(N, count4.load());
|
||||
CPPUNIT_ASSERT_EQUAL(N, count8.load());
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::tearDown() {
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@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
|
||||
@@ -15,29 +16,33 @@
|
||||
* 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
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
// cppunit
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#ifndef IPV6_JOIN_GROUP
|
||||
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
|
||||
#endif
|
||||
namespace test {
|
||||
|
||||
namespace dht {
|
||||
namespace net {
|
||||
class ThreadPoolTester : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(ThreadPoolTester);
|
||||
CPPUNIT_TEST(testThreadPool);
|
||||
CPPUNIT_TEST(testExecutor);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
bool set_nonblocking(int fd, bool nonblocking = true);
|
||||
public:
|
||||
/**
|
||||
* Method automatically called before each test by CppUnit
|
||||
*/
|
||||
void setUp();
|
||||
/**
|
||||
* Method automatically called after each test CppUnit
|
||||
*/
|
||||
void tearDown();
|
||||
|
||||
#ifdef _WIN32
|
||||
void udpPipe(int fds[2]);
|
||||
#endif
|
||||
void testThreadPool();
|
||||
void testExecutor();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace test
|
||||
+103
-90
@@ -48,10 +48,16 @@ void print_id_req() {
|
||||
std::cout << "An identity is required to perform this operation (run with -i)" << std::endl;
|
||||
}
|
||||
|
||||
void print_node_info(const std::shared_ptr<DhtRunner>& dht, const dht_params& params) {
|
||||
std::cout << "OpenDHT node " << dht->getNodeId() << " running on port " << dht->getBoundPort() << std::endl;
|
||||
if (params.generate_identity)
|
||||
std::cout << "Public key ID " << dht->getId() << std::endl;
|
||||
void print_node_info(const std::shared_ptr<DhtRunner>& node, const dht_params& params) {
|
||||
std::cout << "OpenDHT node " << node->getNodeId() << " running on ";
|
||||
auto port4 = node->getBoundPort(AF_INET);
|
||||
auto port6 = node->getBoundPort(AF_INET6);
|
||||
if (port4 == port6)
|
||||
std::cout << "port " << port4 << std::endl;
|
||||
else
|
||||
std::cout << "IPv4 port " << port4 << ", IPv6 port " << port6 << std::endl;
|
||||
if (params.id.first)
|
||||
std::cout << "Public key ID " << node->getId() << std::endl;
|
||||
}
|
||||
|
||||
void print_help() {
|
||||
@@ -110,13 +116,13 @@ void print_help() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
, std::map<in_port_t, std::unique_ptr<DhtProxyServer>>& proxies
|
||||
#endif
|
||||
)
|
||||
{
|
||||
print_node_info(dht, params);
|
||||
print_node_info(node, params);
|
||||
std::cout << " (type 'h' or 'help' for a list of possible commands)" << std::endl << std::endl;
|
||||
|
||||
#ifndef WIN32_NATIVE
|
||||
@@ -145,11 +151,11 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
print_help();
|
||||
continue;
|
||||
} else if (op == "ll") {
|
||||
print_node_info(dht, params);
|
||||
print_node_info(node, params);
|
||||
std::cout << "IPv4 stats:" << std::endl;
|
||||
std::cout << dht->getNodesStats(AF_INET).toString() << std::endl;
|
||||
std::cout << node->getNodesStats(AF_INET).toString() << std::endl;
|
||||
std::cout << "IPv6 stats:" << std::endl;
|
||||
std::cout << dht->getNodesStats(AF_INET6).toString() << std::endl;
|
||||
std::cout << node->getNodesStats(AF_INET6).toString() << std::endl;
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
for (const auto& proxy : proxies) {
|
||||
std::cout << "Stats for proxy on port " << proxy.first << std::endl;
|
||||
@@ -159,29 +165,29 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
continue;
|
||||
} else if (op == "lr") {
|
||||
std::cout << "IPv4 routing table:" << std::endl;
|
||||
std::cout << dht->getRoutingTablesLog(AF_INET) << std::endl;
|
||||
std::cout << node->getRoutingTablesLog(AF_INET) << std::endl;
|
||||
std::cout << "IPv6 routing table:" << std::endl;
|
||||
std::cout << dht->getRoutingTablesLog(AF_INET6) << std::endl;
|
||||
std::cout << node->getRoutingTablesLog(AF_INET6) << std::endl;
|
||||
continue;
|
||||
} else if (op == "ld") {
|
||||
iss >> idstr;
|
||||
InfoHash filter(idstr);
|
||||
if (filter)
|
||||
std::cout << dht->getStorageLog(filter) << std::endl;
|
||||
std::cout << node->getStorageLog(filter) << std::endl;
|
||||
else
|
||||
std::cout << dht->getStorageLog() << std::endl;
|
||||
std::cout << node->getStorageLog() << std::endl;
|
||||
continue;
|
||||
} else if (op == "ls") {
|
||||
iss >> idstr;
|
||||
InfoHash filter(idstr);
|
||||
if (filter)
|
||||
std::cout << dht->getSearchLog(filter) << std::endl;
|
||||
std::cout << node->getSearchLog(filter) << std::endl;
|
||||
else
|
||||
std::cout << dht->getSearchesLog() << std::endl;
|
||||
std::cout << node->getSearchesLog() << std::endl;
|
||||
continue;
|
||||
} else if (op == "la") {
|
||||
std::cout << "Reported public addresses:" << std::endl;
|
||||
auto addrs = dht->getPublicAddressStr();
|
||||
auto addrs = node->getPublicAddressStr();
|
||||
for (const auto& addr : addrs)
|
||||
std::cout << addr << std::endl;
|
||||
continue;
|
||||
@@ -191,7 +197,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
auto addr = splitPort(idstr);
|
||||
if (not addr.first.empty() and addr.second.empty())
|
||||
addr.second = std::to_string(DHT_DEFAULT_PORT);
|
||||
dht->bootstrap(addr.first.c_str(), addr.second.c_str());
|
||||
node->bootstrap(addr.first.c_str(), addr.second.c_str());
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
@@ -199,15 +205,15 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
} else if (op == "log") {
|
||||
iss >> idstr;
|
||||
InfoHash filter(idstr);
|
||||
params.log = filter == InfoHash{} ? !params.log : true;
|
||||
params.log = filter ? true : !params.log;
|
||||
if (params.log)
|
||||
log::enableLogging(*dht);
|
||||
log::enableLogging(*node);
|
||||
else
|
||||
log::disableLogging(*dht);
|
||||
dht->setLogFilter(filter);
|
||||
log::disableLogging(*node);
|
||||
node->setLogFilter(filter);
|
||||
continue;
|
||||
} else if (op == "cc") {
|
||||
dht->connectivityChanged();
|
||||
node->connectivityChanged();
|
||||
continue;
|
||||
}
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
@@ -220,9 +226,9 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
try {
|
||||
unsigned int port = std::stoi(idstr);
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(dht, port, pushServer)));
|
||||
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(node, port, pushServer)));
|
||||
#else
|
||||
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(dht, port)));
|
||||
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(node, port)));
|
||||
#endif // OPENDHT_PUSH_NOTIFICATIONS
|
||||
} catch (...) { }
|
||||
continue;
|
||||
@@ -238,16 +244,16 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
#endif //OPENDHT_PROXY_SERVER
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
else if (op == "stt") {
|
||||
dht->enableProxy(true);
|
||||
node->enableProxy(true);
|
||||
continue;
|
||||
} else if (op == "stp") {
|
||||
dht->enableProxy(false);
|
||||
node->enableProxy(false);
|
||||
continue;
|
||||
}
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
else if (op == "rp") {
|
||||
iss >> value;
|
||||
dht->pushNotificationReceived({{"to", "dhtnode"}, {"token", value}});
|
||||
node->pushNotificationReceived({{"to", "dhtnode"}, {"token", value}});
|
||||
continue;
|
||||
}
|
||||
#endif // OPENDHT_PUSH_NOTIFICATIONS
|
||||
@@ -284,7 +290,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
std::transform(key.begin(), key.end(), std::inserter(ks, ks.end()), [](Pht::Key::value_type& f) {
|
||||
return std::make_pair(f.first, f.second.size());
|
||||
});
|
||||
indexes.emplace(index, Pht {index, std::move(ks), dht});
|
||||
indexes.emplace(index, Pht {index, std::move(ks), node});
|
||||
} catch (std::invalid_argument& e) { std::cout << e.what() << std::endl; }
|
||||
}
|
||||
}
|
||||
@@ -308,35 +314,36 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
if (op == "g") {
|
||||
std::string rem;
|
||||
std::getline(iss, rem);
|
||||
dht->get(id, [start](std::shared_ptr<Value> value) {
|
||||
node->get(id, [start](const std::vector<std::shared_ptr<Value>>& values) {
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Get: found value (after " << print_dt(now-start) << "s)" << std::endl;
|
||||
std::cout << "\t" << *value << std::endl;
|
||||
std::cout << "Get: found " << values.size() << " value(s) after " << print_duration(now-start) << std::endl;
|
||||
for (const auto& value : values)
|
||||
std::cout << "\t" << *value << std::endl;
|
||||
return true;
|
||||
}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Get: " << (ok ? "completed" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Get: " << (ok ? "completed" : "failure") << ", took " << print_duration(end-start) << std::endl;
|
||||
}, {}, dht::Where {rem});
|
||||
}
|
||||
else if (op == "q") {
|
||||
std::string rem;
|
||||
std::getline(iss, rem);
|
||||
dht->query(id, [start](const std::vector<std::shared_ptr<FieldValueIndex>>& field_value_indexes) {
|
||||
node->query(id, [start](const std::vector<std::shared_ptr<FieldValueIndex>>& field_value_indexes) {
|
||||
auto now = std::chrono::high_resolution_clock::now();
|
||||
for (auto& index : field_value_indexes) {
|
||||
std::cout << "Query: found field value index (after " << print_dt(now-start) << "s)" << std::endl;
|
||||
std::cout << "Query: found field value index after " << print_duration(now-start) << std::endl;
|
||||
std::cout << "\t" << *index << std::endl;
|
||||
}
|
||||
return true;
|
||||
}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Query: " << (ok ? "completed" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Query: " << (ok ? "completed" : "failure") << ", took " << print_duration(end-start) << std::endl;
|
||||
}, dht::Query {rem});
|
||||
}
|
||||
else if (op == "l") {
|
||||
std::string rem;
|
||||
std::getline(iss, rem);
|
||||
auto token = dht->listen(id, [](const std::vector<std::shared_ptr<Value>>& values, bool expired) {
|
||||
auto token = node->listen(id, [](const std::vector<std::shared_ptr<Value>>& values, bool expired) {
|
||||
std::cout << "Listen: found " << values.size() << " values" << (expired ? " expired" : "") << std::endl;
|
||||
for (const auto& value : values)
|
||||
std::cout << "\t" << *value << std::endl;
|
||||
@@ -355,17 +362,17 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
std::cerr << "Syntax: cl [key] [token]" << std::endl;
|
||||
continue;
|
||||
}
|
||||
dht->cancelListen(id, token);
|
||||
node->cancelListen(id, token);
|
||||
}
|
||||
else if (op == "p") {
|
||||
std::string v;
|
||||
iss >> v;
|
||||
dht->put(id, dht::Value {
|
||||
node->put(id, dht::Value {
|
||||
dht::ValueType::USER_DATA.id,
|
||||
std::vector<uint8_t> {v.begin(), v.end()}
|
||||
}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Put: " << (ok ? "success" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Put: " << (ok ? "success" : "failure") << ", took " << print_duration(end-start) << std::endl;
|
||||
});
|
||||
}
|
||||
else if (op == "pp") {
|
||||
@@ -375,55 +382,55 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
dht::ValueType::USER_DATA.id,
|
||||
std::vector<uint8_t> {v.begin(), v.end()}
|
||||
);
|
||||
dht->put(id, value, [start,value](bool ok) {
|
||||
node->put(id, value, [start,value](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto flags(std::cout.flags());
|
||||
std::cout << "Put: " << (ok ? "success" : "failure") << " (took " << print_dt(end-start) << "s). Value ID: " << std::hex << value->id << std::endl;
|
||||
std::cout << "Put: " << (ok ? "success" : "failure") << ", took " << print_duration(end-start) << ". Value ID: " << std::hex << value->id << std::endl;
|
||||
std::cout.flags(flags);
|
||||
}, time_point::max(), true);
|
||||
}
|
||||
else if (op == "cpp") {
|
||||
std::string rem;
|
||||
iss >> rem;
|
||||
dht->cancelPut(id, std::stoul(rem, nullptr, 16));
|
||||
node->cancelPut(id, std::stoul(rem, nullptr, 16));
|
||||
}
|
||||
else if (op == "s") {
|
||||
if (not params.generate_identity) {
|
||||
if (not params.id.first) {
|
||||
print_id_req();
|
||||
continue;
|
||||
}
|
||||
std::string v;
|
||||
iss >> v;
|
||||
dht->putSigned(id, dht::Value {
|
||||
node->putSigned(id, dht::Value {
|
||||
dht::ValueType::USER_DATA.id,
|
||||
std::vector<uint8_t> {v.begin(), v.end()}
|
||||
}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Put signed: " << (ok ? "success" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Put signed: " << (ok ? "success" : "failure") << " (took " << print_duration(end-start) << "s)" << std::endl;
|
||||
});
|
||||
}
|
||||
else if (op == "e") {
|
||||
if (not params.generate_identity) {
|
||||
if (not params.id.first) {
|
||||
print_id_req();
|
||||
continue;
|
||||
}
|
||||
std::string tostr;
|
||||
std::string v;
|
||||
iss >> tostr >> v;
|
||||
dht->putEncrypted(id, InfoHash(tostr), dht::Value {
|
||||
node->putEncrypted(id, InfoHash(tostr), dht::Value {
|
||||
dht::ValueType::USER_DATA.id,
|
||||
std::vector<uint8_t> {v.begin(), v.end()}
|
||||
}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Put encrypted: " << (ok ? "success" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Put encrypted: " << (ok ? "success" : "failure") << " (took " << print_duration(end-start) << std::endl;
|
||||
});
|
||||
}
|
||||
else if (op == "a") {
|
||||
in_port_t port;
|
||||
iss >> port;
|
||||
dht->put(id, dht::Value {dht::IpServiceAnnouncement::TYPE.id, dht::IpServiceAnnouncement(port)}, [start](bool ok) {
|
||||
node->put(id, dht::Value {dht::IpServiceAnnouncement::TYPE.id, dht::IpServiceAnnouncement(port)}, [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Announce: " << (ok ? "success" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
|
||||
std::cout << "Announce: " << (ok ? "success" : "failure") << " (took " << print_duration(end-start) << std::endl;
|
||||
});
|
||||
}
|
||||
#ifdef OPENDHT_INDEXATION
|
||||
@@ -446,7 +453,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
|
||||
[start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Pht::lookup: " << (ok ? "done." : "failed.")
|
||||
<< " took " << print_dt(end-start) << "s)" << std::endl;
|
||||
<< " took " << print_duration(end-start) << std::endl;
|
||||
|
||||
}, exact_match.size() != 0 and exact_match == "false" ? false : true
|
||||
);
|
||||
@@ -484,59 +491,62 @@ main(int argc, char **argv)
|
||||
#ifdef WIN32_NATIVE
|
||||
gnutls_global_init();
|
||||
#endif
|
||||
auto params = parseArgs(argc, argv);
|
||||
if (params.help) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
if (params.version) {
|
||||
print_version();
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto dht = std::make_shared<DhtRunner>();
|
||||
if (params.daemonize) {
|
||||
daemonize();
|
||||
}
|
||||
setupSignals();
|
||||
|
||||
auto node = std::make_shared<DhtRunner>();
|
||||
|
||||
try {
|
||||
auto params = parseArgs(argc, argv);
|
||||
if (params.help) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
if (params.version) {
|
||||
print_version();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (params.daemonize) {
|
||||
daemonize();
|
||||
} else if (params.service) {
|
||||
setupSignals();
|
||||
}
|
||||
|
||||
dht::crypto::Identity crt {};
|
||||
if (params.generate_identity) {
|
||||
if (not params.id.first and params.generate_identity) {
|
||||
auto ca_tmp = dht::crypto::generateEcIdentity("DHT Node CA");
|
||||
crt = dht::crypto::generateIdentity("DHT Node", ca_tmp);
|
||||
params.id = dht::crypto::generateIdentity("DHT Node", ca_tmp);
|
||||
if (not params.save_identity.empty()) {
|
||||
dht::crypto::saveIdentity(ca_tmp, params.save_identity + "_ca", params.privkey_pwd);
|
||||
dht::crypto::saveIdentity(params.id, params.save_identity, params.privkey_pwd);
|
||||
}
|
||||
}
|
||||
|
||||
dht::DhtRunner::Config config {};
|
||||
config.dht_config.node_config.network = params.network;
|
||||
config.dht_config.node_config.maintain_storage = false;
|
||||
config.dht_config.node_config.persist_path = params.persist_path;
|
||||
config.dht_config.id = crt;
|
||||
config.dht_config.id = params.id;
|
||||
config.threaded = true;
|
||||
config.proxy_server = params.proxyclient;
|
||||
config.push_node_id = "dhtnode";
|
||||
config.peer_discovery = params.peer_discovery;
|
||||
config.peer_publish = params.peer_discovery;
|
||||
if (not params.proxyclient.empty())
|
||||
dht->setPushNotificationToken(params.devicekey);
|
||||
|
||||
dht->run(params.port, config);
|
||||
node->setPushNotificationToken(params.devicekey);
|
||||
|
||||
dht::DhtRunner::Context context {};
|
||||
if (params.log) {
|
||||
if (params.syslog or (params.daemonize and params.logfile.empty()))
|
||||
log::enableSyslog(*dht, "dhtnode");
|
||||
context.logger = log::getSyslogLogger("dhtnode");
|
||||
else if (not params.logfile.empty())
|
||||
log::enableFileLogging(*dht, params.logfile);
|
||||
context.logger = log::getFileLogger(params.logfile);
|
||||
else
|
||||
log::enableLogging(*dht);
|
||||
context.logger = log::getStdLogger();
|
||||
}
|
||||
node->run(params.port, config, std::move(context));
|
||||
if (context.logger)
|
||||
log::enableLogging(*node);
|
||||
|
||||
if (not params.bootstrap.first.empty()) {
|
||||
//std::cout << "Bootstrap: " << params.bootstrap.first << ":" << params.bootstrap.second << std::endl;
|
||||
dht->bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
|
||||
std::cout << "Bootstrap: " << params.bootstrap.first << ":" << params.bootstrap.second << std::endl;
|
||||
node->bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
|
||||
}
|
||||
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
@@ -544,7 +554,7 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
if (params.proxyserver != 0) {
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
proxies.emplace(params.proxyserver, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(dht, params.proxyserver, params.pushserver)));
|
||||
proxies.emplace(params.proxyserver, std::unique_ptr<DhtProxyServer>(new DhtProxyServer(node, params.proxyserver, params.pushserver, context.logger)));
|
||||
#else
|
||||
std::cerr << "DHT proxy server requested but OpenDHT built without proxy server support." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -554,7 +564,7 @@ main(int argc, char **argv)
|
||||
if (params.daemonize or params.service)
|
||||
while (runner.wait());
|
||||
else
|
||||
cmd_loop(dht, params
|
||||
cmd_loop(node, params
|
||||
#ifdef OPENDHT_PROXY_SERVER
|
||||
, proxies
|
||||
#endif
|
||||
@@ -566,20 +576,23 @@ main(int argc, char **argv)
|
||||
|
||||
std::condition_variable cv;
|
||||
std::mutex m;
|
||||
std::atomic_bool done {false};
|
||||
bool done {false};
|
||||
|
||||
dht->shutdown([&]()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
done = true;
|
||||
node->shutdown([&]() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
done = true;
|
||||
}
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
// wait for shutdown
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
cv.wait(lk, [&](){ return done.load(); });
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
cv.wait(lk, [&](){ return done; });
|
||||
}
|
||||
|
||||
dht->join();
|
||||
node->join();
|
||||
#ifdef WIN32_NATIVE
|
||||
gnutls_global_deinit();
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# Copyright (C) 2017-2019 Savoir-faire Linux Inc.
|
||||
# Author: 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
|
||||
# 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/>.
|
||||
#
|
||||
# Manually run with Web UI:
|
||||
# locust -f tester.py --host http://127.0.0.1:8080
|
||||
#
|
||||
# Run in Terminal:
|
||||
# locust -f tester.py --host http://127.0.0.1:8080 \
|
||||
# --clients 100 --hatch-rate 1 --run-time 10s --no-web --only-summary
|
||||
|
||||
from locust import HttpLocust, TaskSet
|
||||
from random import randint
|
||||
import urllib.request
|
||||
import base64
|
||||
import json
|
||||
|
||||
words_url = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain"
|
||||
words_resp = urllib.request.urlopen(words_url)
|
||||
words = words_resp.read().decode().splitlines()
|
||||
|
||||
headers = {'content-type': 'application/json'}
|
||||
|
||||
def rand_list_value(mylist):
|
||||
return mylist[randint(0, len(mylist) - 1)]
|
||||
|
||||
def put_key(l):
|
||||
key = rand_list_value(words)
|
||||
val = rand_list_value(words)
|
||||
print("Put/get: key={} value={}".format(key, val))
|
||||
data = base64.b64encode(val.encode()).decode()
|
||||
print("Base64 encoding: value={} encoded={}".format(val, data))
|
||||
l.client.post("/" + key, data=json.dumps({"data": data}),
|
||||
headers=headers, catch_response=True)
|
||||
|
||||
def get_key(l):
|
||||
key = rand_list_value(words)
|
||||
print("Get: key={}".format(key))
|
||||
l.client.get("/" + key)
|
||||
|
||||
def get_stats(l):
|
||||
l.client.get("/stats")
|
||||
|
||||
def subscribe(l):
|
||||
key = rand_list_value(words)
|
||||
print("Subscribe: key={}".format(key))
|
||||
l.client.get("/" + key + "/subscribe")
|
||||
|
||||
def listen(l):
|
||||
key = rand_list_value(words)
|
||||
print("Listen: key={}".format(key))
|
||||
l.client.get("/" + key + "/listen")
|
||||
|
||||
class UserBehavior(TaskSet):
|
||||
tasks = {get_key: 5, put_key: 5, get_stats: 1, subscribe: 1, listen: 1}
|
||||
|
||||
def on_start(self):
|
||||
put_key(self)
|
||||
get_key(self)
|
||||
subscribe(self)
|
||||
listen(self)
|
||||
|
||||
def on_stop(self):
|
||||
get_stats(self)
|
||||
|
||||
class WebsiteUser(HttpLocust):
|
||||
task_set = UserBehavior
|
||||
min_wait = 5000
|
||||
max_wait = 9000
|
||||
print("Initiate the benchmark at http://127.0.0.1:8089/")
|
||||
@@ -1 +1 @@
|
||||
DHT_ARGS=-b bootstrap.ring.cx -p 4222 -v
|
||||
DHT_ARGS=-b bootstrap.jami.net -p 4222 -v
|
||||
@@ -1,13 +1,13 @@
|
||||
[Unit]
|
||||
Description=OpenDHT standalone node
|
||||
After=network.target
|
||||
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=@sysconfdir@/dhtnode.conf
|
||||
ExecStart=@bindir@/dhtnode -d $DHT_ARGS
|
||||
ExecStart=@bindir@/dhtnode -s $DHT_ARGS
|
||||
KillMode=process
|
||||
Restart=on-failure
|
||||
Type=forking
|
||||
Type=simple
|
||||
DynamicUser=yes
|
||||
|
||||
[Install]
|
||||
|
||||
+81
-32
@@ -22,6 +22,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <opendht.h>
|
||||
#include <opendht/log.h>
|
||||
#include <opendht/crypto.h>
|
||||
#ifndef WIN32_NATIVE
|
||||
#include <getopt.h>
|
||||
#include <readline/readline.h>
|
||||
@@ -86,53 +88,79 @@ bool isInfoHash(const dht::InfoHash& h) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
loadFile(const std::string& path)
|
||||
{
|
||||
std::vector<uint8_t> buffer;
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
if (!file)
|
||||
throw std::runtime_error("Can't read file: "+path);
|
||||
file.seekg(0, std::ios::end);
|
||||
auto size = file.tellg();
|
||||
if (size > std::numeric_limits<unsigned>::max())
|
||||
throw std::runtime_error("File is too big: "+path);
|
||||
buffer.resize(size);
|
||||
file.seekg(0, std::ios::beg);
|
||||
if (!file.read((char*)buffer.data(), size))
|
||||
throw std::runtime_error("Can't load file: "+path);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
|
||||
|
||||
struct dht_params {
|
||||
bool help {false}; // print help and exit
|
||||
bool version {false};
|
||||
bool log {false};
|
||||
std::string logfile {};
|
||||
bool syslog {false};
|
||||
in_port_t port {0};
|
||||
dht::NetId network {0};
|
||||
bool generate_identity {false};
|
||||
bool daemonize {false};
|
||||
bool service {false};
|
||||
bool peer_discovery {false};
|
||||
bool log {false};
|
||||
bool syslog {false};
|
||||
std::string logfile {};
|
||||
std::pair<std::string, std::string> bootstrap {};
|
||||
dht::NetId network {0};
|
||||
in_port_t port {0};
|
||||
in_port_t proxyserver {0};
|
||||
std::string proxyclient {};
|
||||
std::string pushserver {};
|
||||
std::string devicekey {};
|
||||
std::string persist_path {};
|
||||
dht::crypto::Identity id {};
|
||||
std::string privkey_pwd {};
|
||||
std::string save_identity {};
|
||||
};
|
||||
|
||||
static const constexpr struct option long_options[] = {
|
||||
{"help", no_argument , nullptr, 'h'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"net", required_argument, nullptr, 'n'},
|
||||
{"bootstrap", required_argument, nullptr, 'b'},
|
||||
{"identity", no_argument , nullptr, 'i'},
|
||||
{"verbose", no_argument , nullptr, 'v'},
|
||||
{"daemonize", no_argument , nullptr, 'd'},
|
||||
{"service", no_argument , nullptr, 's'},
|
||||
{"peer-discovery", no_argument , nullptr, 'D'},
|
||||
{"persist", required_argument, nullptr, 'f'},
|
||||
{"logfile", required_argument, nullptr, 'l'},
|
||||
{"syslog", no_argument , nullptr, 'L'},
|
||||
{"proxyserver", required_argument, nullptr, 'S'},
|
||||
{"proxyclient", required_argument, nullptr, 'C'},
|
||||
{"pushserver", required_argument, nullptr, 'y'},
|
||||
{"devicekey", required_argument, nullptr, 'z'},
|
||||
{"version", no_argument , nullptr, 'V'},
|
||||
{nullptr, 0 , nullptr, 0}
|
||||
{"help", no_argument , nullptr, 'h'},
|
||||
{"port", required_argument, nullptr, 'p'},
|
||||
{"net", required_argument, nullptr, 'n'},
|
||||
{"bootstrap", required_argument, nullptr, 'b'},
|
||||
{"identity", no_argument , nullptr, 'i'},
|
||||
{"save-identity", required_argument, nullptr, 'I'},
|
||||
{"certificate", required_argument, nullptr, 'c'},
|
||||
{"privkey", required_argument, nullptr, 'k'},
|
||||
{"privkey-password", required_argument, nullptr, 'm'},
|
||||
{"verbose", no_argument , nullptr, 'v'},
|
||||
{"daemonize", no_argument , nullptr, 'd'},
|
||||
{"service", no_argument , nullptr, 's'},
|
||||
{"peer-discovery", no_argument , nullptr, 'D'},
|
||||
{"persist", required_argument, nullptr, 'f'},
|
||||
{"logfile", required_argument, nullptr, 'l'},
|
||||
{"syslog", no_argument , nullptr, 'L'},
|
||||
{"proxyserver", required_argument, nullptr, 'S'},
|
||||
{"proxyclient", required_argument, nullptr, 'C'},
|
||||
{"pushserver", required_argument, nullptr, 'y'},
|
||||
{"devicekey", required_argument, nullptr, 'z'},
|
||||
{"version", no_argument , nullptr, 'V'},
|
||||
{nullptr, 0 , nullptr, 0}
|
||||
};
|
||||
|
||||
dht_params
|
||||
parseArgs(int argc, char **argv) {
|
||||
dht_params params;
|
||||
int opt;
|
||||
std::string privkey;
|
||||
while ((opt = getopt_long(argc, argv, "hidsvDp:n:b:f:l:", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case 'p': {
|
||||
@@ -200,10 +228,36 @@ parseArgs(int argc, char **argv) {
|
||||
case 's':
|
||||
params.service = true;
|
||||
break;
|
||||
case 'c': {
|
||||
try {
|
||||
params.id.second = std::make_shared<dht::crypto::Certificate>(loadFile(optarg));
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error(std::string("Error loading certificate: ") + e.what());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'k':
|
||||
privkey = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
params.privkey_pwd = optarg;
|
||||
break;
|
||||
case 'I':
|
||||
params.save_identity = optarg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (not privkey.empty()) {
|
||||
try {
|
||||
params.id.first = std::make_shared<dht::crypto::PrivateKey>(loadFile(privkey), params.privkey_pwd);
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error(std::string("Error loading private key: ") + e.what());
|
||||
}
|
||||
}
|
||||
if (params.save_identity.empty())
|
||||
params.privkey_pwd.clear();
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -228,18 +282,17 @@ readLine(const char* prefix = PROMPT)
|
||||
struct ServiceRunner {
|
||||
bool wait() {
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
cv.wait(lock, [&]{return terminate;});
|
||||
cv.wait(lock, [&]{return terminate.load();});
|
||||
return !terminate;
|
||||
}
|
||||
void kill() {
|
||||
std::lock_guard<std::mutex> lock(m);
|
||||
terminate = true;
|
||||
cv.notify_all();
|
||||
}
|
||||
private:
|
||||
std::condition_variable cv;
|
||||
std::mutex m;
|
||||
bool terminate = false;
|
||||
std::atomic_bool terminate {false};
|
||||
};
|
||||
|
||||
ServiceRunner runner;
|
||||
@@ -250,6 +303,8 @@ void signal_handler(int sig)
|
||||
case SIGHUP:
|
||||
break;
|
||||
case SIGINT:
|
||||
close(STDIN_FILENO);
|
||||
// fall through
|
||||
case SIGTERM:
|
||||
runner.kill();
|
||||
break;
|
||||
@@ -283,14 +338,8 @@ void daemonize()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((chdir("/")) < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
|
||||
setupSignals();
|
||||
#endif
|
||||
}
|
||||
Reference in new issue
Block a user