Compare commits

..
4 Commits
Author SHA1 Message Date
Adrien Béraud 1751cb02cb dhtnode: print metrics 2020-03-30 14:18:41 -04:00
Adrien Béraud c8cc0e9750 add req count debug 2020-03-30 14:18:41 -04:00
Adrien Béraud 6f05112970 dht: add node metrics
Provides info about internal dht structures
2020-03-30 14:18:41 -04:00
Adrien Béraud a1d62fd062 stats: add search, cached node count 2020-03-30 14:18:23 -04:00
73 changed files with 2689 additions and 2598 deletions

No files matched your search

+5 -4
View File
@@ -16,12 +16,13 @@ env:
before_install:
- |
if [[ "$OPENDHT_TEST_JOB" == *"opendht.classic"* ]]; then
docker pull aberaud/opendht-deps-bionic;
fi
if [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyclient"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyserver"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.push"* ]]; then
# non llvm builds
if [[ "$OPENDHT_TEST_JOB" != *"opendht.llvm"* ]]; then
docker pull aberaud/opendht-deps;
fi
- |
# classic build
if [[ "$OPENDHT_TEST_JOB" == *"opendht.llvm"* ]]; then
docker pull aberaud/opendht-deps-llvm
fi
+88 -189
View File
@@ -4,7 +4,7 @@ include(CMakeDependentOption)
project (opendht)
set (opendht_VERSION_MAJOR 2)
set (opendht_VERSION_MINOR 1.6)
set (opendht_VERSION_MINOR 0.0)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -16,7 +16,6 @@ option (OPENDHT_LOG "Build with logs" ON)
option (OPENDHT_PYTHON "Build Python bindings" OFF)
option (OPENDHT_TOOLS "Build DHT tools" ON)
option (OPENDHT_SYSTEMD "Install systemd module" OFF)
option (OPENDHT_SYSTEMD_UNIT_FILE_LOCATION "Where to install systemd unit file")
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
option (OPENDHT_LTO "Build with LTO" OFF)
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
@@ -30,7 +29,6 @@ CMAKE_DEPENDENT_OPTION(OPENDHT_HTTP "Build embedded http(s) client" OFF "NOT OPE
option (OPENDHT_PEER_DISCOVERY "Enable multicast peer discovery" ON)
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
option (OPENDHT_TESTS "Add unit tests executable" OFF)
option (OPENDHT_TESTS_NETWORK "Enable unit tests that require network access" ON)
option (OPENDHT_C "Build C bindings" OFF)
find_package(Doxygen)
@@ -38,84 +36,62 @@ option (OPENDHT_DOCUMENTATION "Create and install the HTML based API documentati
# Dependencies
list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if (NOT MSVC)
find_package (Threads)
find_package (PkgConfig REQUIRED)
find_package (GnuTLS 3.3 REQUIRED)
pkg_search_module (Nettle nettle)
find_package (Msgpack 1.2 REQUIRED)
if (OPENDHT_TOOLS)
find_package (Readline 6 REQUIRED)
endif ()
if (NOT OPENDHT_ARGON2)
pkg_search_module(argon2 libargon2)
if (argon2_FOUND)
message("-- Found Argon2: " ${argon2_LIBRARY_DIRS} " (found version \"" ${argon2_VERSION} "\")")
link_directories (${argon2_LIBRARY_DIRS})
else ()
message("Argon2 not found, using included version.")
set(OPENDHT_ARGON2 ON)
endif()
endif ()
pkg_search_module(Jsoncpp jsoncpp)
if (Jsoncpp_FOUND)
add_definitions(-DOPENDHT_JSONCPP)
list (APPEND opendht_SOURCES
src/base64.h
src/base64.cpp
)
endif()
if (OPENDHT_HTTP)
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()
if (OPENDHT_PROXY_OPENSSL)
# https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
pkg_search_module(OPENSSL REQUIRED openssl)
if (OPENSSL_FOUND)
message(STATUS "Found OpenSSL ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIRS})
else ()
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
endif()
endif()
if (OPENDHT_PROXY_HTTP_PARSER_FORK)
add_definitions(-DOPENDHT_PROXY_HTTP_PARSER_FORK)
endif()
find_package (Threads)
find_package (PkgConfig)
find_package (GnuTLS 3.3 REQUIRED)
pkg_search_module (Nettle nettle)
find_package (Msgpack 1.2 REQUIRED)
if (OPENDHT_TOOLS)
find_package (Readline 6 REQUIRED)
endif ()
if (NOT OPENDHT_ARGON2)
find_package(PkgConfig)
pkg_search_module(argon2 libargon2)
if (argon2_FOUND)
message("-- Found Argon2: " ${argon2_LIBRARY_DIRS} " (found version \"" ${argon2_VERSION} "\")")
link_directories (${argon2_LIBRARY_DIRS})
else ()
set(OPENDHT_PROXY_OPENSSL OFF)
endif ()
else ()
set (WIN32_DEP_DIR ${PROJECT_SOURCE_DIR}/../)
include_directories(${WIN32_DEP_DIR}/../msvc/include) # SMP gnutls
include_directories(${WIN32_DEP_DIR}/argon2/include)
include_directories(${WIN32_DEP_DIR}/jsoncpp/include)
list (APPEND opendht_SOURCES
src/base64.h
src/base64.cpp
)
add_definitions(-DOPENDHT_JSONCPP)
include_directories(${WIN32_DEP_DIR}/msgpack-c/include)
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
include_directories(
${WIN32_DEP_DIR}/asio/asio/include
${WIN32_DEP_DIR}/openssl/include
${WIN32_DEP_DIR}/restinio/dev
${WIN32_DEP_DIR}/fmt/include
${WIN32_DEP_DIR}/http_parser
)
endif ()
message("Argon2 not found, using included version.")
set(OPENDHT_ARGON2 ON)
endif()
endif ()
pkg_search_module(Jsoncpp jsoncpp)
if (Jsoncpp_FOUND)
add_definitions(-DOPENDHT_JSONCPP)
list (APPEND opendht_SOURCES
src/base64.h
src/base64.cpp
)
endif()
if (OPENDHT_HTTP)
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()
if (OPENDHT_PROXY_OPENSSL)
# https://cmake.org/cmake/help/latest/module/FindOpenSSL.html
pkg_search_module(OPENSSL REQUIRED openssl)
if (OPENSSL_FOUND)
message(STATUS "Found OpenSSL ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIRS})
else ()
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
endif()
endif()
if (OPENDHT_PROXY_HTTP_PARSER_FORK)
add_definitions(-DOPENDHT_PROXY_HTTP_PARSER_FORK)
endif()
else()
set(OPENDHT_PROXY_OPENSSL OFF)
endif()
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
add_definitions(-DASIO_STANDALONE)
endif()
@@ -123,25 +99,9 @@ endif()
# Build flags
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_STANDARD_REQUIRED on)
if (NOT MSVC)
set(CXX_WARNINGS -Wno-return-type -Wall -Wextra
-Wnon-virtual-dtor
-pedantic-errors
-fvisibility=hidden)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNINGS}")
if (OPENDHT_SANITIZE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
endif ()
else ()
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-DWIN32_LEAN_AND_MEAN
-DSTATIC_GETOPT
-DGNUTLS_INTERNAL_BUILD)
set(DISABLE_MSC_WARNINGS "/wd4101 /wd4244 /wd4267 /wd4273 /wd4804 /wd4834 /wd4996")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DISABLE_MSC_WARNINGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
if (OPENDHT_SANITIZE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
endif ()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
@@ -154,7 +114,7 @@ if (OPENDHT_LOG)
else ()
add_definitions(-DOPENDHT_LOG=false)
endif()
if (OPENDHT_LTO AND NOT MSVC)
if (OPENDHT_LTO)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
if (CMAKE_COMPILER_IS_GNUCC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-linker-plugin")
@@ -326,81 +286,23 @@ if(OPENDHT_ARGON2)
include_directories(argon2/include/)
endif()
# cross-platform compatibility sources
set (COMPAT_DIR ${PROJECT_SOURCE_DIR}/src/compat/)
list (APPEND opendht_SOURCES ${COMPAT_DIR}/os_cert.cpp)
if (MSVC)
set (MSC_COMPAT_DIR ${COMPAT_DIR}/msvc/)
list (APPEND opendht_SOURCES ${MSC_COMPAT_DIR}/unistd.h)
endif ()
# Targets
if (OPENDHT_STATIC)
if (NOT MSVC)
add_library (opendht-static STATIC
${opendht_SOURCES}
${opendht_HEADERS}
)
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
if (OPENDHT_ARGON2)
target_include_directories(opendht-static SYSTEM PRIVATE argon2)
else ()
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht-static
PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_STATIC_LIBRARIES}
${Jsoncpp_STATIC_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
${OPENSSL_STATIC_LIBRARIES})
add_library (opendht-static STATIC
${opendht_SOURCES}
${opendht_HEADERS}
)
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
if (OPENDHT_ARGON2)
target_include_directories(opendht-static SYSTEM PRIVATE argon2)
else ()
if (OPENDHT_TOOLS)
function (add_obj_lib name libfile)
add_library(${name} OBJECT IMPORTED)
set_property(TARGET ${name} PROPERTY IMPORTED_OBJECTS ${libfile})
endfunction ()
add_obj_lib (win32_json ${WIN32_DEP_DIR}/../msvc/lib/x64/lib_json.lib)
add_obj_lib (win32_gnutls ${WIN32_DEP_DIR}/../msvc/lib/x64/libgnutls.lib)
add_obj_lib (win32_argon2 ${WIN32_DEP_DIR}/argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib)
list (APPEND obj_libs
$<TARGET_OBJECTS:win32_json>
$<TARGET_OBJECTS:win32_gnutls>
$<TARGET_OBJECTS:win32_argon2>
)
if (OPENDHT_HTTP)
add_obj_lib (win32_fmt ${WIN32_DEP_DIR}/fmt/msvc/Release/fmt.lib)
add_obj_lib (win32_http_parser ${WIN32_DEP_DIR}/http_parser/x64/Release/http-parser.lib)
add_obj_lib (win32_ssl ${WIN32_DEP_DIR}/openssl/libssl_static.lib)
add_obj_lib (win32_crypto ${WIN32_DEP_DIR}/openssl/libcrypto_static.lib)
list (APPEND obj_libs
$<TARGET_OBJECTS:win32_fmt>
$<TARGET_OBJECTS:win32_http_parser>
$<TARGET_OBJECTS:win32_ssl>
$<TARGET_OBJECTS:win32_crypto>
)
endif ()
else ()
list (APPEND win32_Libs
${PROJECT_SOURCE_DIR}/../../msvc/lib/x64/libgnutls.lib
${PROJECT_SOURCE_DIR}/../../msvc/lib/x64/lib_json.lib
${PROJECT_SOURCE_DIR}/../argon2/vs2015/Argon2Ref/vs2015/build/Argon2Ref.lib
)
list (APPEND win32_Libs
${PROJECT_SOURCE_DIR}/../fmt/msvc/Release/fmt.lib
${PROJECT_SOURCE_DIR}/../http_parser/x64/Release/http-parser.lib
${PROJECT_SOURCE_DIR}/../openssl/libssl.lib
${PROJECT_SOURCE_DIR}/../openssl/libcrypto.lib
)
endif ()
add_library (opendht-static STATIC
${opendht_SOURCES}
${opendht_HEADERS}
${obj_libs}
)
target_link_libraries(opendht-static PUBLIC ${Win32_STATIC_LIBRARIES} ${Win32_IMPORT_LIBRARIES})
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4006")
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "libopendht")
endif()
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif ()
target_link_libraries(opendht-static
PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
${OPENSSL_LIBRARIES})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
@@ -478,7 +380,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/opendhtConfigVersion.cmake DESTINATIO
# Unit tests
if (OPENDHT_TESTS)
pkg_search_module(Cppunit REQUIRED cppunit)
FIND_PACKAGE(Cppunit REQUIRED)
# unit testing
list (APPEND test_FILES
tests/infohashtester.h
@@ -492,28 +394,25 @@ if (OPENDHT_TESTS)
tests/threadpooltester.h
tests/threadpooltester.cpp
)
if (OPENDHT_TESTS_NETWORK)
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
list (APPEND test_FILES
tests/httptester.h
tests/httptester.cpp
tests/dhtproxytester.h
tests/dhtproxytester.cpp
)
endif()
if (OPENDHT_PEER_DISCOVERY)
list (APPEND test_FILES
tests/peerdiscoverytester.h
tests/peerdiscoverytester.cpp
)
endif()
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
list (APPEND test_FILES
tests/httptester.h
tests/httptester.cpp
tests/dhtproxytester.h
tests/dhtproxytester.cpp
)
endif()
if (OPENDHT_PEER_DISCOVERY)
list (APPEND test_FILES
tests/peerdiscoverytester.h
tests/peerdiscoverytester.cpp
)
endif()
add_executable(opendht_unit_tests
tests/tests_runner.cpp
${test_FILES}
)
target_include_directories(opendht_unit_tests SYSTEM PRIVATE ${Cppunit_INCLUDE_DIR})
target_link_directories(opendht_unit_tests PRIVATE ${Cppunit_LIBRARY_DIRS})
target_include_directories(opendht_unit_tests SYSTEM PRIVATE ${CPPUNIT_INCLUDE_DIRS})
if (OPENDHT_SHARED)
target_link_libraries(opendht_unit_tests opendht)
else ()
@@ -521,7 +420,7 @@ if (OPENDHT_TESTS)
endif ()
target_link_libraries(opendht_unit_tests
${CMAKE_THREAD_LIBS_INIT}
${Cppunit_LIBRARIES}
${CPPUNIT_LIBRARIES}
${GNUTLS_LIBRARIES}
${Jsoncpp_LIBRARIES}
)
+248
View File
@@ -0,0 +1,248 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
#output directories
DebugLib/
Debug/
ReleaseLib/
Release/
.config/
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.VC.VC.opendb
*.VC.db
*.db
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
!config.h
contrib/build/
+168
View File
@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8BE7F14D-B227-4D54-9105-7E5473F2D0BA}</ProjectGuid>
<RootNamespace>dhtchat</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\tools\dhtchat.cpp" />
<ClCompile Include="wingetopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\tools\tools_common.h" />
<ClInclude Include="wingetopt.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+168
View File
@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{BF92AECF-AA1D-4B05-9D00-0247E92A24B5}</ProjectGuid>
<RootNamespace>dhtnode</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\tools\dhtnode.cpp" />
<ClCompile Include="wingetopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\tools\tools_common.h" />
<ClInclude Include="wingetopt.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+168
View File
@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{78443BCD-4689-4007-A246-F8F34B27F561}</ProjectGuid>
<RootNamespace>dhtscanner</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<OutDir>$(ProjectDir)..\..\bin\x64</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\restbed\source;$(ProjectDir)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4267;4244;4800;4273;4101;</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>restbed.lib;libeay32.lib;ssleay32.lib;crypt32.lib;Argon2Ref.lib;lib_json.lib;libgnutls.lib;libopendht.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\msvc\lib\$(PlatformTarget);$(ProjectDir)..\..\restbed\build\Release;$(ProjectDir)..\..\restbed\dependency\openssl\out32dll;$(ProjectDir)..\..\argon2\vs2015\Argon2Ref\vs2015\build</AdditionalLibraryDirectories>
<AdditionalOptions>/ignore:4049 %(AdditionalOptions)</AdditionalOptions>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\tools\dhtscanner.cpp" />
<ClCompile Include="wingetopt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\tools\tools_common.h" />
<ClInclude Include="wingetopt.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+257
View File
@@ -0,0 +1,257 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opendht", "opendht.vcxproj", "{711397CE-E5D5-467D-9457-8716C047E50C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
DebugDLL|x64 = DebugDLL|x64
DebugDLL|x86 = DebugDLL|x86
DebugDLLStaticDeps|x64 = DebugDLLStaticDeps|x64
DebugDLLStaticDeps|x86 = DebugDLLStaticDeps|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
ReleaseDLL|x64 = ReleaseDLL|x64
ReleaseDLL|x86 = ReleaseDLL|x86
ReleaseDLLStaticDeps|x64 = ReleaseDLLStaticDeps|x64
ReleaseDLLStaticDeps|x86 = ReleaseDLLStaticDeps|x86
ReleaseLTO|x64 = ReleaseLTO|x64
ReleaseLTO|x86 = ReleaseLTO|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.ActiveCfg = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.Build.0 = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.ActiveCfg = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.Build.0 = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.ActiveCfg = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.Build.0 = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.ActiveCfg = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.ActiveCfg = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.Build.0 = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.ActiveCfg = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.Build.0 = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.Build.0 = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.ActiveCfg = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.Build.0 = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.ActiveCfg = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.Build.0 = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.ActiveCfg = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.Build.0 = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.ActiveCfg = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.Build.0 = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.ActiveCfg = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.Build.0 = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.ActiveCfg = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.Build.0 = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.ActiveCfg = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.Build.0 = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.ActiveCfg = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.Build.0 = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.Build.0 = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.ActiveCfg = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.Build.0 = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.ActiveCfg = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.Build.0 = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.ActiveCfg = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.Build.0 = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.ActiveCfg = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.Build.0 = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.ActiveCfg = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.Build.0 = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.ActiveCfg = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.Build.0 = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.ActiveCfg = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.Build.0 = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.ActiveCfg = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.Build.0 = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.ActiveCfg = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.Build.0 = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.ActiveCfg = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.Build.0 = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.ActiveCfg = Debug|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.Build.0 = Debug|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+271
View File
@@ -0,0 +1,271 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\dht_proxy_client.cpp" />
<ClCompile Include="..\src\http.cpp" />
<ClCompile Include="..\src\network_utils.cpp" />
<ClCompile Include="..\src\op_cache.cpp" />
<ClCompile Include="..\src\peer_discovery.cpp" />
<ClCompile Include="..\src\rng.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\src\thread_pool.cpp" />
<ClCompile Include="wingetopt.c" />
<ClCompile Include="..\src\base64.cpp" />
<ClCompile Include="..\src\callbacks.cpp" />
<ClCompile Include="..\src\crypto.cpp" />
<ClCompile Include="..\src\default_types.cpp" />
<ClCompile Include="..\src\dht.cpp" />
<ClCompile Include="..\src\dhtrunner.cpp" />
<ClCompile Include="..\src\dht_proxy_server.cpp" />
<ClCompile Include="..\src\indexation\pht.cpp" />
<ClCompile Include="..\src\infohash.cpp" />
<ClCompile Include="..\src\log.cpp" />
<ClCompile Include="..\src\network_engine.cpp" />
<ClCompile Include="..\src\node.cpp" />
<ClCompile Include="..\src\node_cache.cpp" />
<ClCompile Include="..\src\routing_table.cpp" />
<ClCompile Include="..\src\securedht.cpp" />
<ClCompile Include="..\src\utils.cpp" />
<ClCompile Include="..\src\value.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\opendht\http.h" />
<ClInclude Include="..\src\network_utils.h" />
<ClInclude Include="..\src\thread_pool.h" />
<ClInclude Include="unistd.h" />
<ClInclude Include="wingetopt.h" />
<ClInclude Include="..\include\opendht.h" />
<ClInclude Include="..\include\opendht\callbacks.h" />
<ClInclude Include="..\include\opendht\crypto.h" />
<ClInclude Include="..\include\opendht\def.h" />
<ClInclude Include="..\include\opendht\default_types.h" />
<ClInclude Include="..\include\opendht\dht.h" />
<ClInclude Include="..\include\opendht\dhtrunner.h" />
<ClInclude Include="..\include\opendht\dht_proxy_server.h" />
<ClInclude Include="..\include\opendht\indexation\pht.h" />
<ClInclude Include="..\include\opendht\infohash.h" />
<ClInclude Include="..\include\opendht\log.h" />
<ClInclude Include="..\include\opendht\log_enable.h" />
<ClInclude Include="..\include\opendht\network_engine.h" />
<ClInclude Include="..\include\opendht\node.h" />
<ClInclude Include="..\include\opendht\node_cache.h" />
<ClInclude Include="..\include\opendht\rate_limiter.h" />
<ClInclude Include="..\include\opendht\rng.h" />
<ClInclude Include="..\include\opendht\routing_table.h" />
<ClInclude Include="..\include\opendht\scheduler.h" />
<ClInclude Include="..\include\opendht\securedht.h" />
<ClInclude Include="..\include\opendht\sockaddr.h" />
<ClInclude Include="..\include\opendht\utils.h" />
<ClInclude Include="..\include\opendht\value.h" />
<ClInclude Include="..\src\base64.h" />
<ClInclude Include="..\src\listener.h" />
<ClInclude Include="..\src\net.h" />
<ClInclude Include="..\src\parsed_message.h" />
<ClInclude Include="..\src\request.h" />
<ClInclude Include="..\src\search.h" />
<ClInclude Include="..\src\storage.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{711397CE-E5D5-467D-9457-8716C047E50C}</ProjectGuid>
<RootNamespace>opendht</RootNamespace>
<WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>libopendht</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>libopendht</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
<TargetName>libopendht</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)..\..\..\msvc\</OutDir>
<TargetName>libopendht</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
<SuppressStartupBanner>false</SuppressStartupBanner>
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
mkdir $(OutDir)\include\opendht\indexation
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
mkdir $(OutDir)\include\opendht\indexation
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
mkdir $(OutDir)\include\opendht\indexation
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;$(ProjectDir)..\include\opendht;$(ProjectDir)..\..\..\msvc\include;$(ProjectDir)..\..\include;$(ProjectDir)..\..\argon2\include;$(ProjectDir)..\..\msgpack-c\include;$(ProjectDir)..\..\jsoncpp\include;$(ProjectDir)..\..\openssl\inc32;$(ProjectDir)..\..\asio\asio\include;$(ProjectDir)..\..\restinio\dev;$(ProjectDir)..\..\fmt\include;$(ProjectDir)..\..\http_parser</AdditionalIncludeDirectories>
<PreprocessorDefinitions>OPENDHT_JSONCPP;OPENDHT_PROXY_CLIENT;OPENDHT_PROXY_SERVER;OPENDHT_PUSH_NOTIFICATIONS;_WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;4273;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNING;%(AdditionalOptions)</AdditionalOptions>
<ProgramDataBaseFileName>$(OutDir)lib\$(PlatformTarget)\$(TargetName).pdb</ProgramDataBaseFileName>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
mkdir $(OutDir)\include\opendht\indexation
copy ..\include\opendht\indexation\*.h $(OutDir)\include\opendht\indexation
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)lib\$(PlatformTarget)\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+198
View File
@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\src\callbacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\crypto.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\default_types.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\dht.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\dhtrunner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\infohash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\network_engine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\node.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\node_cache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\routing_table.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\securedht.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\value.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\base64.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\dht_proxy_server.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\indexation\pht.cpp">
<Filter>Source Files\indexation</Filter>
</ClCompile>
<ClCompile Include="wingetopt.c" />
<ClCompile Include="..\src\rng.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\op_cache.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\dht_proxy_client.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\peer_discovery.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\network_utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\thread_pool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\http.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\opendht.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\callbacks.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\crypto.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\default_types.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\dht.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\dht_proxy_server.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\dhtrunner.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\infohash.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\log.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\log_enable.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\network_engine.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\node.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\node_cache.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\rate_limiter.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\rng.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\routing_table.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\scheduler.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\securedht.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\utils.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\value.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\indexation\pht.h">
<Filter>Header Files\opendht\indexation</Filter>
</ClInclude>
<ClInclude Include="unistd.h" />
<ClInclude Include="wingetopt.h" />
<ClInclude Include="..\include\opendht\def.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\net.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\parsed_message.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\sockaddr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\network_utils.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\src\thread_pool.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
<ClInclude Include="..\src\listener.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\base64.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\search.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\request.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\src\storage.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="..\include\opendht\http.h">
<Filter>Header Files\opendht</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{be73d179-6cf2-4c05-8d91-53c8499a7134}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{d1ab5bfe-3ab1-45ee-9324-b4b071887668}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\indexation">
<UniqueIdentifier>{939134d3-d5a2-4458-bca8-a10ea9042ea2}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\opendht">
<UniqueIdentifier>{0b46e2d0-4874-404c-bae3-fae8d49b85b8}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\opendht\indexation">
<UniqueIdentifier>{03bd5139-2ae5-41b0-a77b-944814e1b2b6}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3 -3
View File
@@ -27,7 +27,7 @@ Build instructions: <https://github.com/savoirfairelinux/opendht/wiki/Build-the-
#### How-to build a simple client app
```bash
g++ main.cpp -std=c++14 -lopendht
g++ main.cpp -std=c++14 -lopendht -lgnutls
```
## Examples
@@ -51,7 +51,7 @@ int main()
// Join the network through any running node,
// here using a known bootstrap node.
node.bootstrap("bootstrap.jami.net", "4222");
node.bootstrap("bootstrap.ring.cx", "4222");
// put some data on the dht
std::vector<uint8_t> some_data(5, 10);
@@ -82,7 +82,7 @@ node.run()
# Join the network through any running node,
# here using a known bootstrap node.
node.bootstrap("bootstrap.jami.net", "4222")
node.bootstrap("bootstrap.ring.cx", "4222")
# blocking call (provide callback arguments to make the call non-blocking)
node.put(dht.InfoHash.get("unique_key"), dht.Value(b'some binary data'))
+28
View File
@@ -0,0 +1,28 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_CPPUNIT "cppunit")
FIND_PATH(CPPUNIT_INCLUDE_DIRS
NAMES cppunit/TestCase.h
HINTS ${PC_CPPUNIT_INCLUDE_DIR}
${CMAKE_INSTALL_PREFIX}/include
PATHS
/usr/local/include
/usr/include
)
FIND_LIBRARY(CPPUNIT_LIBRARIES
NAMES cppunit
HINTS ${PC_CPPUNIT_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS
${CPPUNIT_INCLUDE_DIRS}/../lib
/usr/local/lib
/usr/lib
)
LIST(APPEND CPPUNIT_LIBRARIES ${CMAKE_DL_LIBS})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CPPUNIT DEFAULT_MSG CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
MARK_AS_ADVANCED(CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
+2 -5
View File
@@ -1,7 +1,7 @@
dnl define macros
m4_define([opendht_major_version], 2)
m4_define([opendht_minor_version], 1)
m4_define([opendht_patch_version], 6)
m4_define([opendht_minor_version], 0)
m4_define([opendht_patch_version], 0)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
@@ -140,7 +140,6 @@ AS_IF([test "x$with_jsoncpp" != "xno"],
AS_IF([test "x$have_jsoncpp" = "xyes"], [
AC_MSG_NOTICE([Using JsonCpp])
CPPFLAGS+=" -DOPENDHT_JSONCPP"
AC_SUBST(jsoncpp_lib, [", jsoncpp"])
], [
AC_MSG_NOTICE([Not using JsonCpp])
AM_COND_IF(PROXY_CLIENT_OR_SERVER, AC_MSG_ERROR(["JsonCpp is required for proxy/push notification support"]))
@@ -152,7 +151,6 @@ AS_IF([test "x$with_openssl" != "xno"],
[have_openssl=no])
AS_IF([test "x$have_openssl" = "xyes"], [
AC_MSG_NOTICE([Using OpenSSL])
AC_SUBST(openssl_lib, [", openssl"])
], [
AC_MSG_NOTICE([Not using OpenSSL])
])
@@ -177,7 +175,6 @@ AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
# http_parser has no pkgconfig, instead we check with:
AC_CHECK_LIB(http_parser, exit,, AC_MSG_ERROR([Missing HttpParser library files]))
AC_CHECK_HEADERS([http_parser.h], [http_parser_headers=yes; break;])
AC_SUBST(http_parser_lib, ["-lhttp_parser"])
AS_IF([test "x$http_parser_headers" != "xyes"], AC_MSG_ERROR([Missing HttpParser headers files]))
])
+1 -1
View File
@@ -2,5 +2,5 @@ FROM aberaud/opendht-deps
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+1 -1
View File
@@ -1,4 +1,4 @@
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.1.3
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.0.0
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
+46 -17
View File
@@ -1,27 +1,56 @@
FROM ubuntu:20.04
FROM ubuntu:16.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update && apt-get install -y \
build-essential pkg-config cmake git wget \
autotools-dev autoconf \
cython3 python3-dev python3-setuptools \
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
libssl-dev libfmt-dev libhttp-parser-dev libasio-dev libmsgpack-dev \
build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
autotools-dev autoconf libssl-dev \
&& apt-get clean
RUN echo "*** Installing libfmt ***" \
&& wget https://github.com/fmtlib/fmt/archive/5.3.0.tar.gz \
&& tar -xzf 5.3.0.tar.gz && cd fmt-5.3.0/ \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=On -DFMT_TEST=Off -DFMT_DOC=Off . \
&& make -j8 && make install \
&& cd ../ && rm -rf fmt*
# libhttp-parser-dev is 2.1-2 which is too old
RUN echo "*** Building nodejs/http_parser dependency ***" \
&& wget https://github.com/nodejs/http-parser/archive/v2.9.2.tar.gz \
&& tar xvf v2.9.2.tar.gz && cd http-parser-2.9.2/ \
&& PREFIX=/usr make -j8 install \
&& cd ../ && rm -rf http-parser*
# libasio-dev (1.10.6-3) is too old
RUN echo "** Building a recent version of asio ***" \
&& wget https://github.com/aberaud/asio/archive/a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz \
&& tar -xvf a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz && cd asio-a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571/asio \
&& ./autogen.sh && ./configure --prefix=/usr --without-boost --disable-examples --disable-tests \
&& make install \
&& cd ../../ && rm -rf asio*
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/2c0b6f5e5ba04d7a74e8406a3df1fd433680599d.tar.gz \
&& ls -l && tar -xzf 2c0b6f5e5ba04d7a74e8406a3df1fd433680599d.tar.gz \
&& cd restinio-2c0b6f5e5ba04d7a74e8406a3df1fd433680599d/dev \
&& wget https://github.com/aberaud/restinio/archive/a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
&& ls -l && tar -xzf a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
&& cd restinio-a7a10e419d9089c5b8ee63f5e3098c892f22fae4/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
&& make -j8 && make install \
&& cd ../../.. && rm -rf restinio
&& cd ../../ && rm -rf restinio*
# build restbed from sources
RUN git clone --recursive https://github.com/corvusoft/restbed.git \
&& cd restbed && mkdir build && cd build \
&& cmake -DBUILD_TESTS=NO -DBUILD_EXAMPLES=NO -DBUILD_SSL=NO -DBUILD_SHARED=YES -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib .. \
&& make -j8 install \
&& cd .. && rm -rf restbed
#build msgpack from source
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-2.1.5/msgpack-2.1.5.tar.gz \
&& tar -xzf msgpack-2.1.5.tar.gz \
&& cd msgpack-2.1.5 && mkdir build && cd build \
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
&& make -j8 && make install \
&& cd ../.. && rm -rf msgpack-2.1.5 msgpack-2.1.5.tar.gz
+1 -3
View File
@@ -3,13 +3,11 @@ MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
RUN apt-get update && apt-get install -y \
apt-transport-https build-essential pkg-config git wget libncurses5-dev libreadline-dev nettle-dev \
apt-transport-https build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev \
&& apt-get clean
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
# libasio-dev (1.10) is too old
RUN echo "** Building a recent version of asio ***" \
&& wget https://github.com/aberaud/asio/archive/a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz \
+46 -12
View File
@@ -1,28 +1,62 @@
FROM ubuntu:20.04
FROM ubuntu:16.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update \
&& apt-get install -y llvm llvm-dev clang make cmake pkg-config git wget libncurses5-dev libreadline-dev \
&& 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 cython3 python3-dev \
python3-setuptools libcppunit-dev python3-pip \
autotools-dev autoconf libssl-dev libargon2-dev \
libfmt-dev libhttp-parser-dev libasio-dev \
autotools-dev autoconf libssl-dev \
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
ENV CC cc
ENV CXX c++
RUN echo "*** Installing libfmt ***" \
&& wget https://github.com/fmtlib/fmt/archive/5.3.0.tar.gz \
&& tar -xzf 5.3.0.tar.gz && cd fmt-5.3.0/ \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=On -DFMT_TEST=Off -DFMT_DOC=Off . \
&& make -j8 && make install \
&& cd ../ && rm -rf fmt*
# libhttp-parser-dev is 2.1-2 which is too old
RUN echo "*** Building nodejs/http_parser dependency ***" \
&& wget https://github.com/nodejs/http-parser/archive/v2.9.2.tar.gz \
&& tar xvf v2.9.2.tar.gz && cd http-parser-2.9.2/ \
&& PREFIX=/usr make -j8 install \
&& cd ../ && rm -rf http-parser*
# libasio-dev (1.10.6-3) is too old
RUN echo "** Building a recent version of asio ***" \
&& wget https://github.com/aberaud/asio/archive/a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz \
&& tar -xvf a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571.tar.gz && cd asio-a7d66ef4017d8f1b7f2cef1bb4ba8e23b0961571/asio \
&& ./autogen.sh && ./configure --prefix=/usr --without-boost --disable-examples --disable-tests \
&& make install \
&& cd ../../ && rm -rf asio*
#patch for https://github.com/Stiffstream/restinio-conan-example/issues/2
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/2c0b6f5e5ba04d7a74e8406a3df1fd433680599d.tar.gz \
&& ls -l && tar -xzf 2c0b6f5e5ba04d7a74e8406a3df1fd433680599d.tar.gz \
&& cd restinio-2c0b6f5e5ba04d7a74e8406a3df1fd433680599d/dev \
&& wget https://github.com/aberaud/restinio/archive/a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
&& ls -l && tar -xzf a7a10e419d9089c5b8ee63f5e3098c892f22fae4.tar.gz \
&& cd restinio-a7a10e419d9089c5b8ee63f5e3098c892f22fae4/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
&& make -j8 && make install \
&& cd ../../ && rm -rf restinio*
# build restbed from sources
RUN git clone --recursive https://github.com/corvusoft/restbed.git \
&& cd restbed && mkdir build && cd build \
&& cmake -DBUILD_TESTS=NO -DBUILD_EXAMPLES=NO -DBUILD_SSL=NO -DBUILD_SHARED=YES -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_LIBDIR=lib .. \
&& make -j8 install \
&& cd .. && rm -rf restbed
#build msgpack from source
RUN wget https://github.com/msgpack/msgpack-c/releases/download/cpp-2.1.5/msgpack-2.1.5.tar.gz \
&& tar -xzf msgpack-2.1.5.tar.gz \
&& cd msgpack-2.1.5 && mkdir build && cd build \
&& cmake -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF -DCMAKE_INSTALL_PREFIX=/usr .. \
&& make -j8 && make install \
&& cd ../.. && rm -rf msgpack-2.1.5 msgpack-2.1.5.tar.gz
-6
View File
@@ -1,6 +0,0 @@
FROM aberaud/opendht-deps-llvm
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+1 -3
View File
@@ -1,8 +1,6 @@
FROM aberaud/opendht-deps-bionic
FROM aberaud/opendht-deps
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
COPY . /root/opendht
RUN cd /root/opendht && mkdir build && cd build \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_C=On -DOPENDHT_LTO=On -DOPENDHT_TESTS=ON .. \
+22 -11
View File
@@ -58,8 +58,8 @@ struct OPENDHT_PUBLIC NodeStats {
cached_nodes {0},
incoming_nodes {0};
unsigned table_depth {0};
unsigned cachedNodes {0};
unsigned searches {0};
unsigned node_cache_size {0};
unsigned getKnownNodes() const { return good_nodes + dubious_nodes; }
unsigned long getNetworkSizeEstimation() const { return 8 * std::exp2(table_depth); }
std::string toString() const;
@@ -73,7 +73,25 @@ struct OPENDHT_PUBLIC NodeStats {
explicit NodeStats(const Json::Value& v);
#endif
MSGPACK_DEFINE_MAP(good_nodes, dubious_nodes, cached_nodes, incoming_nodes, table_depth, searches, node_cache_size)
MSGPACK_DEFINE_MAP(good_nodes, dubious_nodes, cached_nodes, incoming_nodes, table_depth, searches)
};
struct OPENDHT_PUBLIC NodeMetrics {
size_t scheduler_size {0};
size_t node_cache_size {0};
size_t request_count {0};
size_t rate_limiter_size {0};
size_t reported_addr_num {0};
size_t store_size {0};
size_t store_values {0};
size_t store_quota_size {0};
#ifdef OPENDHT_JSONCPP
/**
* Build a json object from a NodeStats
*/
Json::Value toJson() const;
#endif
};
struct OPENDHT_PUBLIC NodeInfo {
@@ -82,8 +100,7 @@ struct OPENDHT_PUBLIC NodeInfo {
NodeStats ipv4 {};
NodeStats ipv6 {};
size_t ongoing_ops {0};
in_port_t bound4 {0};
in_port_t bound6 {0};
NodeMetrics metrics {};
#ifdef OPENDHT_JSONCPP
/**
@@ -120,18 +137,12 @@ struct OPENDHT_PUBLIC Config {
/** If set, the dht will load its state from this file on start and save its state in this file on shutdown */
std::string persist_path {};
/** If non-0, overrides the default global rate-limit. -1 means no limit. */
/** If non-0, overrides the default global rate-limit.-1 means no limit. */
ssize_t max_req_per_sec {0};
/** If non-0, overrides the default per-IP address rate-limit. -1 means no limit. */
ssize_t max_peer_req_per_sec {0};
/* If non-0, overrides the default maximum number of searches. -1 means no limit. */
ssize_t max_searches {0};
/* If non-0, overrides the default maximum store size. -1 means no limit. */
ssize_t max_store_size {0};
/**
* Use appropriate bahavior for a public IP, stable node:
* - No connectivity change triggered when a search fails
+1 -42
View File
@@ -1,7 +1,6 @@
/*
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,7 +26,6 @@ extern "C" {
#include <gnutls/gnutls.h>
#include <gnutls/abstract.h>
#include <gnutls/x509.h>
#include <gnutls/ocsp.h>
}
#include <vector>
@@ -198,6 +196,7 @@ private:
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
};
class OPENDHT_PUBLIC RevocationList
{
using clock = std::chrono::system_clock;
@@ -310,36 +309,6 @@ private:
gnutls_x509_crq_t request {nullptr};
};
class OPENDHT_PUBLIC OcspResponse
{
public:
OcspResponse(const uint8_t* dat_ptr, size_t dat_size);
~OcspResponse();
Blob pack() const;
/*
* Get OCSP Response in readable format.
*/
std::string toString(const bool compact = true) const;
/*
* Get OCSP response certificate status.
* Return certificate status.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-cert-status-t
*/
gnutls_ocsp_cert_status_t getCertificateStatus() const;
/*
* Verify OCSP response.
* Return OCSP verify reason.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-verify-reason-t
*/
gnutls_ocsp_verify_reason_t verifyDirect(const Certificate& crt, const Blob& nonce);
private:
gnutls_ocsp_resp_t response;
};
struct OPENDHT_PUBLIC Certificate {
Certificate() noexcept {}
@@ -465,8 +434,6 @@ struct OPENDHT_PUBLIC Certificate {
/** Same as getPublicKey().getLongId() */
PkId getLongId() const;
Blob getSerialNumber() const;
/** Read certificate Common Name (CN) */
std::string getName() const;
@@ -560,16 +527,8 @@ struct OPENDHT_PUBLIC Certificate {
gnutls_digest_algorithm_t getPreferredDigest() const;
/*
* Generate OCSP request.
* Return GnuTLS error code.
* https://www.gnutls.org/manual/html_node/Error-codes.html
*/
std::pair<Blob,Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
gnutls_x509_crt_t cert {nullptr};
std::shared_ptr<Certificate> issuer {};
std::shared_ptr<OcspResponse> ocspResponse;
private:
Certificate(const Certificate&) = delete;
Certificate& operator=(const Certificate&) = delete;
+21 -48
View File
@@ -80,14 +80,10 @@ public:
*/
inline const InfoHash& getNodeId() const override { return myid; }
NodeStatus updateStatus(sa_family_t af) override;
/**
* Get the current status of the node for the given family.
*/
NodeStatus getStatus(sa_family_t af) const override {
return dht(af).status;
}
NodeStatus getStatus(sa_family_t af) const override;
NodeStatus getStatus() const override {
return std::max(getStatus(AF_INET), getStatus(AF_INET6));
@@ -115,15 +111,6 @@ public:
return types.getType(type_id);
}
void addBootstrap(const std::string& host, const std::string& service) override {
bootstrap_nodes.emplace_back(host, service);
onDisconnected();
}
void clearBootstrap() override {
bootstrap_nodes.clear();
}
/**
* Insert a node in the main routing table.
* The node is not pinged, so this should be
@@ -286,6 +273,7 @@ public:
void loadState(const std::string& path);
NodeStats getNodesStats(sa_family_t af) const override;
NodeMetrics getNodeMetrics() const override;
std::string getStorageLog() const override;
std::string getStorageLog(const InfoHash&) const override;
@@ -343,10 +331,10 @@ private:
static constexpr unsigned LISTEN_NODES {4};
/* The maximum number of hashes we're willing to track. */
static constexpr unsigned MAX_HASHES {1024 * 1024};
static constexpr unsigned MAX_HASHES {64 * 1024};
/* The maximum number of searches we keep data about. */
static constexpr unsigned MAX_SEARCHES {1024 * 1024};
static constexpr unsigned MAX_SEARCHES {64 * 1024};
static constexpr std::chrono::minutes MAX_STORAGE_MAINTENANCE_EXPIRE_TIME {10};
@@ -371,8 +359,6 @@ private:
Dht(const Dht&) = delete;
Dht& operator=(const Dht&) = delete;
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
InfoHash myid {};
uint64_t secret {};
@@ -381,39 +367,27 @@ private:
// registred types
TypeStore types;
using SearchMap = std::map<InfoHash, Sp<Search>>;
struct Kad {
RoutingTable buckets {};
SearchMap searches {};
unsigned pending_pings {0};
NodeStatus status;
NodeStatus getStatus(time_point now) const;
NodeStats getNodesStats(time_point now, const InfoHash& myid) const;
};
Kad dht4 {};
Kad dht6 {};
std::vector<std::pair<std::string,std::string>> bootstrap_nodes {};
std::chrono::steady_clock::duration bootstrap_period {std::chrono::seconds(10)};
Sp<Scheduler::Job> bootstrapJob {};
// the stuff
RoutingTable buckets4 {};
RoutingTable buckets6 {};
std::map<InfoHash, Storage> store;
std::map<SockAddr, StorageBucket, SockAddr::ipCmp> store_quota;
size_t total_values {0};
size_t total_store_size {0};
size_t max_store_keys {MAX_HASHES};
size_t max_store_size {DEFAULT_STORAGE_LIMIT};
size_t max_searches {MAX_SEARCHES};
size_t search_id {0};
using SearchMap = std::map<InfoHash, Sp<Search>>;
SearchMap searches4 {};
SearchMap searches6 {};
uint16_t search_id {0};
// map a global listen token to IPv4, IPv6 specific listen tokens.
// 0 is the invalid token.
std::map<size_t, std::tuple<size_t, size_t, size_t>> listeners {};
size_t listener_token {1};
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
// timing
Scheduler scheduler;
@@ -421,6 +395,9 @@ private:
Sp<Scheduler::Job> nextStorageMaintenance {};
net::NetworkEngine network_engine;
unsigned pending_pings4 {0};
unsigned pending_pings6 {0};
using ReportedAddr = std::pair<unsigned, SockAddr>;
std::vector<ReportedAddr> reported_addr;
@@ -446,7 +423,7 @@ private:
void reportedAddr(const SockAddr&);
// Storage
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {}, int version = 0);
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {});
bool storageStore(const InfoHash& id, const Sp<Value>& value, time_point created, const SockAddr& sa = {}, bool permanent = false);
bool storageErase(const InfoHash& id, Value::Id vid);
bool storageRefresh(const InfoHash& id, Value::Id vid);
@@ -466,10 +443,8 @@ private:
size_t maintainStorage(decltype(store)::value_type&, bool force=false, const DoneCallback& donecb={});
// Buckets
Kad& dht(sa_family_t af) { return af == AF_INET ? dht4 : dht6; }
const Kad& dht(sa_family_t af) const { return af == AF_INET ? dht4 : dht6; }
RoutingTable& buckets(sa_family_t af) { return dht(af).buckets; }
const RoutingTable& buckets(sa_family_t af) const { return dht(af).buckets; }
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) {
auto& b = buckets(af);
auto it = b.findBucket(id);
@@ -491,8 +466,8 @@ private:
// Searches
inline SearchMap& searches(sa_family_t af) { return dht(af).searches; }
inline const SearchMap& searches(sa_family_t af) const { return dht(af).searches; }
inline SearchMap& searches(sa_family_t af) { return af == AF_INET ? searches4 : searches6; }
inline const SearchMap& searches(sa_family_t af) const { return af == AF_INET ? searches4 : searches6; }
/**
* Low-level method that will perform a search on the DHT for the specified
@@ -515,7 +490,6 @@ private:
void confirmNodes();
void expire();
void onDisconnected();
/**
* Generic function to execute when a 'get' request has completed.
@@ -601,8 +575,7 @@ private:
const InfoHash& hash,
const Blob& token,
size_t socket_id,
const Query& query,
int version = 0);
const Query& query);
void onListenDone(const Sp<Node>& status,
net::RequestAnswer& a,
Sp<Search>& sr);
+1 -4
View File
@@ -42,7 +42,6 @@ public:
/**
* Get the current status of the node for the given family.
*/
virtual NodeStatus updateStatus(sa_family_t af) { return getStatus(af); };
virtual NodeStatus getStatus(sa_family_t af) const = 0;
virtual NodeStatus getStatus() const = 0;
@@ -70,9 +69,6 @@ public:
virtual const ValueType& getType(ValueType::Id type_id) const = 0;
virtual void addBootstrap(const std::string& /*host*/, const std::string& /*service*/) {};
virtual void clearBootstrap() {};
/**
* Insert a node in the main routing table.
* The node is not pinged, so this should be
@@ -198,6 +194,7 @@ public:
virtual void importValues(const std::vector<ValuesExport>&) = 0;
virtual NodeStats getNodesStats(sa_family_t af) const = 0;
virtual NodeMetrics getNodeMetrics() const { return {}; }
virtual std::string getStorageLog() const = 0;
virtual std::string getStorageLog(const InfoHash&) const = 0;
+3 -2
View File
@@ -264,10 +264,11 @@ public:
std::vector<unsigned> getNodeMessageStats(bool) override { return {}; }
void setStorageLimit(size_t) override {}
void connectivityChanged(sa_family_t) override {
getProxyInfos();
restartListeners();
}
void connectivityChanged() override {
getProxyInfos();
restartListeners();
loopSignal_();
}
@@ -384,7 +385,7 @@ private:
/**
* Relaunch LISTEN requests if the client disconnect/reconnect.
*/
void restartListeners(const asio::error_code &ec);
void restartListeners();
/**
* Refresh a listen via a token
+8 -77
View File
@@ -36,15 +36,6 @@
#include <memory>
#include <mutex>
namespace dht {
enum class PushType {
None = 0,
Android,
iOS
};
}
MSGPACK_ADD_ENUM(dht::PushType)
namespace http {
class Request;
struct ListenerSession;
@@ -61,13 +52,6 @@ class DhtRunner;
using RestRouter = restinio::router::express_router_t<>;
using RequestStatus = restinio::request_handling_status_t;
struct ProxyServerConfig {
in_port_t port {8000};
std::string pushServer {};
std::string persistStatePath {};
dht::crypto::Identity identity {};
};
/**
* Describes the REST API
*/
@@ -82,9 +66,10 @@ public:
* @note if the server fails to start (if port is already used or reserved),
* it will fails silently
*/
DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
const ProxyServerConfig& config = {},
const std::shared_ptr<dht::Logger>& logger = {});
DhtProxyServer(
dht::crypto::Identity identity,
std::shared_ptr<DhtRunner> dht, in_port_t port = 8000, const std::string& pushServer = "",
std::shared_ptr<dht::Logger> logger = {});
virtual ~DhtProxyServer();
@@ -98,10 +83,8 @@ public:
struct ServerStats {
/** Current number of listen operations */
size_t listenCount {0};
/** Current number of permanent put operations (hash used) */
/** Current number of permanent put operations */
size_t putCount {0};
/** Current number of permanent put values */
size_t totalPermanentPuts {0};
/** Current number of push tokens with at least one listen operation */
size_t pushListenersCount {0};
/** Average requests per second */
@@ -131,7 +114,6 @@ public:
Json::Value result;
result["listenCount"] = static_cast<Json::UInt64>(listenCount);
result["putCount"] = static_cast<Json::UInt64>(putCount);
result["totalPermanentPuts"] = static_cast<Json::UInt64>(totalPermanentPuts);
result["pushListenersCount"] = static_cast<Json::UInt64>(pushListenersCount);
result["requestRate"] = requestRate;
if (nodeInfo)
@@ -300,17 +282,17 @@ private:
* @param key of the device
* @param json, the content to send
*/
void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority);
void sendPushNotification(const std::string& key, Json::Value&& json, bool isAndroid, bool highPriority);
/**
* Send push notification with an expire timeout.
* @param ec
* @param pushToken
* @param json
* @param type
* @param isAndroid
*/
void handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
std::function<Json::Value()> json, PushType type);
std::function<Json::Value()> json, const bool isAndroid);
/**
* Remove a push listener between a client and a hash
@@ -327,12 +309,6 @@ private:
void handlePrintStats(const asio::error_code &ec);
void updateStats();
template <typename Os>
void saveState(Os& stream);
template <typename Is>
void loadState(Is& is, size_t size);
using clock = std::chrono::steady_clock;
using time_point = clock::time_point;
@@ -340,9 +316,6 @@ private:
std::shared_ptr<DhtRunner> dht_;
Json::StreamWriterBuilder jsonBuilder_;
Json::CharReaderBuilder jsonReaderBuilder_;
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
std::string persistPath_;
// http server
std::thread serverThread_;
@@ -371,7 +344,6 @@ private:
struct PushSessionContext {
std::mutex lock;
std::string sessionId;
PushSessionContext(const std::string& id) : sessionId(id) {}
};
struct PermanentPut {
time_point expiration;
@@ -381,32 +353,9 @@ private:
std::unique_ptr<asio::steady_timer> expireTimer;
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
Sp<Value> value;
PushType type;
template <typename Packer>
void msgpack_pack(Packer& p) const
{
p.pack_map(2 + (sessionCtx ? 1 : 0) + (clientId.empty() ? 0 : 1) + (type == PushType::None ? 0 : 2));
p.pack("value"); p.pack(value);
p.pack("exp"); p.pack(to_time_t(expiration));
if (not clientId.empty()) {
p.pack("cid"); p.pack(clientId);
}
if (sessionCtx) {
std::lock_guard<std::mutex> l(sessionCtx->lock);
p.pack("sid"); p.pack(sessionCtx->sessionId);
}
if (type != PushType::None) {
p.pack("t"); p.pack(type);
p.pack("token"); p.pack(pushToken);
}
}
void msgpack_unpack(const msgpack::object& o);
};
struct SearchPuts {
std::map<dht::Value::Id, PermanentPut> puts;
MSGPACK_DEFINE_ARRAY(puts)
};
std::mutex lockSearchPuts_;
std::map<InfoHash, SearchPuts> puts_;
@@ -418,32 +367,14 @@ private:
#ifdef OPENDHT_PUSH_NOTIFICATIONS
struct Listener {
time_point expiration;
std::string clientId;
std::shared_ptr<PushSessionContext> sessionCtx;
std::future<size_t> internalToken;
std::unique_ptr<asio::steady_timer> expireTimer;
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
PushType type;
template <typename Packer>
void msgpack_pack(Packer& p) const
{
p.pack_map(sessionCtx ? 4 : 3);
p.pack("cid"); p.pack(clientId);
p.pack("exp"); p.pack(to_time_t(expiration));
if (sessionCtx) {
std::lock_guard<std::mutex> l(sessionCtx->lock);
p.pack("sid"); p.pack(sessionCtx->sessionId);
}
p.pack("t"); p.pack(type);
}
void msgpack_unpack(const msgpack::object& o);
};
struct PushListener {
std::map<InfoHash, std::vector<Listener>> listeners;
MSGPACK_DEFINE_ARRAY(listeners)
};
std::mutex lockPushListeners_;
std::map<std::string, PushListener> pushListeners_;
+18 -1
View File
@@ -389,7 +389,7 @@ 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(SockAddr& local4, SockAddr& local6, const Config& config, Context&& context = {});
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).
@@ -459,6 +459,14 @@ private:
Stopping
};
/**
* Will try to resolve the list of hostnames `bootstrap_nodes` on seperate
* thread and then queue ping requests. This list should contain reliable
* nodes so that the DHT node can recover quickly from losing connection
* with the network.
*/
void tryBootstrapContinuously();
time_point loop_();
NodeStatus getStatus() const {
@@ -505,6 +513,15 @@ private:
net::PacketList rcv {};
decltype(rcv) rcv_free {};
/** true if currently actively boostraping */
std::atomic_bool bootstraping {false};
/* bootstrap nodes given as (host, service) pairs */
std::vector<std::pair<std::string,std::string>> bootstrap_nodes_all {};
std::vector<std::pair<std::string,std::string>> bootstrap_nodes {};
std::thread bootstrap_thread {};
std::mutex bootstrap_mtx {};
std::condition_variable bootstrap_cv {};
std::queue<std::function<void(SecureDht&)>> pending_ops_prio {};
std::queue<std::function<void(SecureDht&)>> pending_ops {};
std::mutex storage_mtx {};
+7 -16
View File
@@ -72,17 +72,15 @@ using socket_t = asio::ip::tcp::socket;
class OPENDHT_PUBLIC Url
{
public:
Url() = default;
Url(){};
Url(const std::string& url);
std::string url;
std::string protocol {"http"};
std::string host;
std::string service;
std::string target;
std::string service {"80"};
std::string target {"/"};
std::string query;
std::string fragment;
std::string toString() const;
};
class OPENDHT_PUBLIC Connection : public std::enable_shared_from_this<Connection>
@@ -97,7 +95,7 @@ public:
bool is_open() const;
bool is_ssl() const;
void set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode);
void set_ssl_verification(const asio::ip::tcp::endpoint& endpoint, const asio::ssl::verify_mode verify_mode);
asio::streambuf& input();
std::istream& data() { return istream_; }
@@ -228,15 +226,12 @@ public:
using OnStatusCb = std::function<void(unsigned status_code)>;
using OnDataCb = std::function<void(const char* at, size_t length)>;
using OnStateChangeCb = std::function<void(State state, const Response& response)>;
using OnJsonCb = std::function<void(Json::Value value, const Response& response)>;
using OnJsonCb = std::function<void(Json::Value value, unsigned status_code)>;
using OnDoneCb = std::function<void(const Response& response)>;
// resolves implicitly
Request(asio::io_context& ctx, const std::string& url, const Json::Value& json, OnJsonCb jsoncb,
std::shared_ptr<dht::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb,
std::shared_ptr<dht::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& host, const std::string& service,
const bool ssl = false, std::shared_ptr<dht::Logger> logger = {});
@@ -290,14 +285,10 @@ public:
void send();
/** Send and block for response */
const Response& await();
/**
* User action to cancel the Request and call the completion callbacks.
*/
void cancel();
void terminate(const asio::error_code& ec);
private:
using OnCompleteCb = std::function<void()>;
@@ -310,8 +301,6 @@ private:
OnStateChangeCb on_state_change;
};
static std::string getRelativePath(const Url& origin, const std::string& path);
void notify_state_change(State state);
void build();
@@ -324,6 +313,8 @@ private:
void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
void terminate(const asio::error_code& ec);
void post();
void handle_request(const asio::error_code& ec);
-16
View File
@@ -237,9 +237,6 @@ public:
static Hash getRandom();
template <typename Rd>
static Hash getRandom(Rd&);
template <size_t M>
OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Hash<M>& h);
@@ -327,19 +324,6 @@ Hash<N>::getRandom()
return h;
}
template <size_t N>
template <typename Rd>
Hash<N>
Hash<N>::getRandom(Rd& rdev)
{
Hash h;
std::uniform_int_distribution<uint32_t> rand_int;
auto a = reinterpret_cast<uint32_t*>(h.data());
auto b = reinterpret_cast<uint32_t*>(h.data() + h.size());
std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
return h;
}
struct HexMap : public std::array<std::array<char, 2>, 256> {
HexMap() {
for (size_t i=0; i<size(); i++) {
+3 -3
View File
@@ -82,13 +82,13 @@ private:
};
struct Logger {
LogMethod ERR = {};
LogMethod WARN = {};
LogMethod DBG = {};
LogMethod WARN = {};
LogMethod ERR = {};
Logger() = default;
Logger(LogMethod&& err, LogMethod&& warn, LogMethod&& dbg)
: ERR(std::move(err)), WARN(std::move(warn)), DBG(std::move(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_);
+20 -43
View File
@@ -180,8 +180,7 @@ private:
const InfoHash&,
const Blob&,
Tid,
const Query&,
int)> onListen {};
const Query&)> onListen {};
/**
* Called on announce request.
*
@@ -211,7 +210,6 @@ private:
public:
using RequestCb = std::function<void(const Request&, RequestAnswer&&)>;
using RequestErrorCb = std::function<bool(const Request&, DhtProtocolException&&)>;
using RequestExpiredCb = std::function<void(const Request&, bool)>;
NetworkEngine(const Sp<Logger>& log, std::mt19937_64& rd, Scheduler& scheduler, std::unique_ptr<DatagramSocket>&& sock);
@@ -239,10 +237,9 @@ public:
void clear();
/**
* Sends values (with closest nodes) to a listener.
* Sends values (with closest nodes) to a listenner.
*
* @deprecated
* @param sa The address of the listener.
* @param sa The address of the listenner.
* @param sslen The length of the sockaddr structure.
* @param socket_id The tid to use to write to the request socket.
* @param hash The hash key of the value.
@@ -251,14 +248,13 @@ public:
* @param nodes The ipv4 closest nodes.
* @param nodes6 The ipv6 closest nodes.
* @param values The values to send.
* @param version If version = 1, a request will be used to answer to the listener
*/
void tellListener(Sp<Node> n, Tid socket_id, const InfoHash& hash, want_t want, const Blob& ntoken,
std::vector<Sp<Node>>&& nodes, std::vector<Sp<Node>>&& nodes6,
std::vector<Sp<Value>>&& values, const Query& q, int version);
std::vector<Sp<Value>>&& values, const Query& q);
void tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
void tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values);
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values);
bool isRunning(sa_family_t af) const;
inline want_t want () const { return dht_socket->hasIPv4() and dht_socket->hasIPv6() ? (WANT4 | WANT6) : -1; }
@@ -280,7 +276,7 @@ public:
*/
Sp<Request>
sendPing(Sp<Node> n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
/**
* Send a "ping" request to a given node.
*
@@ -297,7 +293,7 @@ public:
std::forward<RequestCb>(on_done),
std::forward<RequestExpiredCb>(on_expired));
}
/**
* Send a "find node" request to a given node.
*
@@ -362,9 +358,10 @@ public:
const InfoHash& hash,
const Query& query,
const Blob& token,
Tid socketId,
Sp<Request> previous,
RequestCb&& on_done,
RequestExpiredCb&& on_expired);
RequestExpiredCb&& on_expired,
SocketCb&& socket_cb);
/**
* Send a "announce" request to a given node.
*
@@ -403,26 +400,7 @@ public:
const Value::Id& vid,
const Blob& token,
RequestCb&& on_done,
RequestErrorCb&& on_error,
RequestExpiredCb&& on_expired);
/**
* Send a "update" request to a given node. Used for Listen operations
*
* @param n The node.
* @param hash The target hash.
* @param values The values.
* @param created Time id.
* @param token A security token.
* @param sid The socket id.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendUpdateValues(Sp<Node> n,
const InfoHash& infohash,
const std::vector<Sp<Value>>& values,
time_point created,
const Blob& token,
const size_t& sid);
/**
* Parses a message and calls appropriate callbacks.
@@ -435,8 +413,8 @@ public:
*/
void processMessage(const uint8_t *buf, size_t buflen, SockAddr addr);
Sp<Node> insertNode(const InfoHash& id, const SockAddr& addr) {
auto n = cache.getNode(id, addr, scheduler.time(), 0);
Sp<Node> insertNode(const InfoHash& myid, const SockAddr& addr) {
auto n = cache.getNode(myid, addr, scheduler.time(), 0);
onNewNode(n, 0);
return n;
}
@@ -512,20 +490,19 @@ private:
void sendRequest(const Sp<Request>& request);
struct MessageStats {
unsigned ping {0};
unsigned find {0};
unsigned get {0};
unsigned put {0};
unsigned listen {0};
unsigned refresh {0};
unsigned updateValue {0};
unsigned ping {0};
unsigned find {0};
unsigned get {0};
unsigned put {0};
unsigned listen {0};
unsigned refresh {0};
};
// basic wrapper for socket sendto function
int send(const SockAddr& addr, const char *buf, size_t len, bool confirmed = false);
void sendValueParts(Tid tid, const std::vector<Blob>& svals, const SockAddr& addr);
void sendValueParts(const TransId& tid, const std::vector<Blob>& svals, const SockAddr& addr);
std::vector<Blob> packValueHeader(msgpack::sbuffer&, const std::vector<Sp<Value>>&);
void maintainRxBuffer(Tid tid);
-8
View File
@@ -61,9 +61,6 @@ using PacketList = std::list<ReceivedPacket>;
class OPENDHT_PUBLIC DatagramSocket {
public:
/** A function that takes a list of new received packets and
* optionally returns consumed packets for recycling.
**/
using OnReceive = std::function<PacketList(PacketList&& packets)>;
virtual ~DatagramSocket() {};
@@ -88,11 +85,6 @@ public:
virtual const SockAddr& getBoundRef(sa_family_t family = AF_UNSPEC) const = 0;
/** Virtual resolver mothod allows to implement custom resolver */
virtual std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {}) {
return SockAddr::resolve(host, service);
}
virtual void stop() = 0;
protected:
+5 -14
View File
@@ -21,8 +21,6 @@
#include <random>
#include <algorithm>
#include <functional>
#include <thread>
#include <stdexcept>
namespace dht {
namespace crypto {
@@ -113,18 +111,11 @@ using random_device = std::random_device;
template<class T = std::mt19937, std::size_t N = T::state_size>
auto getSeededRandomEngine () -> typename std::enable_if<!!N, T>::type {
typename T::result_type random_data[N];
for (unsigned i=0; i<256; i++) {
try {
random_device source;
std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
std::seed_seq seeds(std::begin(random_data), std::end(random_data));
T seededEngine (seeds);
return seededEngine;
} catch (...) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
throw std::runtime_error("Can't seed random engine");
random_device source;
std::generate(std::begin(random_data), std::end(random_data), std::ref(source));
std::seed_seq seeds(std::begin(random_data), std::end(random_data));
T seededEngine (seeds);
return seededEngine;
}
}} // dht::crypto
+2
View File
@@ -115,6 +115,8 @@ public:
inline time_point syncTime() { return (now = clock::now()); }
inline void syncTime(const time_point& n) { now = n; }
inline size_t size() const { return timers.size(); }
private:
time_point now {clock::now()};
std::multimap<time_point, Sp<Job>> timers {}; /* the jobs ordered by time */
+3 -9
View File
@@ -180,6 +180,9 @@ public:
NodeStats getNodesStats(sa_family_t af) const override {
return dht_->getNodesStats(af);
}
NodeMetrics getNodeMetrics() const override {
return dht_->getNodeMetrics();
}
std::vector<unsigned> getNodeMessageStats(bool in = false) override {
return dht_->getNodeMessageStats(in);
}
@@ -201,9 +204,6 @@ public:
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
return dht_->periodic(buf, buflen, from, fromlen, now);
}
NodeStatus updateStatus(sa_family_t af) override {
return dht_->updateStatus(af);
}
NodeStatus getStatus(sa_family_t af) const override {
return dht_->getStatus(af);
}
@@ -219,12 +219,6 @@ public:
const ValueType& getType(ValueType::Id type_id) const override {
return dht_->getType(type_id);
}
void addBootstrap(const std::string& host, const std::string& service) override {
dht_->addBootstrap(host, service);
}
void clearBootstrap() override {
dht_->clearBootstrap();
}
void insertNode(const InfoHash& id, const SockAddr& sa) override {
dht_->insertNode(id, sa);
}
+4 -9
View File
@@ -105,7 +105,8 @@ static std::string
print_duration(DT d) {
if (d < std::chrono::seconds(0)) {
return "-" + print_duration(-d);
} else if (d < std::chrono::milliseconds(1)) {
}
if (d < std::chrono::milliseconds(1)) {
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count()) + " us";
} else if (d < std::chrono::seconds(1)) {
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
@@ -173,13 +174,7 @@ unpackMsg(Blob b) {
msgpack::unpacked unpackMsg(Blob b);
msgpack::object* findMapValue(const msgpack::object& map, const char* key, size_t length);
inline msgpack::object* findMapValue(const msgpack::object& map, const char* key) {
return findMapValue(map, key, strlen(key));
}
inline msgpack::object* findMapValue(const msgpack::object& map, const std::string& key) {
return findMapValue(map, key.c_str(), key.size());
}
msgpack::object* findMapValue(const msgpack::object& map, const char* key);
msgpack::object* findMapValue(const msgpack::object& map, const std::string& key);
} // namespace dht
+3 -3
View File
@@ -3,9 +3,9 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenDHT
Description: C++14 Distributed Hash Table library
Description: C++ Distributed Hash Table library
Version: @VERSION@
Libs: -L${libdir} -lopendht
Libs.private: @http_parser_lib@ -pthread
Requires.private: gnutls >= 3.3, nettle >= 2.4@argon2_lib@@jsoncpp_lib@@openssl_lib@
Libs.private: -lpthread
Requires.private: gnutls >= 3.1@argon2_lib@
Cflags: -I${includedir}
+26 -11
View File
@@ -21,7 +21,6 @@ from math import cos, sin, pi
import urllib3
import gzip
import queue
from geoip import geolite2
sys.path.append('..')
from opendht import *
@@ -56,7 +55,7 @@ plt.ion()
plt.figaspect(2.)
fig, axes = plt.subplots(2, 1)
#fig.set_size_inches(8,16,forward=True)
fig.set_size_inches(8,16,forward=True)
fig.tight_layout()
fig.canvas.set_window_title('OpenDHT scanner')
@@ -91,12 +90,27 @@ def exitcb(arg):
run = False
exitbtn.on_clicked(exitcb)
def check_dl(fname, url):
if os.path.isfile(fname):
return
print('downloading', url)
ghandle = gzip.GzipFile(fileobj=http.request('GET', url, headers={'User-Agent': 'Mozilla/5.0'}, preload_content=False))
with open(fname, 'wb') as out:
for line in ghandle:
out.write(line)
check_dl("GeoLiteCity.dat", "http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz")
check_dl("GeoLiteCityv6.dat", "http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz")
gi = GeoIP.open("GeoLiteCity.dat", GeoIP.GEOIP_INDEX_CACHE | GeoIP.GEOIP_CHECK_CACHE)
gi6 = GeoIP.open("GeoLiteCityv6.dat", GeoIP.GEOIP_INDEX_CACHE | GeoIP.GEOIP_CHECK_CACHE)
def gcb(v):
return True
r = DhtRunner()
r.run(port=4112)
r.bootstrap("bootstrap.jami.net", "4222")
r.bootstrap("bootstrap.ring.cx", "4222")
plt.pause(1)
@@ -129,9 +143,9 @@ def nextstep(cur_h, cur_depth, ok, nodes):
depth = min(8, commonBits+6)
if cur_depth < depth:
for b in range(cur_depth, depth):
new_h = InfoHash(cur_h.toString())
new_h.setBit(b, 1)
step(new_h, b+1)
new_h = InfoHash(cur_h.toString());
new_h.setBit(b, 1);
step(new_h, b+1);
else:
print("step done with no nodes", ok, cur_h.toString().decode())
done -= 1
@@ -172,22 +186,23 @@ def appendNewNode(n):
if addr in nodes_ip6s:
nodes_ip6s[addr][1] += 1
else:
georecord = geolite2.lookup(addr)
georecord = gi6.record_by_name_v6(addr)
nodes_ip6s[addr] = [n, 1, georecord]
else:
if addr in nodes_ip4s:
nodes_ip4s[addr][1] += 1
else:
georecord = geolite2.lookup(addr)
georecord = gi.record_by_name(addr)
nodes_ip4s[addr] = [n, 1, georecord]
if georecord:
appendMapPoint(georecord)
def appendMapPoint(res):
global lons, lats, cities
lons.append(res.location[1])
lats.append(res.location[0])
cities.append(res.city if res.city else (str(int(res.location[0]))+'-'+str(int(res.location[1]))))
lons.append(res['longitude'])
lats.append(res['latitude'])
cities.append(res['city'] if res['city'] else (str(int(res['latitude']))+'-'+str(int(res['longitude']))))
def restart(arg):
global collection, all_lines, all_nodes, points, done, nodes_ip4s, nodes_ip6s, lats, lons, cities, xys, colors
+16 -1
View File
@@ -94,7 +94,6 @@ NodeStats::toString() const
{
std::stringstream ss;
ss << "Known nodes: " << good_nodes << " good, " << dubious_nodes << " dubious, " << incoming_nodes << " incoming." << std::endl;
ss << searches << " searches, " << node_cache_size << " total cached nodes" << std::endl;
if (table_depth > 1) {
ss << "Routing table depth: " << table_depth << std::endl;
ss << "Network size estimation: " << getNetworkSizeEstimation() << " nodes" << std::endl;
@@ -145,6 +144,7 @@ NodeInfo::toJson() const
val["ipv4"] = ipv4.toJson();
val["ipv6"] = ipv6.toJson();
val["ops"] = Json::Value::LargestUInt(ongoing_ops);
val["metrics"] = metrics.toJson();
return val;
}
@@ -158,6 +158,21 @@ NodeInfo::NodeInfo(const Json::Value& v)
ongoing_ops = v["ops"].asLargestUInt();
}
Json::Value
NodeMetrics::toJson() const
{
Json::Value val;
val["scheduler_size"] = Json::Value::LargestUInt(scheduler_size);
val["node_cache_size"] = Json::Value::LargestUInt(node_cache_size);
val["request_count"] = Json::Value::LargestUInt(request_count);
val["rate_limiter_size"] = Json::Value::LargestUInt(rate_limiter_size);
val["reported_addr_num"] = Json::Value::LargestUInt(reported_addr_num);
val["store_size"] = Json::Value::LargestUInt(store_size);
val["store_values"] = Json::Value::LargestUInt(store_values);
val["store_quota_size"] = Json::Value::LargestUInt(store_quota_size);
return val;
}
#endif
-221
View File
@@ -1,221 +0,0 @@
/*
* Copyright (C) 2020 Savoir-faire Linux Inc.
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "os_cert.h"
#include "log_enable.h"
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")
#include <openssl/ssl.h>
#undef X509_NAME
#undef OCSP_REQUEST
#undef OCSP_RESPONSE
#endif /*WIN32*/
#ifdef __APPLE__
#include <Security/Security.h>
#endif /*__APPLE__*/
#ifdef _WIN32
#define GENTIME_LENGTH 15
#define UTCTIME_LENGTH 13
#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
// Taken from libressl/src/crypto/asn1/a_time_tm.c
/*
* Parse an RFC 5280 format ASN.1 time string.
*
* mode must be:
* 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
* V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
* V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
*
* Returns:
* -1 if the string was invalid.
* V_ASN1_UTCTIME if the string validated as a UTC time string.
* V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
*
* Fills in *tm with the corresponding time if tm is non NULL.
*/
int
ASN1_time_parse(const char* bytes, size_t len, struct tm* tm, int mode)
{
size_t i;
int type = 0;
struct tm ltm;
struct tm* lt;
const char* p;
if (bytes == NULL)
return (-1);
/* Constrain to valid lengths. */
if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH)
return (-1);
lt = tm;
if (lt == NULL) {
memset(&ltm, 0, sizeof(ltm));
lt = &ltm;
}
/* Timezone is required and must be GMT (Zulu). */
if (bytes[len - 1] != 'Z')
return (-1);
/* Make sure everything else is digits. */
for (i = 0; i < len - 1; i++) {
if (isdigit((unsigned char) bytes[i]))
continue;
return (-1);
}
/*
* Validate and convert the time
*/
p = bytes;
switch (len) {
case GENTIME_LENGTH:
if (mode == V_ASN1_UTCTIME)
return (-1);
lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
type = V_ASN1_GENERALIZEDTIME;
/* FALLTHROUGH */
case UTCTIME_LENGTH:
if (type == 0) {
if (mode == V_ASN1_GENERALIZEDTIME)
return (-1);
type = V_ASN1_UTCTIME;
}
lt->tm_year += ATOI2(p); /* yy */
if (type == V_ASN1_UTCTIME) {
if (lt->tm_year < 50)
lt->tm_year += 100;
}
lt->tm_mon = ATOI2(p) - 1; /* mm */
if (lt->tm_mon < 0 || lt->tm_mon > 11)
return (-1);
lt->tm_mday = ATOI2(p); /* dd */
if (lt->tm_mday < 1 || lt->tm_mday > 31)
return (-1);
lt->tm_hour = ATOI2(p); /* HH */
if (lt->tm_hour < 0 || lt->tm_hour > 23)
return (-1);
lt->tm_min = ATOI2(p); /* MM */
if (lt->tm_min < 0 || lt->tm_min > 59)
return (-1);
lt->tm_sec = ATOI2(p); /* SS */
/* Leap second 60 is not accepted. Reconsider later? */
if (lt->tm_sec < 0 || lt->tm_sec > 59)
return (-1);
break;
default:
return (-1);
}
return (type);
}
#endif /*_WIN32*/
namespace dht {
namespace http {
void
addSystemCaCertificates(SSL_CTX* ctx, const std::shared_ptr<Logger>& logger)
{
X509_STORE* store = SSL_CTX_get_cert_store(ctx);
if (store == nullptr) {
if (logger)
logger->e("couldn't get the context cert store");
return;
}
X509* x509cert;
#ifdef _WIN32
PCCERT_CONTEXT pContext = NULL;
HCERTSTORE hSystemStore;
hSystemStore = CertOpenSystemStore(NULL, "ROOT");
if (!hSystemStore) {
if (logger)
logger->e("couldn't open the system cert store");
return;
}
while (pContext = CertEnumCertificatesInStore(hSystemStore, pContext)) {
x509cert = nullptr;
const uint8_t* encoded_cert = pContext->pbCertEncoded;
x509cert = d2i_X509(nullptr, &encoded_cert, pContext->cbCertEncoded);
if (x509cert) {
if (X509_STORE_add_cert(store, x509cert) == 1) {
if (logger)
logger->d("local certificate added");
}
X509_free(x509cert);
}
}
CertCloseStore(hSystemStore, 0);
#elif __APPLE__
CFArrayRef result = NULL;
OSStatus osStatus;
if ((osStatus = SecTrustCopyAnchorCertificates(&result)) != 0) {
if (logger) {
CFStringRef statusString = SecCopyErrorMessageString(osStatus, NULL);
logger->d("Error enumerating certificates: %s",
CFStringGetCStringPtr(statusString, kCFStringEncodingASCII));
CFRelease(statusString);
}
if (result != NULL) {
CFRelease(result);
}
return;
}
CFDataRef rawData = NULL;
for (CFIndex i = 0; i < CFArrayGetCount(result); i++) {
x509cert = nullptr;
SecCertificateRef cert = (SecCertificateRef) CFArrayGetValueAtIndex(result, i);
rawData = SecCertificateCopyData(cert);
if (!rawData) {
if (logger)
logger->e("couldn't copy raw certificate data");
break;
}
const uint8_t* rawDataPtr = CFDataGetBytePtr(rawData);
x509cert = d2i_X509(nullptr, &rawDataPtr, CFDataGetLength(rawData));
if (x509cert) {
if (X509_STORE_add_cert(store, x509cert) == 1) {
if (logger)
logger->d("local certificate added");
}
X509_free(x509cert);
}
CFRelease(rawData);
rawData = NULL;
}
if (result != NULL) {
CFRelease(result);
}
if (rawData != NULL) {
CFRelease(rawData);
}
#endif /*__APPLE__, _WIN32*/
}
} /*namespace http*/
} /*namespace dht*/
-38
View File
@@ -1,38 +0,0 @@
/*
* Copyright (C) 2020 Savoir-faire Linux Inc.
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "log_enable.h"
#include <memory>
#include <openssl/x509.h>
#ifdef _WIN32
#define V_ASN1_UTCTIME 23
#define V_ASN1_GENERALIZEDTIME 24
#define timegm _mkgmtime
int ASN1_time_parse(const char* bytes, size_t len, struct tm* tm, int mode);
#endif /*_WIN32*/
namespace dht {
namespace http {
void addSystemCaCertificates(SSL_CTX* ctx, const std::shared_ptr<Logger>& logger);
}
} // namespace dht
-161
View File
@@ -1,7 +1,6 @@
/*
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,7 +25,6 @@ extern "C" {
#include <gnutls/x509.h>
#include <nettle/gcm.h>
#include <nettle/aes.h>
#include <gnutls/crypto.h>
#include <argon2.h>
}
@@ -877,18 +875,6 @@ Certificate::getLongId() const
#endif
}
Blob
Certificate::getSerialNumber() const
{
if (not cert)
return {};
// extract from certificate
unsigned char serial[64];
auto size = sizeof(serial);
gnutls_x509_crt_get_serial(cert, &serial, &size);
return {serial, serial + size};
}
std::string
Certificate::getName() const
{
@@ -1034,32 +1020,6 @@ Certificate::getPreferredDigest() const
return getPublicKey().getPreferredDigest();
}
std::pair<Blob,Blob>
Certificate::generateOcspRequest(gnutls_x509_crt_t& issuer)
{
gnutls_ocsp_req_t rreq;
int err = gnutls_ocsp_req_init(&rreq);
if (err < 0)
throw CryptoException(gnutls_strerror(err));
std::unique_ptr<struct gnutls_ocsp_req_int, decltype(&gnutls_ocsp_req_deinit)> req(rreq, &gnutls_ocsp_req_deinit);
err = gnutls_ocsp_req_add_cert(req.get(), GNUTLS_DIG_SHA512, issuer, cert);
if (err < 0)
throw CryptoException(gnutls_strerror(err));
Blob noncebuf(64);
gnutls_datum_t nonce = { noncebuf.data(), (unsigned)noncebuf.size() };
err = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
err = gnutls_ocsp_req_set_nonce(req.get(), 0, &nonce);
if (err < 0)
throw CryptoException(gnutls_strerror(err));
gnutls_datum_t rdata;
err = gnutls_ocsp_req_export(req.get(), &rdata);
if (err != 0)
throw CryptoException(gnutls_strerror(err));
Blob ret(rdata.data, rdata.data + rdata.size);
gnutls_free(rdata.data);
return std::make_pair<Blob,Blob>(std::move(ret), std::move(noncebuf));
}
// PrivateKey
PrivateKey
@@ -1246,127 +1206,6 @@ Certificate::getRevocationLists() const
return ret;
}
// OcspResponse
OcspResponse::OcspResponse(const uint8_t* dat_ptr, size_t dat_size)
{
int ret = gnutls_ocsp_resp_init(&response);
if (ret < 0)
throw CryptoException(gnutls_strerror(ret));
gnutls_datum_t dat = {(unsigned char*)dat_ptr,(unsigned int)dat_size};
ret = gnutls_ocsp_resp_import(response, &dat);
if (ret < 0){
gnutls_ocsp_resp_deinit(response);
throw CryptoException(gnutls_strerror(ret));
}
}
OcspResponse::~OcspResponse()
{
gnutls_ocsp_resp_deinit(response);
}
Blob
OcspResponse::pack() const
{
gnutls_datum_t dat;
int ret = gnutls_ocsp_resp_export(response, &dat);
if (ret < 0)
throw CryptoException(gnutls_strerror(ret));
return {dat.data, dat.data + dat.size};
}
std::string
OcspResponse::toString(const bool compact) const
{
int ret;
std::string str;
gnutls_datum_t dat;
ret = gnutls_ocsp_resp_print(response, compact ? GNUTLS_OCSP_PRINT_COMPACT : GNUTLS_OCSP_PRINT_FULL, &dat);
if (ret == 0)
str = std::string((const char*)dat.data, (size_t)dat.size);
gnutls_free(dat.data);
if (ret < 0)
throw CryptoException(gnutls_strerror(ret));
return str;
}
gnutls_ocsp_cert_status_t
OcspResponse::getCertificateStatus() const
{
int ret;
unsigned int status;
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status, NULL, NULL, NULL, NULL);
if (ret < 0)
throw CryptoException(gnutls_strerror(ret));
return (gnutls_ocsp_cert_status_t) status;
}
gnutls_ocsp_verify_reason_t
OcspResponse::verifyDirect(const Certificate& crt, const Blob& nonce)
{
// https://www.gnutls.org/manual/html_node/Error-codes.html
int ret = -1;
// http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-verify-reason-t
unsigned int verify = 0;
// http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-cert-status-t
unsigned int status = 6; // by default assume GNUTLS_OCSP_RESP_UNAUTHORIZED
#if GNUTLS_VERSION_NUMBER >= 0x030103
/*
* This function will check whether the OCSP response is about the provided certificate.
* index: Specifies response number to get. Use (0) to get the first one.
*/
if ((ret = gnutls_ocsp_resp_check_crt(response, 0, crt.cert)) < 0)
goto end;
#endif
/*
* Verify signature of the Basic OCSP Response against the public key in the issuer certificate.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-resp-verify-direct
*/
ret = gnutls_ocsp_resp_verify_direct(response, crt.issuer->cert /*signer*/, &verify, 0);
if (ret < 0)
goto end;
ret = gnutls_ocsp_resp_check_crt(response, 0 /*index*/, crt.cert);
if (ret < 0)
goto end;
/*
* This function will return the certificate information of the indx'ed response in the
* Basic OCSP Response resp. The information returned corresponds to the OCSP SingleResponse
* structure except the final singleExtensions.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-resp-get-single
*/
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status, NULL, NULL, NULL, NULL);
if (ret < 0)
goto end;
gnutls_datum_t rnonce;
/*
* This function will return the Basic OCSP Response nonce extension data.
*/
ret = gnutls_ocsp_resp_get_nonce(response, NULL, &rnonce);
if (ret < 0)
goto end;
// Ensure no replay attack has been done
if (rnonce.size != nonce.size() || memcmp(nonce.data(), rnonce.data, nonce.size()) != 0){
ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
goto end;
}
end:
/*
* OCSP validation outcome based on interogative aspects
*/
if (ret != GNUTLS_E_SUCCESS)
throw CryptoException(gnutls_strerror(ret));
else if (status != GNUTLS_OCSP_CERT_GOOD)
if (status == GNUTLS_OCSP_CERT_REVOKED)
throw CryptoException("Certificate was revoked");
else
throw CryptoException("Certificate is unknown");
else
return (gnutls_ocsp_verify_reason_t) verify;
}
// RevocationList
RevocationList::RevocationList()
+187 -217
View File
@@ -17,6 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "dht.h"
#include "rng.h"
#include "search.h"
@@ -42,41 +43,13 @@ constexpr duration Dht::REANNOUNCE_MARGIN;
static constexpr size_t MAX_REQUESTS_PER_SEC {8 * 1024};
NodeStatus
Dht::updateStatus(sa_family_t af)
Dht::getStatus(sa_family_t af) const
{
auto& d = dht(af);
auto old = d.status;
d.status = d.getStatus(scheduler.time());
if (d.status != old) {
auto& other = dht(af == AF_INET ? AF_INET6 : AF_INET);
if (other.status == NodeStatus::Disconnected && d.status == NodeStatus::Disconnected)
onDisconnected();
else if (other.status == NodeStatus::Connected || d.status == NodeStatus::Connected) {
// On connected
if (bootstrapJob) {
bootstrapJob->cancel();
bootstrapJob.reset();
}
bootstrap_period = std::chrono::seconds(10);
}
}
return d.status;
}
NodeStatus
Dht::Kad::getStatus(time_point now) const
{
unsigned dubious = 0;
for (const auto& b : buckets) {
for (auto& n : b.nodes) {
if (n->isGood(now)) {
return NodeStatus::Connected;
} else if (not n->isExpired())
dubious++;
}
}
auto& ping = pending_pings;
if (dubious or ping)
const auto& stats = getNodesStats(af);
if (stats.good_nodes)
return NodeStatus::Connected;
auto& ping = af == AF_INET ? pending_pings4 : pending_pings6;
if (ping or stats.getKnownNodes())
return NodeStatus::Connecting;
return NodeStatus::Disconnected;
}
@@ -245,8 +218,8 @@ Dht::expireSearches()
return b;
} else { return false; }
};
erase_if(dht4.searches, expired);
erase_if(dht6.searches, expired);
erase_if(searches4, expired);
erase_if(searches6, expired);
}
void
@@ -432,7 +405,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
{ /* when put done */
if (auto sr = ws.lock()) {
onAnnounceDone(req.node, answer, sr);
scheduler.edit(sr->nextSearchStep, scheduler.time());
searchStep(sr);
}
};
@@ -490,29 +463,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %d)",
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
sn->acked[a.value->id] = {
network_engine.sendRefreshValue(sn->node, sr->id, a.value->id, sn->token, onDone,
[this, ws, node=sn->node, v=a.value,
onDone,
onExpired,
created = a.permanent ? time_point::max() : a.created,
next_refresh_time
](const net::Request& /*req*/, net::DhtProtocolException&& e){
if (e.getCode() == net::DhtProtocolException::NOT_FOUND) {
if (logger_)
logger_->e(node->id, "[node %s] returned error 404: storage not found", node->toString().c_str());
if (auto sr = ws.lock()) {
if (auto sn = sr->getNode(node)) {
sn->acked[v->id] = {
network_engine.sendAnnounceValue(sn->node, sr->id, v, created, sn->token, onDone, onExpired),
next_refresh_time
};
scheduler.edit(sr->nextSearchStep, scheduler.time());
return true;
}
}
}
return false;
}, onExpired),
network_engine.sendRefreshValue(sn->node, sr->id, a.value->id, sn->token, onDone, onExpired),
next_refresh_time
};
} else {
@@ -591,30 +542,33 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
std::weak_ptr<Search> ws = sr;
for (const auto& l : sr->listeners) {
const auto& query = l.second.query;
auto r = n.listenStatus.find(query);
if (n.getListenTime(r, listenExp) > scheduler.time())
auto list_token = l.first;
if (n.getListenTime(query, listenExp) > scheduler.time())
continue;
// if (logger_)
// logger_->d(sr->id, n.node->id, "[search %s] [node %s] sending 'listen'",
// sr->id.toString().c_str(), n.node->toString().c_str());
auto r = n.listenStatus.find(query);
if (r == n.listenStatus.end()) {
r = n.listenStatus.emplace(std::piecewise_construct,
std::forward_as_tuple(query),
std::forward_as_tuple(
l.second.get_cb,
l.second.sync_cb,
n.node->openSocket([this,ws,query](const Sp<Node>& node, net::RequestAnswer&& answer) mutable {
/* on new values */
if (auto sr = ws.lock()) {
scheduler.edit(sr->nextSearchStep, scheduler.time());
sr->insertNode(node, scheduler.time(), answer.ntoken);
if (auto sn = sr->getNode(node)) {
sn->onValues(query, std::move(answer), types, scheduler);
}
[ws,list_token](const std::vector<Sp<Value>>& values, bool expired){
if (auto sr = ws.lock()) {
auto l = sr->listeners.find(list_token);
if (l != sr->listeners.end()) {
l->second.get_cb(values, expired);
}
}))).first;
}
}, [ws,list_token] (ListenSyncStatus status) {
if (auto sr = ws.lock()) {
auto l = sr->listeners.find(list_token);
if (l != sr->listeners.end()) {
l->second.sync_cb(status);
}
}
})).first;
r->second.cacheExpirationJob = scheduler.add(time_point::max(), [this,ws,query,node=n.node]{
if (auto sr = ws.lock()) {
if (auto sn = sr->getNode(node)) {
@@ -623,7 +577,8 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
}
});
}
auto new_req = network_engine.sendListen(n.node, sr->id, *query, n.token, r->second.socketId,
auto prev_req = r != n.listenStatus.end() ? r->second.req : nullptr;
auto new_req = network_engine.sendListen(n.node, sr->id, *query, n.token, prev_req,
[this,ws,query](const net::Request& req, net::RequestAnswer&& answer) mutable
{ /* on done */
if (auto sr = ws.lock()) {
@@ -643,6 +598,16 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
if (auto sn = sr->getNode(req.node))
sn->listenStatus.erase(query);
}
},
[this,ws,query](const Sp<Node>& node, net::RequestAnswer&& answer) mutable
{ /* on new values */
if (auto sr = ws.lock()) {
scheduler.edit(sr->nextSearchStep, scheduler.time());
sr->insertNode(node, scheduler.time(), answer.ntoken);
if (auto sn = sr->getNode(node)) {
sn->onValues(query, std::move(answer), types, scheduler);
}
}
}
);
// Here the request may have failed and the CachedListenStatus removed
@@ -725,8 +690,8 @@ Dht::searchStep(Sp<Search> sr)
while (sr->currentlySolicitedNodeCount() < MAX_REQUESTED_SEARCH_NODES and searchSendGetValues(sr));
if (sr->getNumberOfConsecutiveBadNodes() >= std::min<size_t>(sr->nodes.size(), SEARCH_MAX_BAD_NODES))
if (sr->getNumberOfConsecutiveBadNodes() >= std::min(sr->nodes.size(),
static_cast<size_t>(SEARCH_MAX_BAD_NODES)))
{
if (logger_)
logger_->w(sr->id, "[search %s IPv%c] expired", sr->id.toString().c_str(), sr->af == AF_INET ? '4' : '6');
@@ -785,7 +750,7 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback gcb, QueryCallback q
sr->done = false;
sr->expired = false;
} else {
if (srs.size() < max_searches) {
if (searches4.size() + searches6.size() < MAX_SEARCHES) {
sr = std::make_shared<Search>();
srs.emplace(id, sr);
} else {
@@ -833,12 +798,47 @@ Dht::announce(const InfoHash& id,
{
auto& srs = searches(af);
auto srp = srs.find(id);
if (auto sr = srp == srs.end() ? search(id, af) : srp->second) {
sr->put(value, callback, created, permanent);
scheduler.edit(sr->nextSearchStep, scheduler.time());
} else if (callback) {
callback(false, {});
auto sr = srp == srs.end() ? search(id, af) : srp->second;
if (!sr) {
if (callback)
callback(false, {});
return;
}
sr->done = false;
sr->expired = false;
auto a_sr = std::find_if(sr->announce.begin(), sr->announce.end(), [&](const Announce& a){
return a.value->id == value->id;
});
if (a_sr == sr->announce.end()) {
sr->announce.emplace_back(Announce {permanent, value, created, callback});
for (auto& n : sr->nodes) {
n->probe_query.reset();
n->acked[value->id].first.reset();
}
} else {
a_sr->permanent = permanent;
a_sr->created = created;
if (a_sr->value != value) {
a_sr->value = value;
for (auto& n : sr->nodes) {
n->acked[value->id].first.reset();
n->probe_query.reset();
}
}
if (sr->isAnnounced(value->id)) {
if (a_sr->callback)
a_sr->callback(true, {});
a_sr->callback = {};
if (callback)
callback(true, {});
return;
} else {
if (a_sr->callback)
a_sr->callback(false, {});
a_sr->callback = callback;
}
}
scheduler.edit(sr->nextSearchStep, scheduler.time());
}
size_t
@@ -872,7 +872,7 @@ Dht::listen(const InfoHash& id, ValueCallback cb, Value::Filter f, Where where)
auto query = std::make_shared<Query>(Select{}, std::move(where));
auto filter = f.chain(query->where.getFilter());
auto st = store.find(id);
if (st == store.end() && store.size() < max_store_keys)
if (st == store.end() && store.size() < MAX_HASHES)
st = store.emplace(id, scheduler.time() + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME).first;
size_t tokenlocal = 0;
@@ -918,8 +918,8 @@ Dht::cancelListen(const InfoHash& id, size_t token)
srp->second->cancelListen(token, scheduler);
}
};
searches_cancel_listen(dht4.searches, std::get<1>(it->second));
searches_cancel_listen(dht6.searches, std::get<2>(it->second));
searches_cancel_listen(searches4, std::get<1>(it->second));
searches_cancel_listen(searches6, std::get<2>(it->second));
listeners.erase(it);
return true;
}
@@ -1130,8 +1130,8 @@ Dht::getPut(const InfoHash& id) const
auto vals = srp->second->getPut();
ret.insert(ret.end(), vals.begin(), vals.end());
};
find_values(dht4.searches);
find_values(dht6.searches);
find_values(searches4);
find_values(searches6);
return ret;
}
@@ -1142,9 +1142,9 @@ Dht::getPut(const InfoHash& id, const Value::Id& vid) const
auto srp = srs.find(id);
return (srp != srs.end()) ? srp->second->getPut(vid) : Sp<Value> {};
};
if (auto v4 = find_value(dht4.searches))
if (auto v4 = find_value(searches4))
return v4;
if (auto v6 = find_value(dht6.searches))
if (auto v6 = find_value(searches6))
return v6;
return {};
}
@@ -1157,8 +1157,8 @@ Dht::cancelPut(const InfoHash& id, const Value::Id& vid)
auto srp = srs.find(id);
return (srp != srs.end()) ? srp->second->cancelPut(vid) : false;
};
canceled |= sr_cancel_put(dht4.searches);
canceled |= sr_cancel_put(dht6.searches);
canceled |= sr_cancel_put(searches4);
canceled |= sr_cancel_put(searches6);
if (canceled)
storageErase(id, vid);
return canceled;
@@ -1209,7 +1209,7 @@ Dht::storageChanged(const InfoHash& id, Storage& st, ValueStorage& v, bool newVa
vals.push_back(v.data);
Blob ntoken = makeToken(node_listeners.first->getAddr(), false);
network_engine.tellListener(node_listeners.first, l.first, id, 0, ntoken, {}, {},
std::move(vals), l.second.query, l.second.version);
std::move(vals), l.second.query);
}
}
}
@@ -1226,7 +1226,7 @@ Dht::storageStore(const InfoHash& id, const Sp<Value>& value, time_point created
auto st = store.find(id);
if (st == store.end()) {
if (store.size() >= max_store_keys)
if (store.size() >= MAX_HASHES)
return false;
auto st_i = store.emplace(id, now);
st = st_i.first;
@@ -1267,12 +1267,12 @@ Dht::storageErase(const InfoHash& id, Value::Id vid)
}
void
Dht::storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t socket_id, Query&& query, int version)
Dht::storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t socket_id, Query&& query)
{
const auto& now = scheduler.time();
auto st = store.find(id);
if (st == store.end()) {
if (store.size() >= max_store_keys)
if (store.size() >= MAX_HASHES)
return;
st = store.emplace(id, now).first;
}
@@ -1282,10 +1282,10 @@ Dht::storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t socket_
auto vals = st->second.get(query.where.getFilter());
if (not vals.empty()) {
network_engine.tellListener(node, socket_id, id, WANT4 | WANT6, makeToken(node->getAddr(), false),
dht4.buckets.findClosestNodes(id, now, TARGET_NODES), dht6.buckets.findClosestNodes(id, now, TARGET_NODES),
std::move(vals), query, version);
buckets4.findClosestNodes(id, now, TARGET_NODES), buckets6.findClosestNodes(id, now, TARGET_NODES),
std::move(vals), query);
}
node_listeners.emplace(socket_id, Listener {now, std::forward<Query>(query), version});
node_listeners.emplace(socket_id, Listener {now, std::forward<Query>(query)});
}
else
l->second.refresh(now, std::forward<Query>(query));
@@ -1320,7 +1320,7 @@ Dht::expireStore(decltype(store)::iterator i)
id.toString().c_str(),
node_listeners.first->toString().c_str());
Blob ntoken = makeToken(node_listeners.first->getAddr(), false);
network_engine.tellListenerExpired(node_listeners.first, l.first, id, ntoken, ids, l.second.version);
network_engine.tellListenerExpired(node_listeners.first, l.first, id, ntoken, ids);
}
}
}
@@ -1460,17 +1460,11 @@ Dht::tokenMatch(const Blob& token, const SockAddr& addr) const
NodeStats
Dht::getNodesStats(sa_family_t af) const
{
NodeStats stats = dht(af).getNodesStats(scheduler.time(), myid);
stats.node_cache_size = network_engine.getNodeCacheSize(af);
return stats;
}
NodeStats
Dht::Kad::getNodesStats(time_point now, const InfoHash& myid) const
{
NodeStats stats {};
for (const auto& b : buckets) {
const auto& now = scheduler.time();
const auto& bcks = buckets(af);
for (const auto& b : bcks) {
for (auto& n : b.nodes) {
if (n->isGood(now)) {
stats.good_nodes++;
@@ -1482,11 +1476,26 @@ Dht::Kad::getNodesStats(time_point now, const InfoHash& myid) const
if (b.cached)
stats.cached_nodes++;
}
stats.table_depth = buckets.depth(buckets.findBucket(myid));
stats.searches = searches.size();
stats.table_depth = bcks.depth(bcks.findBucket(myid));
stats.searches = searches(af).size();
stats.cached_nodes = network_engine.getNodeCacheSize(af);
return stats;
}
NodeMetrics
Dht::getNodeMetrics() const
{
NodeMetrics metrics;
metrics.scheduler_size = scheduler.size();
metrics.node_cache_size = network_engine.getNodeCacheSize();
metrics.rate_limiter_size = network_engine.getRateLimiterSize();
metrics.store_size = store.size();
metrics.store_quota_size = store_quota.size();
metrics.reported_addr_num = reported_addr.size();
metrics.request_count = net::REQ_COUNT.load();
return metrics;
}
void
Dht::dumpBucket(const Bucket& b, std::ostream& out) const
{
@@ -1604,18 +1613,18 @@ Dht::dumpTables() const
out << "My id " << myid << std::endl;
out << "Buckets IPv4 :" << std::endl;
for (const auto& b : dht4.buckets)
for (const auto& b : buckets4)
dumpBucket(b, out);
out << "Buckets IPv6 :" << std::endl;
for (const auto& b : dht6.buckets)
for (const auto& b : buckets6)
dumpBucket(b, out);
auto dump_searches = [&](std::map<InfoHash, Sp<Search>> srs) {
for (auto& srp : srs)
dumpSearch(*srp.second, out);
};
dump_searches(dht4.searches);
dump_searches(dht6.searches);
dump_searches(searches4);
dump_searches(searches6);
out << std::endl;
out << getStorageLog() << std::endl;
@@ -1691,24 +1700,24 @@ std::string
Dht::getSearchesLog(sa_family_t af) const
{
std::stringstream out;
auto num_searches = dht4.searches.size() + dht6.searches.size();
auto num_searches = searches4.size() + searches6.size();
if (num_searches > 8) {
if (not af or af == AF_INET)
for (const auto& sr : dht4.searches)
for (const auto& sr : searches4)
out << "[search " << sr.first << " IPv4]" << std::endl;
if (not af or af == AF_INET6)
for (const auto& sr : dht6.searches)
for (const auto& sr : searches6)
out << "[search " << sr.first << " IPv6]" << std::endl;
} else {
out << "s:synched, u:updated, a:announced, c:candidate, f:cur req, x:expired, *:known" << std::endl;
if (not af or af == AF_INET)
for (const auto& sr : dht4.searches)
for (const auto& sr : searches4)
dumpSearch(*sr.second, out);
if (not af or af == AF_INET6)
for (const auto& sr : dht6.searches)
for (const auto& sr : searches6)
dumpSearch(*sr.second, out);
}
out << "Total: " << num_searches << " searches (" << dht4.searches.size() << " IPv4, " << dht6.searches.size() << " IPv6)." << std::endl;
out << "Total: " << num_searches << " searches (" << searches4.size() << " IPv4, " << searches6.size() << " IPv6)." << std::endl;
return out.str();
}
@@ -1729,9 +1738,9 @@ Dht::getSearchLog(const InfoHash& id, sa_family_t af) const
Dht::~Dht()
{
for (auto& s : dht4.searches)
for (auto& s : searches4)
s.second->clear();
for (auto& s : dht6.searches)
for (auto& s : searches6)
s.second->clear();
}
@@ -1750,12 +1759,7 @@ fromDhtConfig(const Config& config)
Dht::Dht() : store(), network_engine(logger_, rd, scheduler, {}) {}
Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, const Sp<Logger>& l)
: DhtInterface(l),
myid(config.node_id ? config.node_id : InfoHash::getRandom(rd)),
store(),
store_quota(),
max_store_keys(config.max_store_size ? (int)config.max_store_size : MAX_HASHES),
max_searches(config.max_searches ? (int)config.max_searches : MAX_SEARCHES),
: DhtInterface(l), myid(config.node_id ? config.node_id : InfoHash::getRandom()), store(), store_quota(),
network_engine(myid, fromDhtConfig(config), std::move(sock), logger_, rd, scheduler,
std::bind(&Dht::onError, this, _1, _2),
std::bind(&Dht::onNewNode, this, _1, _2),
@@ -1763,7 +1767,7 @@ Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, cons
std::bind(&Dht::onPing, this, _1),
std::bind(&Dht::onFindNode, this, _1, _2, _3),
std::bind(&Dht::onGetValues, this, _1, _2, _3, _4),
std::bind(&Dht::onListen, this, _1, _2, _3, _4, _5, _6),
std::bind(&Dht::onListen, this, _1, _2, _3, _4, _5),
std::bind(&Dht::onAnnounce, this, _1, _2, _3, _4, _5),
std::bind(&Dht::onRefresh, this, _1, _2, _3, _4)),
persistPath(config.persist_path),
@@ -1776,12 +1780,12 @@ Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, cons
if (not s or (not s->hasIPv4() and not s->hasIPv6()))
throw DhtException("Opened socket required");
if (s->hasIPv4()) {
dht4.buckets = {Bucket {AF_INET}};
dht4.buckets.is_client = config.is_bootstrap;
buckets4 = {Bucket {AF_INET}};
buckets4.is_client = config.is_bootstrap;
}
if (s->hasIPv6()) {
dht6.buckets = {Bucket {AF_INET6}};
dht6.buckets.is_client = config.is_bootstrap;
buckets6 = {Bucket {AF_INET6}};
buckets6.is_client = config.is_bootstrap;
}
search_id = std::uniform_int_distribution<decltype(search_id)>{}(rd);
@@ -1793,13 +1797,13 @@ Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, cons
secret = std::uniform_int_distribution<uint64_t>{}(rd);
rotateSecrets();
if (not persistPath.empty())
loadState(persistPath);
expire();
if (logger_)
logger_->d("DHT node initialised with ID %s", myid.toString().c_str());
if (not persistPath.empty())
loadState(persistPath);
}
bool
@@ -1976,39 +1980,13 @@ Dht::expire()
uniform_duration_distribution<> time_dis(std::chrono::minutes(2), std::chrono::minutes(6));
auto expire_stuff_time = scheduler.time() + duration(time_dis(rd));
expireBuckets(dht4.buckets);
expireBuckets(dht6.buckets);
expireBuckets(buckets4);
expireBuckets(buckets6);
expireStore();
expireSearches();
scheduler.add(expire_stuff_time, std::bind(&Dht::expire, this));
}
void
Dht::onDisconnected()
{
if (dht4.status != NodeStatus::Disconnected || dht6.status != NodeStatus::Disconnected)
return;
if (logger_)
logger_->d(myid, "Bootstraping");
for (const auto& boootstrap : bootstrap_nodes) {
try {
auto ips = network_engine.getSocket()->resolve(boootstrap.first, boootstrap.second);
for (auto& ip : ips) {
if (ip.getPort() == 0)
ip.setPort(net::DHT_DEFAULT_PORT);
pingNode(ip);
}
} catch (const std::exception& e) {
if (logger_)
logger_->e(myid, "Can't resolve %s:%s: %s", boootstrap.first.c_str(), boootstrap.second.c_str(), e.what());
}
}
if (bootstrapJob)
bootstrapJob->cancel();
bootstrapJob = scheduler.add(scheduler.time() + bootstrap_period, std::bind(&Dht::onDisconnected, this));
bootstrap_period *= 2;
}
void
Dht::confirmNodes()
{
@@ -2016,25 +1994,25 @@ Dht::confirmNodes()
bool soon = false;
const auto& now = scheduler.time();
if (dht4.searches.empty() and dht4.status == NodeStatus::Connected) {
if (searches4.empty() and getStatus(AF_INET) == NodeStatus::Connected) {
if (logger_)
logger_->d(myid, "[confirm nodes] initial IPv4 'get' for my id (%s)", myid.toString().c_str());
search(myid, AF_INET);
}
if (dht6.searches.empty() and dht6.status == NodeStatus::Connected) {
if (searches6.empty() and getStatus(AF_INET6) == NodeStatus::Connected) {
if (logger_)
logger_->d(myid, "[confirm nodes] initial IPv6 'get' for my id (%s)", myid.toString().c_str());
search(myid, AF_INET6);
}
soon |= bucketMaintenance(dht4.buckets);
soon |= bucketMaintenance(dht6.buckets);
soon |= bucketMaintenance(buckets4);
soon |= bucketMaintenance(buckets6);
if (!soon) {
if (dht4.buckets.grow_time >= now - seconds(150))
soon |= neighbourhoodMaintenance(dht4.buckets);
if (dht6.buckets.grow_time >= now - seconds(150))
soon |= neighbourhoodMaintenance(dht6.buckets);
if (buckets4.grow_time >= now - seconds(150))
soon |= neighbourhoodMaintenance(buckets4);
if (buckets6.grow_time >= now - seconds(150))
soon |= neighbourhoodMaintenance(buckets6);
}
/* In order to maintain all buckets' age within 600 seconds, worst
@@ -2078,13 +2056,13 @@ Dht::importValues(const std::vector<ValuesExport>& import)
{
const auto& now = scheduler.time();
for (const auto& value : import) {
if (value.second.empty())
for (const auto& node : import) {
if (node.second.empty())
continue;
try {
msgpack::unpacked msg;
msgpack::unpack(msg, (const char*)value.second.data(), value.second.size());
msgpack::unpack(msg, (const char*)node.second.data(), node.second.size());
auto valarr = msg.get();
if (valarr.type != msgpack::type::ARRAY)
throw msgpack::type_error();
@@ -2099,15 +2077,15 @@ Dht::importValues(const std::vector<ValuesExport>& import)
tmp_val.msgpack_unpack(valel.via.array.ptr[1]);
} catch (const std::exception&) {
if (logger_)
logger_->e(value.first, "Error reading value at %s", value.first.toString().c_str());
logger_->e(node.first, "Error reading value at %s", node.first.toString().c_str());
continue;
}
val_time = std::min(val_time, now);
storageStore(value.first, std::make_shared<Value>(std::move(tmp_val)), val_time);
storageStore(node.first, std::make_shared<Value>(std::move(tmp_val)), val_time);
}
} catch (const std::exception&) {
if (logger_)
logger_->e(value.first, "Error reading values at %s", value.first.toString().c_str());
logger_->e(node.first, "Error reading values at %s", node.first.toString().c_str());
continue;
}
}
@@ -2119,25 +2097,25 @@ Dht::exportNodes() const
{
const auto& now = scheduler.time();
std::vector<NodeExport> nodes;
const auto b4 = dht4.buckets.findBucket(myid);
if (b4 != dht4.buckets.end()) {
const auto b4 = buckets4.findBucket(myid);
if (b4 != buckets4.end()) {
for (auto& n : b4->nodes)
if (n->isGood(now))
nodes.push_back(n->exportNode());
}
const auto b6 = dht6.buckets.findBucket(myid);
if (b6 != dht6.buckets.end()) {
const auto b6 = buckets6.findBucket(myid);
if (b6 != buckets6.end()) {
for (auto& n : b6->nodes)
if (n->isGood(now))
nodes.push_back(n->exportNode());
}
for (auto b = dht4.buckets.begin(); b != dht4.buckets.end(); ++b) {
for (auto b = buckets4.begin(); b != buckets4.end(); ++b) {
if (b == b4) continue;
for (auto& n : b->nodes)
if (n->isGood(now))
nodes.push_back(n->exportNode());
}
for (auto b = dht6.buckets.begin(); b != dht6.buckets.end(); ++b) {
for (auto b = buckets6.begin(); b != buckets6.end(); ++b) {
if (b == b6) continue;
for (auto& n : b->nodes)
if (n->isGood(now))
@@ -2161,7 +2139,7 @@ Dht::pingNode(SockAddr sa, DoneCallbackSimple&& cb)
scheduler.syncTime();
if (logger_)
logger_->d("Sending ping to %s", sa.toString().c_str());
auto& count = dht(sa.getFamily()).pending_pings;
auto& count = sa.getFamily() == AF_INET ? pending_pings4 : pending_pings6;
count++;
network_engine.sendPing(std::move(sa), [&count,cb](const net::Request&, net::RequestAnswer&&) {
count--;
@@ -2183,6 +2161,7 @@ Dht::onError(Sp<net::Request> req, net::DhtProtocolException e) {
if (logger_)
logger_->e(node->id, "[node %s] token flush", node->toString().c_str());
node->authError();
node->cancelRequest(req);
for (auto& srp : searches(node->getFamily())) {
auto& sr = srp.second;
for (auto& n : sr->nodes) {
@@ -2221,9 +2200,9 @@ Dht::onFindNode(Sp<Node> node, const InfoHash& target, want_t want)
net::RequestAnswer answer;
answer.ntoken = makeToken(node->getAddr(), false);
if (want & WANT4)
answer.nodes4 = dht4.buckets.findClosestNodes(target, now, TARGET_NODES);
answer.nodes4 = buckets4.findClosestNodes(target, now, TARGET_NODES);
if (want & WANT6)
answer.nodes6 = dht6.buckets.findClosestNodes(target, now, TARGET_NODES);
answer.nodes6 = buckets6.findClosestNodes(target, now, TARGET_NODES);
return answer;
}
@@ -2242,8 +2221,8 @@ Dht::onGetValues(Sp<Node> node, const InfoHash& hash, want_t, const Query& query
net::RequestAnswer answer {};
auto st = store.find(hash);
answer.ntoken = makeToken(node->getAddr(), false);
answer.nodes4 = dht4.buckets.findClosestNodes(hash, now, TARGET_NODES);
answer.nodes6 = dht6.buckets.findClosestNodes(hash, now, TARGET_NODES);
answer.nodes4 = buckets4.findClosestNodes(hash, now, TARGET_NODES);
answer.nodes6 = buckets6.findClosestNodes(hash, now, TARGET_NODES);
if (st != store.end() && not st->second.empty()) {
answer.values = st->second.get(query.where.getFilter());
if (logger_)
@@ -2332,7 +2311,7 @@ void Dht::onGetValuesDone(const Sp<Node>& node,
}
net::RequestAnswer
Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t socket_id, const Query& query, int version)
Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t socket_id, const Query& query)
{
if (not hash) {
if (logger_)
@@ -2348,7 +2327,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
throw net::DhtProtocolException {net::DhtProtocolException::UNAUTHORIZED, net::DhtProtocolException::LISTEN_WRONG_TOKEN};
}
Query q = query;
storageAddListener(hash, node, socket_id, std::move(q), version);
storageAddListener(hash, node, socket_id, std::move(q));
return {};
}
@@ -2487,7 +2466,7 @@ Dht::storageRefresh(const InfoHash& id, Value::Id vid)
id.toString().c_str(),
node_listeners.first->toString().c_str());
Blob ntoken = makeToken(node_listeners.first->getAddr(), false);
network_engine.tellListenerRefreshed(node_listeners.first, l.first, id, ntoken, ids, l.second.version);
network_engine.tellListenerRefreshed(node_listeners.first, l.first, id, ntoken, ids);
}
}
}
@@ -2511,24 +2490,12 @@ Dht::onAnnounceDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>
}
struct DhtState {
unsigned v {1};
InfoHash id;
std::vector<NodeExport> nodes;
std::vector<ValuesExport> values;
MSGPACK_DEFINE_MAP(v, id, nodes, values)
};
void
Dht::saveState(const std::string& path) const
{
DhtState state;
state.id = myid;
state.nodes = exportNodes();
state.values = exportValues();
std::ofstream file(path);
msgpack::pack(file, state);
msgpack::pack(file, exportNodes());
msgpack::pack(file, exportValues());
}
void
@@ -2554,16 +2521,19 @@ Dht::loadState(const std::string& path)
// Import nodes
msgpack::object_handle oh;
if (pac.next(oh)) {
auto state = oh.get().as<DhtState>();
if (logger_)
logger_->d("Importing %zu nodes", state.nodes.size());
if (state.id)
myid = state.id;
std::vector<Sp<Node>> tmpNodes;
tmpNodes.reserve(state.nodes.size());
for (const auto& node : state.nodes)
tmpNodes.emplace_back(network_engine.insertNode(node.id, SockAddr(node.ss, node.sslen)));
importValues(state.values);
{
auto imported_nodes = oh.get().as<std::vector<NodeExport>>();
if (logger_)
logger_->d("Importing %zu nodes", imported_nodes.size());
for (const auto& node : imported_nodes)
insertNode(node);
}
if (pac.next(oh)) {
auto imported_values = oh.get().as<std::vector<ValuesExport>>();
if (logger_)
logger_->d("Importing %zu values", imported_values.size());
importValues(imported_values);
}
}
} catch (const std::exception& e) {
if (logger_)
+5 -17
View File
@@ -98,7 +98,7 @@ getRandomSessionId(size_t length = 8) {
static constexpr const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~";
std::string str(length, 0);
crypto::random_device rdev;
std::uniform_int_distribution<> dist(0, (sizeof(chars)/sizeof(char)) - 2);
std::uniform_int_distribution<> dist(0, (sizeof(chars)/sizeof(char)) - 1);
std::generate_n( str.begin(), length, [&]{ return chars[dist(rdev)]; } );
return str;
}
@@ -683,7 +683,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
{
if (isDestroying_)
return;
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
auto& status = family == AF_INET ? statusIpv4_ : statusIpv6_;
if (not proxyInfos.isMember("node_id")) {
@@ -720,7 +720,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
if (newStatus == NodeStatus::Connected) {
if (oldStatus == NodeStatus::Disconnected || oldStatus == NodeStatus::Connecting) {
listenerRestartTimer_->expires_at(std::chrono::steady_clock::now());
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this, std::placeholders::_1));
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this));
}
nextProxyConfirmationTimer_->expires_at(std::chrono::steady_clock::now() + std::chrono::minutes(15));
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
@@ -729,7 +729,6 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
nextProxyConfirmationTimer_->expires_at(std::chrono::steady_clock::now() + std::chrono::minutes(1));
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
}
l.unlock();
loopSignal_();
}
@@ -1079,16 +1078,8 @@ DhtProxyClient::getConnectivityStatus()
}
void
DhtProxyClient::restartListeners(const asio::error_code &ec)
DhtProxyClient::restartListeners()
{
if (ec == asio::error::operation_aborted)
return;
else if (ec){
if (logger_)
logger_->e("[proxy:client] restart error: %s", ec.message().c_str());
return;
}
if (isDestroying_)
return;
if (logger_)
@@ -1162,7 +1153,6 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
statusIpv4_ = NodeStatus::Connected;
statusIpv6_ = NodeStatus::Connected;
}
auto launchLoop = false;
try {
auto sessionId = notification.find("s");
if (sessionId != notification.end() and sessionId->second != pushSessionId_) {
@@ -1239,7 +1229,7 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
opstate->stop = true;
});
}
launchLoop = true;
loopSignal_();
}
}
}
@@ -1247,8 +1237,6 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
if (logger_)
logger_->e("[proxy:client] [push] receive error: %s", e.what());
}
if (launchLoop)
loopSignal_();
#else
(void) notification;
#endif
+124 -338
View File
@@ -34,7 +34,6 @@
#include <functional>
#include <limits>
#include <iostream>
#include <fstream>
using namespace std::placeholders;
using namespace std::chrono_literals;
@@ -174,73 +173,26 @@ struct DhtProxyServer::RestRouterTraits : public restinio::default_traits_t
using connection_state_listener_t = ConnectionListener;
};
void
DhtProxyServer::PermanentPut::msgpack_unpack(const msgpack::object& o)
{
if (auto cid = findMapValue(o, "cid")) {
clientId = cid->as<std::string>();
}
if (auto exp = findMapValue(o, "exp")) {
expiration = from_time_t(exp->as<time_t>());
}
if (auto token = findMapValue(o, "token")) {
pushToken = token->as<std::string>();
}
if (auto sid = findMapValue(o, "sid")) {
if (not sessionCtx)
sessionCtx = std::make_shared<PushSessionContext>(sid->as<std::string>());
else
sessionCtx->sessionId = sid->as<std::string>();
}
if (auto t = findMapValue(o, "t")) {
type = t->as<PushType>();
}
if (auto val = findMapValue(o, "value")) {
value = std::make_shared<dht::Value>(*val);
}
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
void
DhtProxyServer::Listener::msgpack_unpack(const msgpack::object& o)
{
if (auto cid = findMapValue(o, "cid")) {
clientId = cid->as<std::string>();
}
if (auto exp = findMapValue(o, "exp")) {
expiration = from_time_t(exp->as<time_t>());
}
if (auto sid = findMapValue(o, "sid")) {
if (not sessionCtx)
sessionCtx = std::make_shared<PushSessionContext>(sid->as<std::string>());
else
sessionCtx->sessionId = sid->as<std::string>();
}
if (auto t = findMapValue(o, "t")) {
type = t->as<PushType>();
}
}
#endif
DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
const ProxyServerConfig& config,
const std::shared_ptr<dht::Logger>& logger
DhtProxyServer::DhtProxyServer(
crypto::Identity identity,
std::shared_ptr<DhtRunner> dht, in_port_t port, const std::string& pushServer,
std::shared_ptr<Logger> logger
)
: ioContext_(std::make_shared<asio::io_context>()),
dht_(dht), persistPath_(config.persistStatePath), logger_(logger),
dht_(dht), logger_(logger),
printStatsTimer_(std::make_unique<asio::steady_timer>(*ioContext_, 3s)),
connListener_(std::make_shared<ConnectionListener>(std::bind(&DhtProxyServer::onConnectionClosed, this, std::placeholders::_1))),
pushServer_(config.pushServer)
pushServer_(pushServer)
{
if (not dht_)
throw std::invalid_argument("A DHT instance must be provided");
if (logger_)
logger_->d("[proxy:server] [init] running on %i", config.port);
if (not pushServer_.empty()){
logger_->d("[proxy:server] [init] running on %i", port);
if (not pushServer.empty()){
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (logger_)
logger_->d("[proxy:server] [init] using push server %s", pushServer_.c_str());
logger_->d("[proxy:server] [init] using push server %s", pushServer.c_str());
#else
if (logger_)
logger_->e("[proxy:server] [init] opendht built without push notification support");
@@ -250,9 +202,9 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
jsonBuilder_["commentStyle"] = "None";
jsonBuilder_["indentation"] = "";
if (!pushServer_.empty()){
if (!pushServer.empty()){
// no host delim, assume port only
if (pushServer_.find(":") == std::string::npos)
if (pushServer.find(":") == std::string::npos)
pushServer_ = "localhost:" + pushServer_;
// define http request destination for push notifications
pushHostPort_ = splitPort(pushServer_);
@@ -260,7 +212,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
logger_->d("Using push server for notifications: %s:%s", pushHostPort_.first.c_str(),
pushHostPort_.second.c_str());
}
if (config.identity.first and config.identity.second) {
if (identity.first and identity.second) {
asio::error_code ec;
// define tls context
asio::ssl::context tls_context { asio::ssl::context::sslv23 };
@@ -274,13 +226,13 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
SSL_CTX_set_options(tls_context.native_handle(), SSL_OP_NO_RENEGOTIATION); // CVE-2009-3555
#endif
// node private key
auto key = config.identity.first->serialize();
auto key = identity.first->serialize();
tls_context.use_private_key(asio::const_buffer{key.data(), key.size()},
asio::ssl::context::file_format::pem, ec);
if (ec)
throw std::runtime_error("Error setting node's private key: " + ec.message());
// certificate chain
auto certchain = config.identity.second->toString(true/*chain*/);
auto certchain = identity.second->toString(true/*chain*/);
tls_context.use_certificate_chain(asio::const_buffer{certchain.data(), certchain.size()}, ec);
if (ec)
throw std::runtime_error("Error setting certificate chain: " + ec.message());
@@ -289,7 +241,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
// build http server
auto settings = restinio::run_on_this_thread_settings_t<RestRouterTraitsTls>();
addServerSettings(settings);
settings.port(config.port);
settings.port(port);
settings.tls_context(std::move(tls_context));
httpsServer_ = std::make_unique<restinio::http_server_t<RestRouterTraitsTls>>(
ioContext_,
@@ -306,7 +258,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
else {
auto settings = restinio::run_on_this_thread_settings_t<RestRouterTraits>();
addServerSettings(settings);
settings.port(config.port);
settings.port(port);
httpServer_ = std::make_unique<restinio::http_server_t<RestRouterTraits>>(
ioContext_,
std::forward<restinio::run_on_this_thread_settings_t<RestRouterTraits>>(std::move(settings))
@@ -322,158 +274,8 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
dht->forwardAllMessages(true);
updateStats();
printStatsTimer_->async_wait(std::bind(&DhtProxyServer::handlePrintStats, this, std::placeholders::_1));
if (not persistPath_.empty()) {
try {
std::ifstream stateFile(persistPath_, std::ios::binary | std::ios::ate);
if (stateFile) {
std::streamsize size = stateFile.tellg();
stateFile.seekg(0, std::ios::beg);
if (logger_)
logger_->d("Loading proxy state from %.*s (%td bytes)", (int)persistPath_.size(), persistPath_.c_str(), size);
loadState(stateFile, size);
}
} catch (const std::exception& e) {
if (logger_)
logger_->e("Error loading state from file: %s", e.what());
}
}
}
template <typename Os>
void
DhtProxyServer::saveState(Os& stream) {
msgpack::packer<Os> pk(&stream);
pk.pack_map(2);
{
std::lock_guard<std::mutex> lock(lockSearchPuts_);
pk.pack("puts");
pk.pack(puts_);
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
{
std::lock_guard<std::mutex> lock(lockListener_);
pk.pack("pushListeners");
pk.pack(pushListeners_);
}
#endif
}
template <typename Is>
void
DhtProxyServer::loadState(Is& is, size_t size) {
msgpack::unpacker pac;
pac.reserve_buffer(size);
if (is.read(pac.buffer(), size)) {
pac.buffer_consumed(size);
msgpack::object_handle oh;
while (pac.next(oh)) {
if (oh.get().type != msgpack::type::MAP)
continue;
if (auto puts = findMapValue(oh.get(), "puts")) {
std::lock_guard<std::mutex> lock(lockSearchPuts_);
puts_ = puts->as<decltype(puts_)>();
if (logger_)
logger_->d("Loading %zu persistent puts", puts_.size());
for (auto& put : puts_) {
for (auto& pput : put.second.puts) {
pput.second.expireTimer = std::make_unique<asio::steady_timer>(io_context(), pput.second.expiration);
pput.second.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPermamentPut, this,
std::placeholders::_1, put.first, pput.first));
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (not pput.second.pushToken.empty()) {
auto jsonProvider = [infoHash=put.first.toString(), clientId=pput.second.clientId, vid = pput.first, sessionCtx = pput.second.sessionCtx](){
Json::Value json;
json["timeout"] = infoHash;
json["to"] = clientId;
json["vid"] = std::to_string(vid);
if (sessionCtx) {
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
}
return json;
};
pput.second.expireNotifyTimer = std::make_unique<asio::steady_timer>(io_context(), pput.second.expiration - proxy::OP_MARGIN);
pput.second.expireNotifyTimer->async_wait(std::bind(
&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pput.second.pushToken, std::move(jsonProvider), pput.second.type));
}
#endif
dht_->put(put.first, pput.second.value, DoneCallbackSimple{}, time_point::max(), true);
}
}
} else {
if (logger_)
logger_->d("No persistent puts in state");
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (auto listeners = findMapValue(oh.get(), "pushListeners")) {
std::lock_guard<std::mutex> lock(lockListener_);
pushListeners_ = listeners->as<decltype(pushListeners_)>();
if (logger_)
logger_->d("Loading %zu push listeners", pushListeners_.size());
for (auto& pushListener : pushListeners_) {
for (auto& listeners : pushListener.second.listeners) {
for (auto& listener : listeners.second) {
listener.internalToken = dht_->listen(listeners.first,
[this, infoHash=listeners.first, pushToken=pushListener.first, type=listener.type, clientId=listener.clientId, sessionCtx = listener.sessionCtx]
(const std::vector<std::shared_ptr<Value>>& values, bool expired) {
// Build message content
Json::Value json;
json["key"] = infoHash.toString();
json["to"] = clientId;
json["t"] = Json::Value::Int64(std::chrono::duration_cast<std::chrono::milliseconds>(system_clock::now().time_since_epoch()).count());
{
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
}
if (expired and values.size() < 2){
std::stringstream ss;
for(size_t i = 0; i < values.size(); ++i){
if(i != 0) ss << ",";
ss << values[i]->id;
}
json["exp"] = ss.str();
}
auto maxPrio = 1000u;
for (const auto& v : values)
maxPrio = std::min(maxPrio, v->priority);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
return true;
}
);
// expire notify
listener.expireNotifyTimer = std::make_unique<asio::steady_timer>(io_context(), listener.expiration - proxy::OP_MARGIN);
auto jsonProvider = [infoHash = listeners.first.toString(), clientId = listener.clientId, sessionCtx = listener.sessionCtx](){
Json::Value json;
json["timeout"] = infoHash;
json["to"] = clientId;
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
return json;
};
listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pushListener.first, std::move(jsonProvider), listener.type));
// cancel push listen
listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), listener.expiration);
listener.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPushListen, this,
std::placeholders::_1, pushListener.first, listeners.first, listener.clientId));
}
}
}
} else {
if (logger_)
logger_->d("No push listeners in state");
}
#endif
}
if (logger_)
logger_->d("loading ended");
}
}
asio::io_context&
DhtProxyServer::io_context() const
{
@@ -482,12 +284,6 @@ DhtProxyServer::io_context() const
DhtProxyServer::~DhtProxyServer()
{
if (not persistPath_.empty()) {
if (logger_)
logger_->d("Saving proxy state to %.*s", (int)persistPath_.size(), persistPath_.c_str());
std::ofstream stateFile(persistPath_, std::ios::binary);
saveState(stateFile);
}
if (dht_) {
std::lock_guard<std::mutex> lock(lockListener_);
for (auto& l : listeners_) {
@@ -563,10 +359,6 @@ DhtProxyServer::updateStats(std::shared_ptr<NodeInfo> info) const
#ifdef OPENDHT_PUSH_NOTIFICATIONS
stats.pushListenersCount = pushListeners_.size();
#endif
stats.totalPermanentPuts = 0;
std::for_each(puts_.begin(), puts_.end(), [&stats](const auto& put) {
stats.totalPermanentPuts += put.second.puts.size();
});
stats.putCount = puts_.size();
stats.listenCount = listeners_.size();
stats.nodeInfo = std::move(info);
@@ -793,11 +585,12 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
restinio::router::route_params_t params)
{
requestNum_++;
try {
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"].to_string());
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"].to_string());
try {
std::string err;
Json::Value r;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
@@ -814,115 +607,117 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
response.set_body(RESP_MSG_NO_TOKEN);
return response.done();
}
auto type = root["platform"].asString() == "android" ? PushType::Android : PushType::iOS;
auto isAndroid = root["platform"].asString() == "android";
auto clientId = root["client_id"].asString();
auto sessionId = root["session_id"].asString();
if (logger_)
logger_->d("[proxy:server] [subscribe %s] [client %s] [session %s]", infoHash.toString().c_str(), clientId.c_str(), sessionId.c_str());
// ================ Search for existing listener ===================
// start the timer
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
std::lock_guard<std::mutex> lock(lockPushListeners_);
// Insert new or return existing push listeners of a token
std::lock_guard<std::mutex> lock(lockPushListeners_);
auto& pushListener = pushListeners_[pushToken];
auto& pushListeners = pushListener.listeners[infoHash];
auto listIt = std::find_if(pushListeners.begin(), pushListeners.end(), [&](const Listener& l) {
return l.clientId == clientId;
});
bool newListener = listIt == pushListeners.end();
if (newListener) {
pushListeners.emplace_back(Listener{});
listIt = std::prev(pushListeners.end());
listIt->clientId = clientId;
listIt->sessionCtx = std::make_shared<PushSessionContext>(sessionId);
} else {
std::lock_guard<std::mutex> l(listIt->sessionCtx->lock);
listIt->sessionCtx->sessionId = sessionId;
for (auto &listener: pushListeners) {
// Found -> Resubscribe
if (listener.clientId == clientId) {
if (logger_)
logger_->d("[proxy:server] [subscribe] found [client %s]", listener.clientId.c_str());
// Reset timers
listener.expireTimer->expires_at(timeout);
listener.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
{
std::lock_guard<std::mutex> l(listener.sessionCtx->lock);
listener.sessionCtx->sessionId = sessionId;
}
// Send response header
auto response = std::make_shared<ResponseByPartsBuilder>(
initHttpResponse(request->create_response<ResponseByParts>()));
response->flush();
if (!root["refresh"].asBool()) {
// No Refresh
dht_->get(infoHash, [this, response](const Sp<Value>& value){
auto output = Json::writeString(jsonBuilder_, value->toJson()) + "\n";
response->append_chunk(output);
response->flush();
return true;
},
[response] (bool){
response->done();
});
} else {
// Refresh
response->append_chunk("{}\n");
response->done();
}
return restinio::request_handling_status_t::accepted;
}
}
auto& listener = *listIt;
// =========== No existing listener for an infoHash ============
// Add new listener to list of listeners
pushListeners.emplace_back(Listener{});
auto &listener = pushListeners.back();
listener.clientId = clientId;
listener.sessionCtx = std::make_shared<PushSessionContext>();
listener.sessionCtx->sessionId = sessionId;
// Expiration
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
listener.expiration = timeout;
listener.type = type;
if (listener.expireNotifyTimer)
listener.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
else
// Add listen on dht
listener.internalToken = dht_->listen(infoHash,
[this, infoHash, pushToken, isAndroid, clientId, sessionCtx = listener.sessionCtx]
(const std::vector<std::shared_ptr<Value>>& values, bool expired){
// Build message content
Json::Value json;
json["key"] = infoHash.toString();
json["to"] = clientId;
json["t"] = Json::Value::Int64(std::chrono::duration_cast<std::chrono::milliseconds>(system_clock::now().time_since_epoch()).count());
{
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
}
if (expired and values.size() < 2){
std::stringstream ss;
for(size_t i = 0; i < values.size(); ++i){
if(i != 0) ss << ",";
ss << values[i]->id;
}
json["exp"] = ss.str();
}
auto maxPrio = 1000u;
for (const auto& v : values)
maxPrio = std::min(maxPrio, v->priority);
sendPushNotification(pushToken, std::move(json), isAndroid, !expired and maxPrio == 0);
return true;
}
);
// expire notify
if (!listener.expireNotifyTimer)
listener.expireNotifyTimer = std::make_unique<asio::steady_timer>(io_context(), timeout - proxy::OP_MARGIN);
auto jsonProvider = [h=infoHash.toString(), clientId, sessionCtx = listener.sessionCtx](){
else
listener.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
auto jsonProvider = [infoHash, clientId, sessionCtx = listener.sessionCtx](){
Json::Value json;
json["timeout"] = h;
json["timeout"] = infoHash.toString();
json["to"] = clientId;
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
return json;
};
listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type));
std::placeholders::_1, pushToken, std::move(jsonProvider), isAndroid));
// cancel push listen
if (!listener.expireTimer)
listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), timeout);
else
listener.expireTimer->expires_at(timeout);
listener.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPushListen, this,
std::placeholders::_1, pushToken, infoHash, clientId));
// Send response
if (not newListener) {
if (logger_)
logger_->d("[proxy:server] [subscribe] found [client %s]", listener.clientId.c_str());
// Send response header
auto response = std::make_shared<ResponseByPartsBuilder>(initHttpResponse(request->create_response<ResponseByParts>()));
response->flush();
if (!root["refresh"].asBool()) {
// No Refresh
dht_->get(infoHash, [this, response](const Sp<Value>& value){
auto output = Json::writeString(jsonBuilder_, value->toJson()) + "\n";
response->append_chunk(output);
response->flush();
return true;
},
[response] (bool){
response->done();
});
} else {
// Refresh
response->append_chunk("{}\n");
return response->done();
}
} else {
// =========== No existing listener for an infoHash ============
// Add listen on dht
listener.internalToken = dht_->listen(infoHash,
[this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx]
(const std::vector<std::shared_ptr<Value>>& values, bool expired){
// Build message content
Json::Value json;
json["key"] = infoHash.toString();
json["to"] = clientId;
json["t"] = Json::Value::Int64(std::chrono::duration_cast<std::chrono::milliseconds>(system_clock::now().time_since_epoch()).count());
{
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
}
if (expired and values.size() < 2){
std::stringstream ss;
for(size_t i = 0; i < values.size(); ++i){
if(i != 0) ss << ",";
ss << values[i]->id;
}
json["exp"] = ss.str();
}
auto maxPrio = 1000u;
for (const auto& v : values)
maxPrio = std::min(maxPrio, v->priority);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
return true;
}
);
auto response = initHttpResponse(request->create_response());
response.set_body("{}\n");
return response.done();
}
std::placeholders::_1, pushToken, infoHash, clientId));
auto response = initHttpResponse(request->create_response());
response.set_body("{}\n");
return response.done();
}
catch (...) {
return serverError(*request);
@@ -971,7 +766,7 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
void
DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
std::function<Json::Value()> jsonProvider, PushType type)
std::function<Json::Value()> jsonProvider, const bool isAndroid)
{
if (ec == asio::error::operation_aborted)
return;
@@ -981,7 +776,7 @@ DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const s
}
if (logger_)
logger_->d("[proxy:server] [subscribe] sending put refresh to %s token", pushToken.c_str());
sendPushNotification(pushToken, jsonProvider(), type, false);
sendPushNotification(pushToken, jsonProvider(), isAndroid, false);
}
void
@@ -1023,7 +818,7 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st
}
void
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority)
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, bool isAndroid, bool highPriority)
{
if (pushServer_.empty())
return;
@@ -1045,7 +840,7 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
Json::Value tokens(Json::arrayValue);
tokens[0] = token;
notification["tokens"] = std::move(tokens);
notification["platform"] = type == PushType::Android ? 2 : 1;
notification["platform"] = isAndroid ? 2 : 1;
notification["data"] = std::move(json);
notification["priority"] = highPriority ? "high" : "normal";
notification["time_to_live"] = 600;
@@ -1094,7 +889,6 @@ DhtProxyServer::handleCancelPermamentPut(const asio::error_code &ec, const InfoH
}
if (logger_)
logger_->d("[proxy:server] [put %s] cancel permament put %i", key.toString().c_str(), vid);
std::lock_guard<std::mutex> lock(lockSearchPuts_);
auto sPuts = puts_.find(key);
if (sPuts == puts_.end())
return;
@@ -1104,8 +898,6 @@ DhtProxyServer::handleCancelPermamentPut(const asio::error_code &ec, const InfoH
return;
if (dht_)
dht_->cancelPut(key, vid);
if (put->second.expireTimer)
put->second.expireTimer->cancel();
if (put->second.expireNotifyTimer)
put->second.expireNotifyTimer->cancel();
sPutsMap.erase(put);
@@ -1149,13 +941,13 @@ DhtProxyServer::put(restinio::request_handle_t request,
platform = pVal["platform"].asString();
sessionId = pVal["session_id"].asString();
}
std::lock_guard<std::mutex> lock(lockSearchPuts_);
std::unique_lock<std::mutex> lock(lockSearchPuts_);
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
auto& sPuts = puts_[infoHash];
if (value->id == Value::INVALID_ID) {
for (auto& pp : sPuts.puts) {
if (pp.second.pushToken == pushToken
and pp.second.clientId == clientId
if (pp.second.pushToken == pushToken
and pp.second.clientId == clientId
and pp.second.value->contentEquals(*value))
{
pp.second.expireTimer->expires_at(timeout);
@@ -1163,36 +955,32 @@ DhtProxyServer::put(restinio::request_handle_t request,
std::placeholders::_1, infoHash, pp.second.value->id));
if (not sessionId.empty()) {
if (not pp.second.sessionCtx)
pp.second.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
else {
std::lock_guard<std::mutex> l(pp.second.sessionCtx->lock);
pp.second.sessionCtx->sessionId = sessionId;
}
pp.second.sessionCtx = std::make_shared<PushSessionContext>();
std::lock_guard<std::mutex> l(pp.second.sessionCtx->lock);
pp.second.sessionCtx->sessionId = sessionId;
}
auto response = initHttpResponse(request->create_response());
response.append_body(Json::writeString(jsonBuilder_, value->toJson()) + "\n");
return response.done();
}
}
value->id = std::uniform_int_distribution<Value::Id>{1}(rd);
}
auto vid = value->id;
auto& pput = sPuts.puts[vid];
pput.value = value;
pput.expiration = timeout;
if (not pput.expireTimer) {
auto &ctx = io_context();
// cancel permanent put
pput.expireTimer = std::make_unique<asio::steady_timer>(ctx, timeout);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (not pushToken.empty()){
bool isAndroid = platform == "android";
pput.pushToken = pushToken;
pput.clientId = clientId;
pput.type = isAndroid ? PushType::Android : PushType::iOS;
pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
pput.sessionCtx = std::make_shared<PushSessionContext>();
pput.sessionCtx->sessionId = sessionId;
// notify push listen expire
bool isAndroid = platform == "android";
auto jsonProvider = [infoHash, clientId, vid, sessionCtx = pput.sessionCtx](){
Json::Value json;
json["timeout"] = infoHash.toString();
@@ -1209,17 +997,15 @@ DhtProxyServer::put(restinio::request_handle_t request,
pput.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
pput.expireNotifyTimer->async_wait(std::bind(
&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pushToken, std::move(jsonProvider), pput.type));
std::placeholders::_1, pushToken, std::move(jsonProvider), isAndroid));
}
#endif
} else {
if (not sessionId.empty()) {
if (not pput.sessionCtx)
pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
else {
std::lock_guard<std::mutex> l(pput.sessionCtx->lock);
pput.sessionCtx->sessionId = sessionId;
}
pput.sessionCtx = std::make_shared<PushSessionContext>();
std::lock_guard<std::mutex> l(pput.sessionCtx->lock);
pput.sessionCtx->sessionId = sessionId;
}
pput.expireTimer->expires_at(timeout);
if (pput.expireNotifyTimer)
+93 -62
View File
@@ -32,8 +32,6 @@
#include "dht_proxy_client.h"
#endif
#include <fstream>
namespace dht {
constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD;
@@ -92,46 +90,16 @@ DhtRunner::run(const char* ip4, const char* ip6, const char* service, const Conf
{
auto res4 = SockAddr::resolve(ip4, service);
auto res6 = SockAddr::resolve(ip6, service);
if (res4.empty())
res4.emplace_back();
if (res6.empty())
res6.emplace_back();
run(res4.front(), res6.front(), config, std::move(context));
run(res4.empty() ? SockAddr() : res4.front(),
res6.empty() ? SockAddr() : res6.front(), config, std::move(context));
}
void
DhtRunner::run(SockAddr& local4, SockAddr& local6, const Config& config, Context&& context)
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const Config& config, Context&& context)
{
if (running == State::Idle) {
auto state_path = config.dht_config.node_config.persist_path;
if (not state_path.empty()) {
state_path += "_port.txt";
std::ifstream inConfig(state_path);
if (inConfig.is_open()) {
in_port_t port;
if (inConfig >> port) {
if (context.logger)
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
if (local4.getPort() == 0)
local4.setPort(port);
}
if (inConfig >> port) {
if (context.logger)
context.logger->d("[runner %p] Using IPv6 port %hu from saved configuration", this, port);
if (local6.getPort() == 0)
local6.setPort(port);
}
}
}
if (not context.sock)
context.sock.reset(new net::UdpSocket(local4, local6, context.logger));
if (not state_path.empty()) {
std::ofstream outConfig(state_path);
outConfig << context.sock->getBoundRef(AF_INET).getPort() << std::endl;
outConfig << context.sock->getBoundRef(AF_INET6).getPort() << std::endl;
}
run(config, std::move(context));
}
}
@@ -206,7 +174,7 @@ DhtRunner::run(const Config& config, Context&& context)
if (not pending_ops_prio.empty())
return true;
auto s = getStatus();
if (not pending_ops.empty() and (s == NodeStatus::Connected or s == NodeStatus::Disconnected))
if (not pending_ops.empty() and (s == NodeStatus::Connected or (s == NodeStatus::Disconnected and not bootstraping)))
return true;
}
return false;
@@ -332,6 +300,7 @@ DhtRunner::join()
if (running.exchange(State::Idle) == State::Idle)
return;
cv.notify_all();
bootstrap_cv.notify_all();
#ifdef OPENDHT_PEER_DISCOVERY
if (peerDiscovery_)
peerDiscovery_->stop();
@@ -346,6 +315,9 @@ DhtRunner::join()
if (dht_thread.joinable())
dht_thread.join();
if (bootstrap_thread.joinable())
bootstrap_thread.join();
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops = decltype(pending_ops)();
@@ -507,10 +479,8 @@ DhtRunner::getNodeInfo() const {
info.node_id = dht->getNodeId();
info.ipv4 = dht->getNodesStats(AF_INET);
info.ipv6 = dht->getNodesStats(AF_INET6);
if (auto sock = dht->getSocket()) {
info.bound4 = sock->getBoundRef(AF_INET).getPort();
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
}
info.metrics = dht->getNodeMetrics();
info.ongoing_ops = ongoing_ops;
}
info.ongoing_ops = ongoing_ops;
return info;
@@ -528,10 +498,7 @@ DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
info.node_id = dht.getNodeId();
info.ipv4 = dht.getNodesStats(AF_INET);
info.ipv6 = dht.getNodesStats(AF_INET6);
if (auto sock = dht.getSocket()) {
info.bound4 = sock->getBoundRef(AF_INET).getPort();
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
}
info.metrics = dht.getNodeMetrics();
info.ongoing_ops = ongoing_ops;
cb(std::move(sinfo));
opEnded();
@@ -620,7 +587,7 @@ DhtRunner::loop_()
{
std::lock_guard<std::mutex> lck(storage_mtx);
auto s = getStatus();
ops = (pending_ops_prio.empty() && (s == NodeStatus::Connected or s == NodeStatus::Disconnected)) ?
ops = (pending_ops_prio.empty() && (s == NodeStatus::Connected or (s == NodeStatus::Disconnected and not bootstraping))) ?
std::move(pending_ops) : std::move(pending_ops_prio);
}
while (not ops.empty()) {
@@ -675,11 +642,20 @@ DhtRunner::loop_()
if (dropped)
std::cerr << "Dropped " << dropped << " packets with high delay" << std::endl;
NodeStatus nstatus4 = dht->updateStatus(AF_INET);
NodeStatus nstatus6 = dht->updateStatus(AF_INET6);
NodeStatus nstatus4 = dht->getStatus(AF_INET);
NodeStatus nstatus6 = dht->getStatus(AF_INET6);
if (nstatus4 != status4 || nstatus6 != status6) {
status4 = nstatus4;
status6 = nstatus6;
if (status4 == NodeStatus::Disconnected and status6 == NodeStatus::Disconnected) {
// We have lost connection with the DHT. Try to recover using bootstrap nodes.
std::unique_lock<std::mutex> lck(bootstrap_mtx);
bootstrap_nodes = bootstrap_nodes_all;
tryBootstrapContinuously();
} else {
std::unique_lock<std::mutex> lck(bootstrap_mtx);
bootstrap_nodes.clear();
}
if (statusCb)
statusCb(status4, status6);
}
@@ -926,34 +902,89 @@ DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, Done
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb), permanent);
}
void
DhtRunner::tryBootstrapContinuously()
{
if (bootstrap_thread.joinable()) {
if (bootstraping)
return; // already running
else
bootstrap_thread.join();
}
bootstraping = true;
bootstrap_thread = std::thread([this]() {
auto next = clock::now();
do {
decltype(bootstrap_nodes) nodes;
{
std::lock_guard<std::mutex> lck(bootstrap_mtx);
nodes = bootstrap_nodes;
}
next += BOOTSTRAP_PERIOD;
{
std::mutex mtx;
std::unique_lock<std::mutex> blck(mtx);
unsigned ping_count(0);
// Reverse: try last inserted bootstrap nodes first
for (auto it = nodes.rbegin(); it != nodes.rend(); it++) {
++ping_count;
try {
bootstrap(SockAddr::resolve(it->first, it->second), [&](bool) {
if (running != State::Running)
return;
{
std::unique_lock<std::mutex> blck(mtx);
--ping_count;
}
bootstrap_cv.notify_all();
});
} catch (std::invalid_argument& e) {
--ping_count;
std::cerr << e.what() << std::endl;
}
}
// wait at least until the next BOOTSTRAP_PERIOD
bootstrap_cv.wait_until(blck, next, [&]() { return running != State::Running; });
// wait for bootstrap requests to end.
if (running != State::Running)
bootstrap_cv.wait(blck, [&]() { return running != State::Running or ping_count == 0; });
}
// update state
{
std::lock_guard<std::mutex> lck(dht_mtx);
bootstraping = running == State::Running and
status4 == NodeStatus::Disconnected and
status6 == NodeStatus::Disconnected;
}
} while (bootstraping);
});
}
void
DhtRunner::bootstrap(const std::string& host, const std::string& service)
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([host, service] (SecureDht& dht) mutable {
dht.addBootstrap(host, service);
});
cv.notify_all();
std::lock_guard<std::mutex> lck(bootstrap_mtx);
bootstrap_nodes_all.emplace_back(host, service);
bootstrap_nodes.emplace_back(host, service);
tryBootstrapContinuously();
}
void
DhtRunner::bootstrap(const std::string& hostService)
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([host_service = splitPort(hostService)] (SecureDht& dht) mutable {
dht.addBootstrap(host_service.first, host_service.second);
});
cv.notify_all();
std::lock_guard<std::mutex> lck(bootstrap_mtx);
auto host_service = splitPort(hostService);
bootstrap_nodes_all.emplace_back(host_service.first, host_service.second);
bootstrap_nodes.emplace_back(std::move(host_service.first), std::move(host_service.second));
tryBootstrapContinuously();
}
void
DhtRunner::clearBootstrap()
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([] (SecureDht& dht) mutable {
dht.clearBootstrap();
});
cv.notify_all();
std::lock_guard<std::mutex> lck(bootstrap_mtx);
bootstrap_nodes_all.clear();
}
void
+51 -428
View File
@@ -20,31 +20,17 @@
#include "log_enable.h"
#include "crypto.h"
#include "base64.h"
#include "compat/os_cert.h"
#include <asio.hpp>
#include <restinio/impl/tls_socket.hpp>
#include <http_parser.h>
#include <json/json.h>
#include <openssl/ocsp.h>
#include <openssl/ssl.h>
#include <openssl/asn1.h>
#include <crypto/x509.h>
#define MAXAGE_SEC (14*24*60*60)
#define JITTER_SEC (60)
#define OCSP_MAX_RESPONSE_SIZE (20480)
namespace dht {
namespace http {
constexpr const char HTTP_HEADER_CONTENT_TYPE_JSON[] = "application/json";
constexpr const char HTTP_HEADER_DELIM[] = "\r\n\r\n";
constexpr const char HTTP_PROTOCOL[] = "http://";
constexpr const char HTTPS_PROTOCOL[] = "https://";
constexpr const char ORIGIN_PROTOCOL[] = "//";
constexpr char HTTP_HEADER_CONTENT_TYPE_JSON[] = "application/json";
constexpr char HTTP_HEADER_DELIM[] = "\r\n\r\n";
constexpr unsigned MAX_REDIRECTS {5};
Url::Url(const std::string& url): url(url)
@@ -56,6 +42,7 @@ Url::Url(const std::string& url): url(url)
addr_begin = proto_end + 3;
if (url.substr(0, proto_end) == "https"){
protocol = "https";
service = protocol;
}
}
// host and service
@@ -81,21 +68,6 @@ Url::Url(const std::string& url): url(url)
}
}
std::string
Url::toString() const
{
std::stringstream ss;
if (not protocol.empty()) {
ss << protocol << "://";
}
ss << host;
if (not service.empty()) {
ss << ':' << service;
}
ss << target;
return ss.str();
}
// connection
std::atomic_uint Connection::ids_ {1};
@@ -103,16 +75,10 @@ std::atomic_uint Connection::ids_ {1};
Connection::Connection(asio::io_context& ctx, const bool ssl, std::shared_ptr<dht::Logger> l)
: id_(Connection::ids_++), ctx_(ctx), istream_(&read_buf_), logger_(l)
{
if (ssl) {
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::tls_client);
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
#ifdef __ANDROID__
ssl_ctx_->add_verify_path("/system/etc/security/cacerts");
#elif defined(WIN32) || defined(__APPLE__)
addSystemCaCertificates(ssl_ctx_->native_handle(), l);
#else
if (ssl){
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
ssl_ctx_->set_default_verify_paths();
#endif
ssl_ctx_->set_verify_mode(asio::ssl::verify_none);
ssl_socket_ = std::make_unique<ssl_socket_t>(ctx_, ssl_ctx_);
if (logger_)
logger_->d("[connection:%i] start https session", id_);
@@ -128,15 +94,8 @@ Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::crypto::Certi
const dht::crypto::Identity& identity, std::shared_ptr<dht::Logger> l)
: id_(Connection::ids_++), ctx_(ctx), istream_(&read_buf_), logger_(l)
{
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::tls_client);
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
#ifdef __ANDROID__
ssl_ctx_->add_verify_path("/system/etc/security/cacerts");
#elif WIN32
addSystemCaCertificates(ssl_ctx_->native_handle(), l);
#else
ssl_ctx_ = std::make_shared<asio::ssl::context>(asio::ssl::context::sslv23);
ssl_ctx_->set_default_verify_paths();
#endif
asio::error_code ec;
if (server_ca){
auto ca = server_ca->toString(false/*chain*/);
@@ -161,6 +120,7 @@ Connection::Connection(asio::io_context& ctx, std::shared_ptr<dht::crypto::Certi
else if (logger_)
logger_->d("[connection:%i] client certificate %s", id_, identity.second->getUID().c_str());
}
ssl_ctx_->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
ssl_socket_ = std::make_unique<ssl_socket_t>(ctx_, ssl_ctx_);
}
@@ -199,305 +159,30 @@ Connection::is_ssl() const
return ssl_ctx_ ? true : false;
}
static time_t
parse_ocsp_time(ASN1_GENERALIZEDTIME* gt)
{
struct tm tm;
time_t rv = -1;
if (gt == nullptr)
return -1;
// RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME
if (ASN1_time_parse((const char*)gt->data, gt->length, &tm, V_ASN1_GENERALIZEDTIME) == -1)
return -1;
if ((rv = timegm(&tm)) == -1)
return -1;
return rv;
}
static inline X509*
cert_from_chain(STACK_OF(X509)* fullchain)
{
return sk_X509_value(fullchain, 0);
}
static X509*
issuer_from_chain(STACK_OF(X509)* fullchain)
{
X509 *cert, *issuer;
X509_NAME *issuer_name;
cert = cert_from_chain(fullchain);
if ((issuer_name = X509_get_issuer_name(cert)) == nullptr)
return nullptr;
issuer = X509_find_by_subject(fullchain, issuer_name);
return issuer;
}
using OscpRequestPtr = std::unique_ptr<OCSP_REQUEST, decltype(&OCSP_REQUEST_free)>;
struct OscpRequestInfo {
OscpRequestPtr req {nullptr, &OCSP_REQUEST_free};
std::vector<uint8_t> data;
std::string url;
};
static std::unique_ptr<OscpRequestInfo>
ocspRequestFromCert(STACK_OF(X509)* fullchain, const std::shared_ptr<Logger>& logger, bool nonce = false)
{
if (fullchain == nullptr)
return {};
if (sk_X509_num(fullchain) <= 1) {
if (logger)
logger->e("Cert does not contain a cert chain");
return {};
}
X509* cert = cert_from_chain(fullchain);
if (cert == nullptr) {
if (logger)
logger->e("No certificate found");
return {};
}
X509* issuer = issuer_from_chain(fullchain);
if (issuer == nullptr) {
if (logger)
logger->e("Unable to find issuer for cert");
return {};
}
auto urls = X509_get1_ocsp(cert);
if (urls == nullptr || sk_OPENSSL_STRING_num(urls) <= 0) {
if (logger)
logger->e("Certificate contains no OCSP url");
return {};
}
auto url = sk_OPENSSL_STRING_value(urls, 0);
if (url == nullptr)
return {};
auto request = std::make_unique<OscpRequestInfo>();
request->req = OscpRequestPtr(OCSP_REQUEST_new(), &OCSP_REQUEST_free);
request->url = strdup(url);
X509_email_free(urls);
OCSP_CERTID* id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
if (id == nullptr) {
if (logger)
logger->e("Unable to get certificate id from cert");
return {};
}
if (OCSP_request_add0_id(request->req.get(), id) == nullptr) {
if (logger)
logger->e("Unable to add certificate id to request");
return {};
}
if (nonce)
OCSP_request_add1_nonce(request->req.get(), nullptr, -1);
int size;
uint8_t* data {nullptr};
if ((size = i2d_OCSP_REQUEST(request->req.get(), &data)) <= 0) {
if (logger)
logger->e("Unable to encode ocsp request");
return {};
}
if (data == nullptr) {
if (logger)
logger->e("Unable to allocte memory");
return {};
}
request->data = std::vector<uint8_t>(data, data+size);
free(data);
return request;
}
bool
ocspValidateResponse(const OscpRequestInfo& info, STACK_OF(X509)* fullchain, const std::string& response, X509_STORE *store, const std::shared_ptr<Logger>& logger)
{
ASN1_GENERALIZEDTIME *revtime = nullptr, *thisupd = nullptr, *nextupd = nullptr;
const uint8_t* p = (const uint8_t*)response.data();
int status, cert_status=0, crl_reason=0;
time_t now, rev_t = -1, this_t, next_t;
OCSP_RESPONSE *resp;
OCSP_BASICRESP *bresp;
OCSP_CERTID *cid;
X509* cert = cert_from_chain(fullchain);
if (cert == nullptr) {
if (logger)
logger->e("No certificate found");
return false;
}
X509* issuer = issuer_from_chain(fullchain);
if (issuer == nullptr) {
if (logger)
logger->e("Unable to find issuer for cert");
return false;
}
if ((cid = OCSP_cert_to_id(nullptr, cert, issuer)) == nullptr) {
if (logger)
logger->e("Unable to get issuer cert/CID");
return false;
}
if ((resp = d2i_OCSP_RESPONSE(nullptr, &p, response.size())) == nullptr) {
if (logger)
logger->e("OCSP response unserializable");
return false;
}
if ((bresp = OCSP_response_get1_basic(resp)) == nullptr) {
if (logger)
logger->e("Failed to load OCSP response");
return false;
}
if (OCSP_basic_verify(bresp, fullchain, store, OCSP_TRUSTOTHER) != 1) {
if (logger)
logger->w("OCSP verify failed");
return false;
}
printf("OCSP response signature validated\n");
status = OCSP_response_status(resp);
if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
if (logger)
logger->w("OCSP Failure: code %d (%s)", status, OCSP_response_status_str(status));
return false;
}
// Check the nonce if we sent one
if (OCSP_check_nonce(info.req.get(), bresp) <= 0) {
if (logger)
logger->w("No OCSP nonce, or mismatch");
return false;
}
if (OCSP_resp_find_status(bresp, cid, &cert_status, &crl_reason,
&revtime, &thisupd, &nextupd) != 1) {
if (logger)
logger->w("OCSP verify failed: no result for cert");
return false;
}
if (revtime && (rev_t = parse_ocsp_time(revtime)) == -1) {
if (logger)
logger->w("Unable to parse revocation time in OCSP reply");
return false;
}
// Belt and suspenders, Treat it as revoked if there is either
// a revocation time, or status revoked.
if (rev_t != -1 || cert_status == V_OCSP_CERTSTATUS_REVOKED) {
if (logger)
logger->w("Invalid OCSP reply: certificate is revoked");
if (rev_t != -1) {
if (logger)
logger->w("Certificate revoked at: %s", ctime(&rev_t));
}
return false;
}
if ((this_t = parse_ocsp_time(thisupd)) == -1) {
if (logger)
logger->w("unable to parse this update time in OCSP reply");
return false;
}
if ((next_t = parse_ocsp_time(nextupd)) == -1) {
if (logger)
logger->w("unable to parse next update time in OCSP reply");
return false;
}
// Don't allow this update to precede next update
if (this_t >= next_t) {
if (logger)
logger->w("Invalid OCSP reply: this update >= next update");
return false;
}
now = time(nullptr);
// Check that this update is not more than JITTER seconds in the future.
if (this_t > now + JITTER_SEC) {
if (logger)
logger->e("Invalid OCSP reply: this update is in the future (%s)", ctime(&this_t));
return false;
}
// Check that this update is not more than MAXSEC in the past.
if (this_t < now - MAXAGE_SEC) {
if (logger)
logger->e("Invalid OCSP reply: this update is too old (%s)", ctime(&this_t));
return false;
}
// Check that next update is still valid
if (next_t < now - JITTER_SEC) {
if (logger)
logger->w("Invalid OCSP reply: reply has expired (%s)", ctime(&next_t));
return false;
}
if (logger) {
logger->d("OCSP response validated");
logger->d(" This Update: %s", ctime(&this_t));
logger->d(" Next Update: %s", ctime(&next_t));
}
return true;
}
void
Connection::set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode)
Connection::set_ssl_verification(const asio::ip::tcp::endpoint& endpoint, const asio::ssl::verify_mode verify_mode)
{
std::lock_guard<std::mutex> lock(mutex_);
if (ssl_socket_) {
// Set SNI Hostname (many hosts need this to handshake successfully)
SSL_set_tlsext_host_name(ssl_socket_->asio_ssl_stream().native_handle(), hostname.c_str());
if (ssl_socket_ and verify_mode != asio::ssl::verify_none) {
ssl_socket_->asio_ssl_stream().set_verify_mode(verify_mode);
if (verify_mode != asio::ssl::verify_none) {
ssl_socket_->asio_ssl_stream().set_verify_callback([
id = id_, logger = logger_, hostname
] (bool preverified, asio::ssl::verify_context& ctx) -> bool {
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
if (logger) {
char subject_name[1024];
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 1024);
logger->d("[connection:%i] verify %s compliance to RFC 2818:\n%s", id, hostname.c_str(), subject_name);
}
// starts from CA and goes down the presented chain
auto verifier = asio::ssl::rfc2818_verification(hostname);
bool verified = verifier(preverified, ctx);
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
if (verify_ec != 0 /*X509_V_OK*/ and logger)
logger->e("[http::connection:%i] ssl verification error=%i %d", id, verify_ec, verified);
if (verified) {
auto chain = X509_STORE_CTX_get1_chain(ctx.native_handle());
if (auto ocspInfo = ocspRequestFromCert(chain, logger)) {
if (logger)
logger->w("[http::connection:%i] TLS OCSP server: %s, request size: %zu", id, ocspInfo->url.c_str(), ocspInfo->data.size());
bool ocspVerified = false;
asio::io_context io_ctx;
auto ocspReq = std::make_shared<Request>(io_ctx, ocspInfo->url, [&](const Response& ocspResp){
if (ocspResp.status_code == 200) {
ocspVerified = ocspValidateResponse(*ocspInfo, chain, ocspResp.body, ctx.native_handle()->ctx, logger);
} else {
if (logger)
logger->w("[http::connection:%i] TLS OCSP check error", id);
}
}, logger);
ocspReq->set_method(restinio::http_method_post());
ocspReq->set_body({ocspInfo->data.begin(), ocspInfo->data.end()});
ocspReq->send();
io_ctx.run();
if (not ocspVerified)
return false;
}
}
return verified;
}
);
}
ssl_socket_->asio_ssl_stream().set_verify_callback([
id = id_,
logger = logger_,
hostname = endpoint.address().to_string()
] (bool preverified, asio::ssl::verify_context& ctx) -> bool {
if (logger)
logger->d("[connection:%i] verify %s compliance to RFC 2818", id, hostname.c_str());
if (preverified)
return preverified;
// starts from CA and goes down the presented chain
auto verifier = asio::ssl::rfc2818_verification(hostname);
bool verified = verifier(preverified, ctx);
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
if (verified != 0 /*X509_V_OK*/ and logger)
logger->e("[http::connection:%i] ssl verification error=%i", id, verify_ec);
return verified;
}
);
}
}
@@ -557,11 +242,9 @@ Connection::async_handshake(HandlerCb cb)
if (this_.logger_) {
if (verify_ec == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT /*18*/
|| verify_ec == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN /*19*/)
this_.logger_->d("[connection:%i] self-signed certificate in handshake: %i", this_.id_, verify_ec);
this_.logger_->d("[connection:%i] allow self-signed certificate in handshake", this_.id_);
else if (verify_ec != X509_V_OK)
this_.logger_->e("[connection:%i] verify handshake error: %i", this_.id_, verify_ec);
else
this_.logger_->w("[connection:%i] verify handshake success", this_.id_);
}
}
if (cb)
@@ -673,7 +356,7 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
Resolver::Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger)
: url_(url), resolver_(ctx), destroyed_(std::make_shared<bool>(false)), logger_(logger)
{
resolve(url_.host, url_.service.empty() ? url_.protocol : url_.service);
resolve(url_.host, url_.service);
}
Resolver::Resolver(asio::io_context& ctx, const std::string& host, const std::string& service,
@@ -683,7 +366,7 @@ Resolver::Resolver(asio::io_context& ctx, const std::string& host, const std::st
url_.host = host;
url_.service = service;
url_.protocol = (ssl ? "https" : "http");
resolve(url_.host, url_.service.empty() ? url_.protocol : url_.service);
resolve(url_.host, url_.service);
}
Resolver::Resolver(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint> endpoints, const bool ssl,
@@ -746,12 +429,13 @@ void
Resolver::resolve(const std::string& host, const std::string& service)
{
asio::ip::tcp::resolver::query query_(host, service);
resolver_.async_resolve(query_, [this, host, service, destroyed = destroyed_]
(const asio::error_code& ec, asio::ip::tcp::resolver::results_type endpoints)
{
if (ec == asio::error::operation_aborted or *destroyed)
return;
if (logger_) {
if (logger_){
if (ec)
logger_->e("[http:client] [resolver] error for %s:%s: %s",
host.c_str(), service.c_str(), ec.message().c_str());
@@ -799,29 +483,7 @@ Request::Request(asio::io_context& ctx, const std::string& url, const Json::Valu
logger_->e("[http:request:%i] can't parse response to json", id_, err.c_str());
}
if (jsoncb)
jsoncb(std::move(json), response);
});
}
Request::Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb, std::shared_ptr<dht::Logger> logger)
: logger_(std::move(logger)), id_(Request::ids_++), ctx_(ctx),
resolver_(std::make_shared<Resolver>(ctx, url, logger))
{
init_default_headers();
set_header_field(restinio::http_field_t::accept, HTTP_HEADER_CONTENT_TYPE_JSON);
Json::StreamWriterBuilder wbuilder;
set_method(restinio::http_method_get());
add_on_done_callback([this, jsoncb](const Response& response) {
Json::Value json;
if (response.status_code != 0) {
std::string err;
Json::CharReaderBuilder rbuilder;
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(response.body.data(), response.body.data() + response.body.size(), &json, &err) and logger_)
logger_->e("[http:request:%i] can't parse response to json", id_, err.c_str());
}
if (jsoncb)
jsoncb(std::move(json), response);
jsoncb(std::move(json), response.status_code);
});
}
@@ -928,7 +590,7 @@ Request::set_method(restinio::http_method_id_t method) {
void
Request::set_target(std::string target) {
header_.request_target(target.empty() ? "/" : std::move(target));
header_.request_target(std::move(target));
}
void
@@ -1100,20 +762,18 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
eps.append(endpoint.address().to_string() + ":" + std::to_string(endpoint.port()) + " ");
logger_->d("[http:request:%i] connect begin: %s", id_, eps.c_str());
}
bool isHttps = get_url().protocol == "https";
if (isHttps) {
if (server_ca_ or client_identity_.first)
if (get_url().protocol == "https"){
if (server_ca_)
conn_ = std::make_shared<Connection>(ctx_, server_ca_, client_identity_, logger_);
else
conn_ = std::make_shared<Connection>(ctx_, true/*ssl*/, logger_);
conn_->set_ssl_verification(get_url().host, asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
}
else
conn_ = std::make_shared<Connection>(ctx_, false/*ssl*/, logger_);
// try to connect to any until one works
std::weak_ptr<Request> wthis = shared_from_this();
conn_->async_connect(std::move(endpoints), [wthis, cb, isHttps]
conn_->async_connect(std::move(endpoints), [wthis, cb]
(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint){
auto sthis = wthis.lock();
if (not sthis)
@@ -1128,16 +788,23 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
if (this_.logger_)
this_.logger_->e("[http:request:%i] connect failed with all endpoints: %s", this_.id_, ec.message().c_str());
} else {
// if (this_.logger_)
// this_.logger_->d("[http:request:%i] connect success", this_.id_);
const auto& url = this_.get_url();
auto port = endpoint.port();
if ((!isHttps && port == (in_port_t)80)
|| (isHttps && port == (in_port_t)443))
if ((url.protocol == "http" && port == (in_port_t)80)
|| (url.protocol == "https" && port == (in_port_t)443))
this_.set_header_field(restinio::http_field_t::host, url.host);
else
this_.set_header_field(restinio::http_field_t::host, url.host + ":" + std::to_string(port));
if (isHttps) {
if (this_.conn_ and this_.conn_->is_open() and this_.conn_->is_ssl()) {
if (url.protocol == "https") {
if (this_.server_ca_)
this_.conn_->set_ssl_verification(endpoint, asio::ssl::verify_peer
| asio::ssl::verify_fail_if_no_peer_cert);
if (this_.conn_ and this_.conn_->is_open() and this_.conn_->is_ssl()){
this_.conn_->async_handshake([id = this_.id_, cb, logger = this_.logger_](const asio::error_code& ec){
if (ec == asio::error::operation_aborted)
return;
@@ -1264,7 +931,7 @@ Request::handle_request(const asio::error_code& ec)
}
void
Request::handle_response(const asio::error_code& ec, size_t /* n_bytes */)
Request::handle_response(const asio::error_code& ec, size_t n_bytes)
{
std::lock_guard<std::mutex> lock(mutex_);
if (ec && ec != asio::error::eof){
@@ -1321,10 +988,7 @@ Request::onHeadersComplete() {
}
if (follow_redirect and num_redirect < MAX_REDIRECTS) {
auto newUrl = getRelativePath(get_url(), location_it->second);
if (logger_)
logger_->w("[http:client] [request:%i] redirect to %s", id_, newUrl.c_str());
auto next = std::make_shared<Request>(ctx_, newUrl, logger_);
auto next = std::make_shared<Request>(ctx_, location_it->second, logger_);
next->set_method(header_.method());
next->headers_ = std::move(headers_);
next->body_ = std::move(body_);
@@ -1354,46 +1018,5 @@ Request::onHeadersComplete() {
}
}
bool startsWith(const std::string& haystack, const std::string& needle) {
return needle.length() <= haystack.length()
&& std::equal(needle.begin(), needle.end(), haystack.begin());
}
std::string
Request::getRelativePath(const Url& origin, const std::string& path)
{
if (startsWith(path, HTTP_PROTOCOL)
|| startsWith(path, HTTPS_PROTOCOL)
|| startsWith(path, ORIGIN_PROTOCOL)) {
// Absolute path
return path;
}
Url newPath = origin;
if (not path.empty() and path[0] == '/') {
newPath.target = path;
} else {
if (newPath.target.empty())
newPath.target.push_back('/');
newPath.target += path;
}
return newPath.toString();
}
const Response&
Request::await()
{
std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
std::condition_variable cv;
bool ok {false};
add_on_done_callback([&](const Response& resp){
std::lock_guard<std::mutex> lk(mtx);
ok = true;
cv.notify_all();
});
cv.wait(lock, [&]{ return ok; });
return response_;
}
} // namespace http
} // namespace dht
+1 -2
View File
@@ -30,9 +30,8 @@ namespace dht {
struct Listener {
time_point time;
Query query;
int version;
Listener(time_point t, Query&& q, int version = 0) : time(t), query(std::move(q)), version(version) {}
Listener(time_point t, Query&& q) : time(t), query(std::move(q)) {}
void refresh(time_point t, Query&& q) {
time = t;
+1 -2
View File
@@ -31,8 +31,7 @@ enum class MessageType {
Refresh,
Listen,
ValueData,
ValueUpdate,
UpdateValue
ValueUpdate
};
} /* namespace net */
+125 -181
View File
@@ -48,6 +48,23 @@ static constexpr uint8_t v4prefix[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xF
constexpr unsigned SEND_NODES {8};
/* Transaction-ids are 4-bytes long, with the first two bytes identifying
* the kind of request, and the remaining two a sequence number in
* host order.
*/
struct TransId final : public std::array<uint8_t, 4> {
TransId() { std::fill(begin(), end(), 0); }
TransId(const std::array<char, 4>& o) { std::copy(o.begin(), o.end(), begin()); }
TransId(uint32_t id) {
*reinterpret_cast<uint32_t*>(data()) = htonl(id);
}
uint32_t toInt() const {
return ntohl(*reinterpret_cast<const uint32_t*>(&(*this)[0]));
}
};
struct NetworkEngine::PartialMessage {
SockAddr from;
time_point start;
@@ -123,15 +140,11 @@ void
NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash, want_t want,
const Blob& ntoken, std::vector<Sp<Node>>&& nodes,
std::vector<Sp<Node>>&& nodes6, std::vector<Sp<Value>>&& values,
const Query& query, int version)
const Query& query)
{
auto nnodes = bufferNodes(node->getFamily(), hash, want, nodes, nodes6);
try {
if (version >= 1) {
sendUpdateValues(node, hash, values, scheduler.time(), ntoken, socket_id);
} else {
sendNodesValues(node->getAddr(), socket_id, nnodes.first, nnodes.second, values, query, ntoken);
}
sendNodesValues(node->getAddr(), socket_id, nnodes.first, nnodes.second, values, query, ntoken);
} catch (const std::overflow_error& e) {
if (logger_)
logger_->e("Can't send value: buffer not large enough !");
@@ -139,103 +152,63 @@ NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash,
}
void
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(config.network?1:0));
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
pk.pack(KEY_U);
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (not token.empty()) {
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(KEY_REQ_REFRESHED);
pk.pack(values);
if (logger_)
logger_->d(n->id, "[node %s] sending %zu refreshed values", n->toString().c_str(), values.size());
}
pk.pack(version >= 1 ? KEY_A : KEY_U);
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (version >= 1) {
pk.pack(KEY_REQ_SID); pk.pack(socket_id);
}
if (not token.empty()) {
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(KEY_REQ_REFRESHED);
pk.pack(values);
if (logger_)
logger_->d(n->id, "[node %s] sending %zu refreshed values", n->toString().c_str(), values.size());
}
pk.pack(KEY_Y); pk.pack(version >= 1 ? KEY_Q : KEY_R);
pk.pack(KEY_TID); pk.pack(socket_id);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
if (version >= 1) {
Tid tid (n->getNewTid());
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
pk.pack(KEY_TID); pk.pack(tid);
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request&, ParsedMessage&&) { /* on done */ },
[=](const Request&, bool) { /* on expired */ }
);
sendRequest(req);
++out_stats.updateValue;
return;
}
pk.pack(KEY_TID); pk.pack(socket_id);
// send response
send(n->getAddr(), buffer.data(), buffer.size());
}
void
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(config.network?1:0));
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
pk.pack(KEY_U);
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (not token.empty()) {
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(KEY_REQ_EXPIRED);
pk.pack(values);
if (logger_)
logger_->d(n->id, "[node %s] sending %zu expired values", n->toString().c_str(), values.size());
}
pk.pack(version >= 1 ? KEY_A : KEY_U);
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (version >= 1) {
pk.pack(KEY_REQ_SID); pk.pack(socket_id);
}
if (not token.empty()) {
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(KEY_REQ_EXPIRED);
pk.pack(values);
if (logger_)
logger_->d(n->id, "[node %s] sending %zu expired values", n->toString().c_str(), values.size());
}
pk.pack(KEY_Y); pk.pack(version >= 1 ? KEY_Q : KEY_R);
pk.pack(KEY_TID); pk.pack(socket_id);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
if (version >= 1) {
Tid tid (n->getNewTid());
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
pk.pack(KEY_TID); pk.pack(tid);
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request&, ParsedMessage&&) { /* on done */ },
[=](const Request&, bool) { /* on expired */ }
);
sendRequest(req);
++out_stats.updateValue;
return;
}
pk.pack(KEY_TID); pk.pack(socket_id);
// send response
send(n->getAddr(), buffer.data(), buffer.size());
}
@@ -308,9 +281,6 @@ NetworkEngine::requestStep(Sp<Request> sreq)
++req.attempt_count;
req.attempt_duration +=
req.attempt_duration + uniform_duration_distribution<>(0ms, ((duration)Node::MAX_RESPONSE_TIME)/4)(rd);
if (not req.parts.empty()){
sendValueParts(req.tid, req.parts, node.getAddr());
}
}
std::weak_ptr<Request> wreq = sreq;
scheduler.add(req.last_try + req.attempt_duration, [this,wreq] {
@@ -560,8 +530,7 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
{
req->last_try = time_point::min();
req->reply_time = time_point::min();
if (not req->setError(DhtProtocolException {msg->error_code}))
onError(req, DhtProtocolException {msg->error_code});
onError(req, DhtProtocolException {msg->error_code});
} else {
if (logIncoming_)
if (logger_)
@@ -573,11 +542,8 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
case MessageType::Reply:
if (req) { /* request reply */
auto& r = *req;
if (r.getType() == MessageType::AnnounceValue
or r.getType() == MessageType::Listen
or r.getType() == MessageType::Refresh) {
if (r.getType() == MessageType::AnnounceValue or r.getType() == MessageType::Listen)
r.node->authSuccess();
}
r.reply_time = scheduler.time();
deserializeNodes(*msg, from);
@@ -648,29 +614,18 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
if (logIncoming_ and logger_)
logger_->d(msg->info_hash, node->id, "[node %s] got 'listen' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
++in_stats.listen;
RequestAnswer answer = onListen(node, msg->info_hash, msg->token, msg->socket_id, std::move(msg->query), msg->version);
RequestAnswer answer = onListen(node, msg->info_hash, msg->token, msg->socket_id, std::move(msg->query));
auto nnodes = bufferNodes(from.getFamily(), msg->info_hash, msg->want, answer.nodes4, answer.nodes6);
sendListenConfirmation(from, msg->tid);
break;
}
case MessageType::UpdateValue: {
if (logIncoming_ and logger_)
logger_->d(msg->info_hash, node->id, "[node %s] got 'update' request for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
++in_stats.updateValue;
if (auto rsocket = node->getSocket(msg->socket_id))
rsocket->on_receive(node, std::move(*msg));
else if (logger_)
logger_->e(msg->info_hash, node->id, "[node %s] 'update' request without socket for %s", node->toString().c_str(), msg->info_hash.toString().c_str());
sendListenConfirmation(from, msg->tid);
break;
}
default:
break;
}
} catch (const std::overflow_error& e) {
if (logger_)
logger_->e("Can't send value: buffer not large enough !");
} catch (const DhtProtocolException& e) {
} catch (DhtProtocolException& e) {
sendError(from, msg->tid, e.getCode(), e.getMsg().c_str(), true);
}
}
@@ -696,7 +651,7 @@ NetworkEngine::send(const SockAddr& addr, const char *buf, size_t len, bool conf
Sp<Request>
NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (node->getNewTid());
TransId tid (node->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
@@ -705,14 +660,15 @@ NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& o
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_Q); pk.pack(QUERY_PING);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::Ping, tid, node,
auto req = std::make_shared<Request>(MessageType::Ping, tid.toInt(), node,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&&) {
if (logger_)
@@ -742,7 +698,9 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
pk.pack(KEY_REQ_ID); pk.pack(myid);
insertAddr(pk, addr);
pk.pack(KEY_TID); pk.pack(tid);
TransId t (tid);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
@@ -755,7 +713,7 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
Sp<Request>
NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (n->getNewTid());
TransId tid (n->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
@@ -771,14 +729,15 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
}
pk.pack(KEY_Q); pk.pack(QUERY_FIND);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::FindNode, tid, n,
auto req = std::make_shared<Request>(MessageType::FindNode, tid.toInt(), n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
if (on_done) {
@@ -800,7 +759,7 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
Sp<Request>
NetworkEngine::sendGetValues(Sp<Node> n, const InfoHash& info_hash, const Query& query, want_t want,
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (n->getNewTid());
TransId tid (n->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
@@ -824,14 +783,15 @@ NetworkEngine::sendGetValues(Sp<Node> n, const InfoHash& info_hash, const Query&
}
pk.pack(KEY_Q); pk.pack(QUERY_GET);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::GetValues, tid, n,
auto req = std::make_shared<Request>(MessageType::GetValues, tid.toInt(), n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
if (on_done) {
@@ -933,7 +893,7 @@ NetworkEngine::packValueHeader(msgpack::sbuffer& buffer, const std::vector<Sp<Va
}
void
NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const SockAddr& addr)
NetworkEngine::sendValueParts(const TransId& tid, const std::vector<Blob>& svals, const SockAddr& addr)
{
msgpack::sbuffer buffer;
unsigned i=0;
@@ -948,7 +908,8 @@ NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const Soc
pk.pack(KEY_NETID); pk.pack(config.network);
}
pk.pack(KEY_Y); pk.pack(KEY_V);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_V); pk.pack_map(1);
pk.pack(i); pk.pack_map(2);
pk.pack(std::string("o")); pk.pack(start);
@@ -1003,7 +964,9 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
}
}
pk.pack(KEY_TID); pk.pack(tid);
TransId t (tid);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
@@ -1073,35 +1036,54 @@ NetworkEngine::sendListen(Sp<Node> n,
const InfoHash& hash,
const Query& query,
const Blob& token,
Tid socketId,
Sp<Request> previous,
RequestCb&& on_done,
RequestExpiredCb&& on_expired)
RequestExpiredCb&& on_expired,
SocketCb&& socket_cb)
{
Tid tid (n->getNewTid());
Tid socket;
TransId tid (n->getNewTid());
if (previous and previous->node == n) {
socket = previous->getSocket();
} else {
if (previous)
if (logger_)
logger_->e(hash, "[node %s] trying refresh listen contract with wrong node", previous->node->toString().c_str());
socket = n->openSocket(std::move(socket_cb));
}
if (not socket) {
if (logger_)
logger_->e(hash, "[node %s] unable to get a valid socket for listen. Aborting listen", n->toString().c_str());
return {};
}
TransId sid(socket);
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
auto has_query = not query.where.empty() or not query.select.empty();
pk.pack(KEY_A); pk.pack_map(5 + has_query);
pk.pack(KEY_A); pk.pack_map(4 + has_query);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_VERSION); pk.pack(1);
pk.pack(KEY_REQ_H); pk.pack(hash);
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
pk.pack(KEY_REQ_SID); pk.pack(socketId);
pk.pack(KEY_REQ_SID); pk.pack_bin(sid.size());
pk.pack_bin_body((const char*)sid.data(), sid.size());
if (has_query) {
pk.pack(KEY_REQ_QUERY); pk.pack(query);
}
pk.pack(KEY_Q); pk.pack(QUERY_LISTEN);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::Listen, tid, n,
auto req = std::make_shared<Request>(MessageType::Listen, tid.toInt(), n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
if (on_done)
@@ -1110,7 +1092,8 @@ NetworkEngine::sendListen(Sp<Node> n,
[=](const Request& req_status, bool done) { /* on expired */
if (on_expired)
on_expired(req_status, done);
}
},
socket
);
sendRequest(req);
++out_stats.listen;
@@ -1127,7 +1110,9 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
pk.pack(KEY_REQ_ID); pk.pack(myid);
insertAddr(pk, addr);
pk.pack(KEY_TID); pk.pack(tid);
TransId t (tid);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
@@ -1146,7 +1131,7 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
RequestCb&& on_done,
RequestExpiredCb&& on_expired)
{
Tid tid (n->getNewTid());
TransId tid (n->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
@@ -1162,14 +1147,15 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
pk.pack(KEY_Q); pk.pack(QUERY_PUT);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid, n,
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid.toInt(), n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
if (msg.value_id == Value::INVALID_ID) {
@@ -1189,68 +1175,22 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
}
}
);
req->parts = std::move(v);
sendRequest(req);
if (not v.empty())
sendValueParts(tid, v, n->getAddr());
++out_stats.put;
return req;
}
Sp<Request>
NetworkEngine::sendUpdateValues(Sp<Node> n,
const InfoHash& infohash,
const std::vector<Sp<Value>>& values,
time_point created,
const Blob& token,
const size_t& socket_id)
{
Tid tid (n->getNewTid());
Tid sid (socket_id);
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
pk.pack(KEY_A); pk.pack_map((created < scheduler.time() ? 7 : 6));
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_VERSION); pk.pack(1);
pk.pack(KEY_REQ_H); pk.pack(infohash);
pk.pack(KEY_REQ_SID); pk.pack(sid);
auto v = packValueHeader(buffer, values);
if (created < scheduler.time()) {
pk.pack(KEY_REQ_CREATION);
pk.pack(to_time_t(created));
}
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request&, ParsedMessage&&) { /* on done */ },
[=](const Request&, bool) { /* on expired */ }
);
req->parts = std::move(v);
sendRequest(req);
++out_stats.updateValue;
return req;
}
Sp<Request>
NetworkEngine::sendRefreshValue(Sp<Node> n,
const InfoHash& infohash,
const Value::Id& vid,
const Blob& token,
RequestCb&& on_done,
RequestErrorCb&& on_error,
RequestExpiredCb&& on_expired)
{
Tid tid (n->getNewTid());
TransId tid (n->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(config.network?1:0));
@@ -1262,14 +1202,15 @@ NetworkEngine::sendRefreshValue(Sp<Node> n,
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
pk.pack(KEY_Q); pk.pack(QUERY_REFRESH);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
pk.pack(KEY_NETID); pk.pack(config.network);
}
auto req = std::make_shared<Request>(MessageType::Refresh, tid, n,
auto req = std::make_shared<Request>(MessageType::Refresh, tid.toInt(), n,
Blob(buffer.data(), buffer.data() + buffer.size()),
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
if (msg.value_id == Value::INVALID_ID) {
@@ -1283,7 +1224,6 @@ NetworkEngine::sendRefreshValue(Sp<Node> n,
}
}
},
on_error,
[=](const Request& req_status, bool done) { /* on expired */
if (on_expired) {
on_expired(req_status, done);
@@ -1306,7 +1246,9 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
pk.pack(KEY_REQ_VALUE_ID); pk.pack(vid);
insertAddr(pk, addr);
pk.pack(KEY_TID); pk.pack(tid);
TransId t(tid);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
@@ -1325,7 +1267,7 @@ NetworkEngine::sendError(const SockAddr& addr,
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4 + (include_id?1:0) + (config.network?1:0));
pk.pack_map(4 + (include_id?1:0));
pk.pack(KEY_E); pk.pack_array(2);
pk.pack(code);
@@ -1336,7 +1278,9 @@ NetworkEngine::sendError(const SockAddr& addr,
pk.pack(KEY_REQ_ID); pk.pack(myid);
}
pk.pack(KEY_TID); pk.pack(tid);
TransId t(tid);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_E);
pk.pack(KEY_UA); pk.pack(my_v);
if (config.network) {
+1
View File
@@ -116,6 +116,7 @@ Node::cancelRequest(const Sp<net::Request>& req)
{
if (req) {
req->cancel();
closeSocket(req->closeSocket());
requests_.erase(req->getTid());
}
}
-7
View File
@@ -54,12 +54,10 @@ static const std::string KEY_REQ_EXPIRED {"exp"};
static const std::string KEY_REQ_REFRESHED {"re"};
static const std::string KEY_REQ_FIELDS {"fileds"};
static const std::string KEY_REQ_WANT {"w"};
static const std::string KEY_VERSION {"ve"};
static const std::string QUERY_PING {"ping"};
static const std::string QUERY_FIND {"find"};
static const std::string QUERY_GET {"get"};
static const std::string QUERY_UPDATE {"update"};
static const std::string QUERY_PUT {"put"};
static const std::string QUERY_LISTEN {"listen"};
static const std::string QUERY_REFRESH {"refresh"};
@@ -115,7 +113,6 @@ struct ParsedMessage {
uint16_t error_code;
/* reported address by the distant node */
std::string ua;
int version {0};
SockAddr addr;
void msgpack_unpack(const msgpack::object& o);
@@ -227,8 +224,6 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
type = MessageType::AnnounceValue;
else if (parsed.q == QUERY_REFRESH)
type = MessageType::Refresh;
else if (parsed.q == QUERY_UPDATE)
type = MessageType::UpdateValue;
else
throw msgpack::type_error();
@@ -300,8 +295,6 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
parsedReq.fields = &o.val;
else if (key == KEY_REQ_WANT)
parsedReq.want = &o.val;
else if (key == KEY_VERSION)
version = o.val.as<int>();
}
if (parsedReq.sa) {
+18 -24
View File
@@ -27,9 +27,10 @@ struct Node;
namespace net {
class NetworkEngine;
class DhtProtocolException;
struct ParsedMessage;
extern std::atomic<size_t> REQ_COUNT;
/*!
* @class Request
* @brief An atomic request destined to a node.
@@ -68,24 +69,29 @@ struct Request {
}
}
Request(State state = State::PENDING) : state_(state) {}
Request(State state = State::PENDING) : state_(state) {
REQ_COUNT++;
}
Request(MessageType type, Tid tid,
Sp<Node> node,
Blob&& msg,
std::function<void(const Request&, ParsedMessage&&)> on_done,
std::function<void(const Request&, bool)> on_expired) :
node(node), tid(tid), type(type), on_done(on_done), on_expired(on_expired), msg(std::move(msg)) { }
Request(MessageType type, Tid tid,
Sp<Node> node,
Blob&& msg,
std::function<void(const Request&, ParsedMessage&&)> on_done,
std::function<bool(const Request&, DhtProtocolException&&)> on_error,
std::function<void(const Request&, bool)> on_expired) :
node(node), tid(tid), type(type), on_done(on_done), on_error(on_error), on_expired(on_expired), msg(std::move(msg)) { }
std::function<void(const Request&, bool)> on_expired,
Tid socket = 0) :
node(node), tid(tid), type(type), on_done(on_done), on_expired(on_expired), msg(std::move(msg)), socket(socket) {
REQ_COUNT++;
}
~Request() {
REQ_COUNT--;
}
Tid getTid() const { return tid; }
MessageType getType() const { return type; }
Tid getSocket() { return socket; }
Tid closeSocket() { auto ret = socket; socket = 0; return ret; }
void setExpired() {
if (pending()) {
state_ = Request::State::EXPIRED;
@@ -100,15 +106,6 @@ struct Request {
clear();
}
}
bool setError(DhtProtocolException&& e) {
if (pending()) {
state_ = Request::State::EXPIRED;
bool handled = on_error and on_error(*this, std::forward<DhtProtocolException>(e));
clear();
return handled;
}
return true;
}
void cancel() {
if (pending()) {
@@ -126,10 +123,8 @@ private:
void clear() {
on_done = {};
on_error = {};
on_expired = {};
msg = {};
parts = {};
}
const Tid tid {0}; /* the request id. */
@@ -142,11 +137,10 @@ private:
time_point last_try {time_point::min()}; /* time of the last attempt to process the request. */
std::function<void(const Request&, ParsedMessage&&)> on_done {};
std::function<bool(const Request&, DhtProtocolException&&)> on_error {};
std::function<void(const Request&, bool)> on_expired {};
Blob msg {}; /* the serialized message. */
std::vector<Blob> parts;
Tid socket; /* the socket used for further reponses. */
};
} /* namespace net */
+11 -55
View File
@@ -65,16 +65,10 @@ struct Dht::SearchNode {
ValueCache cache;
Sp<Scheduler::Job> cacheExpirationJob {};
Sp<net::Request> req {};
Tid socketId {0};
CachedListenStatus(ValueStateCallback&& cb, SyncCallback scb, Tid sid)
: cache(std::forward<ValueStateCallback>(cb), std::forward<SyncCallback>(scb)), socketId(sid) {}
CachedListenStatus(ValueStateCallback&& cb, SyncCallback&& scb)
: cache(std::forward<ValueStateCallback>(cb), std::forward<SyncCallback>(scb)) {}
CachedListenStatus(CachedListenStatus&&) = delete;
CachedListenStatus(const CachedListenStatus&) = delete;
~CachedListenStatus() {
if (socketId and req and req->node) {
req->node->closeSocket(socketId);
}
}
};
using NodeListenerStatus = std::map<Sp<Query>, CachedListenStatus>;
@@ -350,15 +344,13 @@ struct Dht::SearchNode {
* Assuming the node is synced, should the "listen" request with Query q be
* sent to this node now ?
*/
time_point getListenTime(const decltype(listenStatus)::const_iterator listen_status, duration listen_expire) const {
if (listen_status == listenStatus.cend() or not listen_status->second.req)
time_point getListenTime(const Sp<Query>& q, duration listen_expire) const {
auto listen_status = listenStatus.find(q);
if (listen_status == listenStatus.end() or not listen_status->second.req)
return time_point::min();
return listen_status->second.req->pending() ? time_point::max() :
listen_status->second.req->reply_time + listen_expire - REANNOUNCE_MARGIN;
}
time_point getListenTime(const Sp<Query>& q, duration listen_expire) const {
return getListenTime(listenStatus.find(q), listen_expire);
}
/**
* Is this node expired or candidate
@@ -576,43 +568,6 @@ struct Dht::Search {
return canceled;
}
void put(const Sp<Value>& value, DoneCallback callback, time_point created, bool permanent) {
done = false;
expired = false;
auto a_sr = std::find_if(announce.begin(), announce.end(), [&](const Announce& a){
return a.value->id == value->id;
});
if (a_sr == announce.end()) {
announce.emplace_back(Announce {permanent, value, created, callback});
for (auto& n : nodes) {
n->probe_query.reset();
n->acked[value->id].first.reset();
}
} else {
a_sr->permanent = permanent;
a_sr->created = created;
if (a_sr->value != value) {
a_sr->value = value;
for (auto& n : nodes) {
n->acked[value->id].first.reset();
n->probe_query.reset();
}
}
if (isAnnounced(value->id)) {
if (a_sr->callback)
a_sr->callback(true, {});
a_sr->callback = {};
if (callback)
callback(true, {});
return;
} else {
if (a_sr->callback)
a_sr->callback(false, {});
a_sr->callback = callback;
}
}
}
/**
* @return The number of non-good search nodes.
*/
@@ -624,7 +579,7 @@ struct Dht::Search {
unsigned getNumberOfConsecutiveBadNodes() const {
unsigned count = 0;
std::find_if(nodes.begin(), nodes.end(), [&count](const std::unique_ptr<SearchNode>& sn) {
if (not sn->node->isExpired())
if (not sn->isBad())
return true;
++count;
return false;
@@ -767,6 +722,7 @@ Dht::Search::insertNode(const Sp<Node>& snode, time_point now, const Blob& token
}
}
bool new_search_node = false;
if (not found) {
// find if and where to trim excessive nodes
auto t = nodes.cend();
@@ -790,10 +746,9 @@ Dht::Search::insertNode(const Sp<Node>& snode, time_point now, const Blob& token
}
if (full) {
bool addNode = n < t;
if (t != nodes.cend())
nodes.resize(std::distance(nodes.cbegin(), t));
if (not addNode)
if (n >= t)
return false;
}
@@ -803,6 +758,7 @@ Dht::Search::insertNode(const Sp<Node>& snode, time_point now, const Blob& token
}
n = nodes.emplace(n, std::make_unique<SearchNode>(snode));
node.setTime(now);
new_search_node = true;
if (node.isExpired()) {
if (not expired)
bad++;
@@ -824,9 +780,9 @@ Dht::Search::insertNode(const Sp<Node>& snode, time_point now, const Blob& token
(*n)->token = token;
expired = false;
}
if (not found)
if (new_search_node)
removeExpiredNode(now);
return not found;
return new_search_node;
}
std::vector<Sp<Node>>
+1
View File
@@ -107,6 +107,7 @@ ThreadPool::run(std::function<void()>&& cb)
tasks_.emplace(std::move(cb));
// notify thread
l.unlock();
cv_.notify_one();
}
+21 -3
View File
@@ -34,6 +34,9 @@
#endif
namespace dht {
namespace net {
std::atomic<size_t> REQ_COUNT {0};
}
static constexpr std::array<uint8_t, 12> MAPPED_IPV4_PREFIX {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}};
@@ -76,8 +79,11 @@ SockAddr::resolve(const std::string& host, const std::string& service)
if(rc != 0)
throw std::invalid_argument(std::string("Error: `") + host + ":" + service + "`: " + gai_strerror(rc));
for (addrinfo* infop = info; infop; infop = infop->ai_next)
addrinfo* infop = info;
while (infop) {
ips.emplace_back(infop->ai_addr, infop->ai_addrlen);
infop = infop->ai_next;
}
freeaddrinfo(info);
return ips;
}
@@ -277,16 +283,28 @@ unpackMsg(Blob b) {
}
msgpack::object*
findMapValue(const msgpack::object& map, const char* key, size_t key_length) {
findMapValue(const msgpack::object& map, const char* key) {
if (map.type != msgpack::type::MAP) throw msgpack::type_error();
for (unsigned i = 0; i < map.via.map.size; i++) {
auto& o = map.via.map.ptr[i];
if (o.key.type == msgpack::type::STR
&& key_length == o.key.via.str.size
&& std::strncmp(o.key.via.str.ptr, key, o.key.via.str.size) == 0)
return &o.val;
}
return nullptr;
}
msgpack::object*
findMapValue(const msgpack::object& map, const std::string& key) {
if (map.type != msgpack::type::MAP) throw msgpack::type_error();
for (unsigned i = 0; i < map.via.map.size; i++) {
auto& o = map.via.map.ptr[i];
if (o.key.type == msgpack::type::STR
&& key.size() == o.key.via.str.size
&& std::strncmp(o.key.via.str.ptr, key.data(), o.key.via.str.size) == 0)
return &o.val;
}
return nullptr;
}
}
+1 -3
View File
@@ -75,13 +75,11 @@ std::ostream& operator<< (std::ostream& s, const Value& v)
s << '"';
s.write((const char*)v.data.data(), v.data.size());
s << '"';
} else if (v.data.size() < 1024) {
} else {
s << std::hex;
for (auto i : v.data)
s << std::setfill('0') << std::setw(2) << (unsigned)i;
s << std::dec;
} else {
s << v.data.size() << " bytes";
}
}
}
-26
View File
@@ -2,7 +2,6 @@
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -136,31 +135,6 @@ CryptoTester::testCertificateRequest()
CPPUNIT_ASSERT_MESSAGE(v.toString(), v);
}
void CryptoTester::testCertificateSerialNumber()
{
static const std::string cert_pem = "-----BEGIN CERTIFICATE-----"
"MIICDjCCAZSgAwIBAgIIS90uAKp+u/swCgYIKoZIzj0EAwMwTDEQMA4GA1UEAxMH"
"ZGh0bm9kZTE4MDYGCgmSJomT8ixkAQETKDBlNDQxZTA4YWJmYTQzYTc3ZTVjZDBm"
"Y2QzMzAzMTc4MjYxMTk0MzIwHhcNMTkxMTA3MDA0MTMwWhcNMjkxMTA0MDA0MTMw"
"WjBMMRAwDgYDVQQDEwdkaHRub2RlMTgwNgYKCZImiZPyLGQBARMoMGU0NDFlMDhh"
"YmZhNDNhNzdlNWNkMGZjZDMzMDMxNzgyNjExOTQzMjB2MBAGByqGSM49AgEGBSuB"
"BAAiA2IABCZ7sBp0Pu+b5yIifoNXchU9crv9won0in++COWynvM4GCLF2Gk6QGhh"
"YLDxNGsyQjGR7z5AGibvYhNLU0JA4RbmxYWHw4g3wBrPA1jm9hGZ8y5Y8R97d0Hl"
"VpyreEMjRKNDMEEwHQYDVR0OBBYEFA5EHgir+kOnflzQ/NMwMXgmEZQyMA8GA1Ud"
"EwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAKBggqhkjOPQQDAwNoADBlAjEA"
"kKF/6WReNytwSrJ8JSTToc7xWS5SvAa23Fnla4mywZUxUFS4VSxCMQTjQCknO3iZ"
"AjBgxXyXYqn0d7vz7S6oAY5TdaD5YFT5MD2c1MAAp8pxQSwdPa9k0ZSoGIEn31Z0"
"GxU="
"-----END CERTIFICATE-----";
/*
* $ openssl x509 -in cert.pem -noout -serial
* serial=4BDD2E00AA7EBBFB
*/
static constexpr std::array<uint8_t, 8> SERIAL {{0x4b,0xdd,0x2e,0x00,0xaa,0x7e,0xbb,0xfb}};
auto serial = dht::crypto::Certificate(cert_pem).getSerialNumber();
CPPUNIT_ASSERT(std::equal(SERIAL.begin(), SERIAL.end(), serial.begin(), serial.end()));
}
void
CryptoTester::tearDown() {
-6
View File
@@ -2,7 +2,6 @@
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -31,7 +30,6 @@ class CryptoTester : public CppUnit::TestFixture {
CPPUNIT_TEST(testSignatureEncryption);
CPPUNIT_TEST(testCertificateRevocation);
CPPUNIT_TEST(testCertificateRequest);
CPPUNIT_TEST(testCertificateSerialNumber);
CPPUNIT_TEST_SUITE_END();
public:
@@ -55,10 +53,6 @@ class CryptoTester : public CppUnit::TestFixture {
* Test certificate requests
*/
void testCertificateRequest();
/**
* Test certificate serial number extraction
*/
void testCertificateSerialNumber();
};
} // namespace test
+10 -11
View File
@@ -34,25 +34,24 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DhtProxyTester);
void
DhtProxyTester::setUp() {
clientConfig.dht_config.node_config.max_peer_req_per_sec = -1;
clientConfig.dht_config.node_config.max_req_per_sec = -1;
nodePeer.run(0, clientConfig);
nodePeer.run(0);
nodeProxy = std::make_shared<dht::DhtRunner>();
nodeProxy->run(0, clientConfig);
nodeProxy->run(0);
nodeProxy->bootstrap(nodePeer.getBound());
auto serverCAIdentity = dht::crypto::generateEcIdentity("DHT Node CA");
auto serverIdentity = dht::crypto::generateIdentity("DHT Node", serverCAIdentity);
dht::ProxyServerConfig serverConfig;
serverConfig.identity = dht::crypto::generateIdentity("DHT Node", serverCAIdentity);
serverConfig.port = 8080;
serverConfig.pushServer = "127.0.0.1:8090";
serverProxy = std::make_unique<dht::DhtProxyServer>(nodeProxy, serverConfig);
serverProxy = std::make_unique<dht::DhtProxyServer>(
//dht::crypto::Identity{}, // http
serverIdentity, // https
nodeProxy, 8080, /*pushServer*/"127.0.0.1:8090");
clientConfig.server_ca = serverCAIdentity.second;
clientConfig.client_identity = dht::crypto::generateIdentity("DhtProxyTester");
clientConfig.dht_config.node_config.maintain_storage = false;
clientConfig.threaded = true;
clientConfig.push_node_id = "dhtnode";
clientConfig.proxy_server = "https://127.0.0.1:8080";
}
@@ -281,7 +280,7 @@ DhtProxyTester::testFuzzy()
},[&](bool ok){
CPPUNIT_ASSERT(ok);
});
std::this_thread::sleep_for(5ms);
std::this_thread::sleep_for(10ms);
}
// Assert
+6 -81
View File
@@ -29,12 +29,8 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DhtRunnerTester);
void
DhtRunnerTester::setUp() {
dht::DhtRunner::Config config;
config.dht_config.node_config.max_peer_req_per_sec = -1;
config.dht_config.node_config.max_req_per_sec = -1;
node1.run(42222, config);
node2.run(42232, config);
node1.run(42222);
node2.run(42232);
node2.bootstrap(node1.getBound());
}
@@ -88,9 +84,7 @@ DhtRunnerTester::testListen() {
auto a = dht::InfoHash::get("234");
auto b = dht::InfoHash::get("2345");
auto c = dht::InfoHash::get("23456");
auto d = dht::InfoHash::get("234567");
constexpr unsigned N = 256;
constexpr unsigned SZ = 56 * 1024;
constexpr unsigned N = 32;
auto ftokena = node1.listen(a, [&](const std::shared_ptr<dht::Value>&) {
valueCount++;
@@ -107,16 +101,6 @@ DhtRunnerTester::testListen() {
return true;
});
auto ftokend = node1.listen(d, [&](const std::shared_ptr<dht::Value>&) {
valueCount++;
return true;
});
std::vector<uint8_t> mtu;
mtu.reserve(SZ);
for (size_t i = 0; i < SZ; i++)
mtu.emplace_back((i % 2) ? 'T' : 'M');
for (unsigned i=0; i<N; i++) {
node2.put(a, dht::Value("v1"), [&](bool ok) {
std::lock_guard<std::mutex> lock(mutex);
@@ -130,88 +114,29 @@ DhtRunnerTester::testListen() {
if (ok) putOkCount++;
cv.notify_all();
});
auto bigVal = std::make_shared<dht::Value>();
bigVal->data = mtu;
node2.put(c, bigVal, [&](bool ok) {
std::lock_guard<std::mutex> lock(mutex);
putCount++;
if (ok) putOkCount++;
cv.notify_all();
});
}
{
std::unique_lock<std::mutex> lk(mutex);
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]{ return putCount == N * 3u; }));
CPPUNIT_ASSERT_EQUAL(N * 3u, putOkCount);
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]{ return putCount == N * 2u; }));
CPPUNIT_ASSERT_EQUAL(N * 2u, putOkCount);
}
CPPUNIT_ASSERT(ftokena.valid());
CPPUNIT_ASSERT(ftokenb.valid());
CPPUNIT_ASSERT(ftokenc.valid());
CPPUNIT_ASSERT(ftokend.valid());
auto tokena = ftokena.get();
auto tokenc = ftokenc.get();
auto tokend = ftokend.get();
// tokenb might be 0 since the callback returns false.
CPPUNIT_ASSERT(tokena);
CPPUNIT_ASSERT(tokenc);
CPPUNIT_ASSERT(tokend);
CPPUNIT_ASSERT_EQUAL(N * 2u + 1u, valueCount.load());
CPPUNIT_ASSERT_EQUAL(N + 1u, valueCount.load());
node1.cancelListen(a, tokena);
node1.cancelListen(b, std::move(ftokenb));
node1.cancelListen(c, tokenc);
node1.cancelListen(d, tokend);
}
void
DhtRunnerTester::testListenLotOfBytes() {
std::mutex mutex;
std::condition_variable cv;
std::atomic_uint valueCount(0);
unsigned putCount(0);
unsigned putOkCount(0);
std::string data(10000, 'a');
auto foo = dht::InfoHash::get("foo");
constexpr unsigned N = 50;
for (unsigned i=0; i<N; i++) {
node2.put(foo, data, [&](bool ok) {
std::lock_guard<std::mutex> lock(mutex);
putCount++;
if (ok) putOkCount++;
cv.notify_all();
});
}
{
std::unique_lock<std::mutex> lk(mutex);
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]{ return putCount == N; }));
}
dht::DhtRunner node3 {};
dht::DhtRunner::Config config;
config.dht_config.node_config.max_peer_req_per_sec = -1;
config.dht_config.node_config.max_req_per_sec = -1;
node3.run(42242, config);
node3.bootstrap(node1.getBound());
auto ftokenfoo = node3.listen(foo, [&](const std::shared_ptr<dht::Value>&) {
valueCount++;
cv.notify_all();
return true;
});
{
std::unique_lock<std::mutex> lk(mutex);
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]{ return valueCount == N; }));
}
node3.cancelListen(foo, ftokenfoo.get());
}
} // namespace test
-5
View File
@@ -32,7 +32,6 @@ class DhtRunnerTester : public CppUnit::TestFixture {
CPPUNIT_TEST(testConstructors);
CPPUNIT_TEST(testGetPut);
CPPUNIT_TEST(testListen);
CPPUNIT_TEST(testListenLotOfBytes);
CPPUNIT_TEST_SUITE_END();
dht::DhtRunner node1 {};
@@ -58,10 +57,6 @@ class DhtRunnerTester : public CppUnit::TestFixture {
* Test listen method
*/
void testListen();
/**
* Test listen method with lot of datas
*/
void testListenLotOfBytes();
};
} // namespace test
+18 -8
View File
@@ -39,10 +39,9 @@ HttpTester::setUp() {
nodeProxy->run(0, /*identity*/{}, /*threaded*/true);
nodeProxy->bootstrap(nodePeer->getBound());
dht::ProxyServerConfig config;
config.port = 8080;
config.pushServer = "127.0.0.1:8090";
serverProxy = std::make_unique<dht::DhtProxyServer>(nodeProxy, config);
serverProxy = std::unique_ptr<dht::DhtProxyServer>(
new dht::DhtProxyServer(
/*http*/dht::crypto::Identity{}, nodeProxy, 8080, /*pushServer*/"127.0.0.1:8090"));
}
void
@@ -61,6 +60,7 @@ HttpTester::test_parse_url() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "google.com");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
@@ -74,6 +74,7 @@ HttpTester::test_parse_https_url_no_service() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "https");
CPPUNIT_ASSERT(parsed.host == "jami.net");
CPPUNIT_ASSERT(parsed.service == "https");
CPPUNIT_ASSERT(parsed.target == "/");
}
@@ -87,7 +88,8 @@ HttpTester::test_parse_url_no_prefix_no_target() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "google.com");
CPPUNIT_ASSERT(parsed.target == "");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
void
@@ -114,6 +116,7 @@ HttpTester::test_parse_url_query() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "google.com");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/?key=1");
CPPUNIT_ASSERT(parsed.query == "key=1");
}
@@ -128,6 +131,7 @@ HttpTester::test_parse_url_fragment() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "google.com");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/?key=1");
CPPUNIT_ASSERT(parsed.query == "key=1");
CPPUNIT_ASSERT(parsed.fragment == "#some-important-id");
@@ -143,6 +147,7 @@ HttpTester::test_parse_url_ipv4() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "172.217.13.132");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
@@ -156,6 +161,8 @@ HttpTester::test_parse_url_no_prefix_no_target_ipv4() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "172.217.13.132");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
void
@@ -182,6 +189,7 @@ HttpTester::test_parse_url_ipv6() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "2607:f8b0:4006:804::2004");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
@@ -195,6 +203,8 @@ HttpTester::test_parse_url_no_prefix_no_target_ipv6() {
CPPUNIT_ASSERT(parsed.url == url);
CPPUNIT_ASSERT(parsed.protocol == "http");
CPPUNIT_ASSERT(parsed.host == "2607:f8b0:4006:804::2004");
CPPUNIT_ASSERT(parsed.service == "80");
CPPUNIT_ASSERT(parsed.target == "/");
}
void
@@ -224,13 +234,13 @@ HttpTester::test_send_json() {
Json::Value resp_val;
// Act
auto request = std::make_shared<dht::http::Request>(serverProxy->io_context(),
auto request = std::make_shared<dht::http::Request>(serverProxy->io_context(),
"http://127.0.0.1:8080/key",
json,
[&](Json::Value value, const dht::http::Response& response) {
[&](Json::Value value, unsigned int status_code) {
std::lock_guard<std::mutex> lk(cv_m);
resp_val = std::move(value);
status = response.status_code;
status = status_code;
done = true;
cv.notify_all();
});
+48 -45
View File
@@ -1,35 +1,38 @@
add_executable (dhtnode dhtnode.cpp tools_common.h)
add_executable (dhtscanner dhtscanner.cpp tools_common.h)
add_executable (dhtchat dhtchat.cpp tools_common.h)
add_executable (perftest perftest.cpp tools_common.h)
target_link_libraries (dhtnode LINK_PUBLIC ${READLINE_LIBRARIES})
target_link_libraries (dhtscanner LINK_PUBLIC ${READLINE_LIBRARIES})
target_link_libraries (dhtchat LINK_PUBLIC ${READLINE_LIBRARIES})
target_link_libraries (perftest LINK_PUBLIC ${READLINE_LIBRARIES})
if (OPENDHT_SHARED)
set (OPENDHT_LIBS opendht)
target_link_libraries (dhtnode LINK_PUBLIC opendht)
target_link_libraries (dhtscanner LINK_PUBLIC opendht)
target_link_libraries (dhtchat LINK_PUBLIC opendht)
target_link_libraries (perftest LINK_PUBLIC opendht)
else ()
set (OPENDHT_LIBS opendht-static)
if (MSVC)
set (MSC_COMPAT_SOURCES ${MSC_COMPAT_DIR}/wingetopt.c)
endif ()
target_link_libraries (dhtnode LINK_PUBLIC opendht-static)
target_link_libraries (dhtscanner LINK_PUBLIC opendht-static)
target_link_libraries (dhtchat LINK_PUBLIC opendht-static)
target_link_libraries (perftest LINK_PUBLIC opendht-static)
endif ()
function (configure_tool name extra_files)
add_executable (${name} ${name}.cpp ${extra_files})
target_link_libraries (${name} LINK_PUBLIC ${READLINE_LIBRARIES})
target_link_libraries (${name} LINK_PUBLIC ${OPENDHT_LIBS})
if (MSVC)
target_sources(${name} PRIVATE ${MSC_COMPAT_SOURCES})
target_include_directories (${name} PRIVATE ${MSC_COMPAT_DIR})
endif ()
endfunction ()
configure_tool (dhtnode tools_common.h)
configure_tool (dhtscanner tools_common.h)
configure_tool (dhtchat tools_common.h)
if (NOT MSVC)
configure_tool (perftest tools_common.h)
endif ()
if (OPENDHT_HTTP)
configure_tool (durl tools_common.h)
endif ()
add_executable (durl durl.cpp)
if (OPENDHT_SHARED)
target_link_libraries (durl LINK_PUBLIC opendht)
else ()
target_link_libraries (durl LINK_PUBLIC opendht-static)
endif ()
endif()
if (OPENDHT_C)
add_executable (dhtcnode dhtcnode.c)
target_link_libraries (dhtcnode LINK_PUBLIC opendht-c ${READLINE_LIBRARIES})
add_executable (dhtcnode dhtcnode.c)
target_link_libraries (dhtcnode LINK_PUBLIC opendht-c ${READLINE_LIBRARIES})
endif ()
if (NOT DEFINED CMAKE_INSTALL_BINDIR)
@@ -39,25 +42,25 @@ endif ()
install (TARGETS dhtnode dhtscanner dhtchat RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
if (OPENDHT_SYSTEMD)
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} systemd --variable=systemdsystemunitdir
OUTPUT_VARIABLE SYSTEMD_UNIT_INSTALL_DIR)
string(REGEX REPLACE "[ \t\n]+" "" SYSTEMD_UNIT_INSTALL_DIR "${SYSTEMD_UNIT_INSTALL_DIR}")
set (systemdunitdir "${SYSTEMD_UNIT_INSTALL_DIR}")
execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} systemd --variable=systemdsystemunitdir
OUTPUT_VARIABLE SYSTEMD_UNIT_INSTALL_DIR)
string(REGEX REPLACE "[ \t\n]+" "" SYSTEMD_UNIT_INSTALL_DIR "${SYSTEMD_UNIT_INSTALL_DIR}")
set (systemdunitdir "${SYSTEMD_UNIT_INSTALL_DIR}")
configure_file (
systemd/dhtnode.service.in
systemd/dhtnode.service
@ONLY
)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/systemd/dhtnode.service DESTINATION ${systemdunitdir})
install (FILES systemd/dhtnode.conf DESTINATION ${sysconfdir})
if (OPENDHT_PYTHON)
configure_file (
systemd/dhtcluster.service.in
systemd/dhtcluster.service
@ONLY
)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/systemd/dhtcluster.service DESTINATION ${systemdunitdir})
install (FILES systemd/dhtcluster.conf DESTINATION ${sysconfdir})
endif()
configure_file (
systemd/dhtnode.service.in
systemd/dhtnode.service
@ONLY
)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/systemd/dhtnode.service DESTINATION ${systemdunitdir})
install (FILES systemd/dhtnode.conf DESTINATION ${sysconfdir})
if (OPENDHT_PYTHON)
configure_file (
systemd/dhtcluster.service.in
systemd/dhtcluster.service
@ONLY
)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/systemd/dhtcluster.service DESTINATION ${systemdunitdir})
install (FILES systemd/dhtcluster.conf DESTINATION ${sysconfdir})
endif()
endif ()
+6 -6
View File
@@ -54,7 +54,7 @@ main(int argc, char **argv)
print_usage();
return 0;
}
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_init();
#endif
@@ -64,10 +64,10 @@ main(int argc, char **argv)
auto dhtConf = getDhtConfig(params);
dht.run(params.port, dhtConf.first, std::move(dhtConf.second));
if (not params.bootstrap.empty())
dht.bootstrap(params.bootstrap);
if (not params.bootstrap.first.empty())
dht.bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
print_node_info(dht.getNodeInfo());
print_node_info(dht, params);
std::cout << " type 'c {hash}' to join a channel" << std::endl << std::endl;
bool connected {false};
@@ -76,7 +76,7 @@ main(int argc, char **argv)
const InfoHash myid = dht.getId();
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
// using the GNU History API
using_history();
#endif
@@ -144,7 +144,7 @@ main(int argc, char **argv)
std::cout << std::endl << "Stopping node..." << std::endl;
dht.join();
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_deinit();
#endif
return 0;
+62 -54
View File
@@ -114,10 +114,10 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
#endif
)
{
print_node_info(node->getNodeInfo());
print_node_info(*node, params);
std::cout << " (type 'h' or 'help' for a list of possible commands)" << std::endl << std::endl;
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
// using the GNU History API
using_history();
#endif
@@ -143,23 +143,30 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
print_help();
continue;
} else if (op == "ll") {
node->getNodeInfo([&](const std::shared_ptr<dht::NodeInfo>& nodeInfo) {
print_node_info(*nodeInfo);
std::cout << nodeInfo->ongoing_ops << " ongoing operations" << std::endl;
std::cout << "IPv4 stats:" << std::endl;
std::cout << nodeInfo->ipv4.toString() << std::endl;
std::cout << "IPv6 stats:" << std::endl;
std::cout << nodeInfo->ipv6.toString() << std::endl;
auto nodeInfo = node->getNodeInfo();
print_node_info(*node, params);
std::cout << "Scheduler size:" << nodeInfo.metrics.scheduler_size << std::endl;
std::cout << "RateLimiter size:" << nodeInfo.metrics.rate_limiter_size << std::endl;
std::cout << "ReportedAddr count:" << nodeInfo.metrics.reported_addr_num << std::endl;
std::cout << "Node cache size:" << nodeInfo.metrics.node_cache_size << std::endl;
std::cout << "Store size:" << nodeInfo.metrics.store_size << std::endl;
std::cout << "Store quota size:" << nodeInfo.metrics.store_quota_size << std::endl;
std::cout << "Global request count:" << nodeInfo.metrics.request_count << std::endl;
std::cout << nodeInfo.ongoing_ops << " ongoing operations" << std::endl;
std::cout << "IPv4 stats:" << std::endl;
std::cout << nodeInfo.ipv4.toString() << std::endl;
std::cout << "IPv6 stats:" << std::endl;
std::cout << nodeInfo.ipv6.toString() << std::endl;
#ifdef OPENDHT_PROXY_SERVER
for (const auto& proxy : proxies) {
std::cout << "Stats for proxy server on port " << proxy.first << std::endl;
if (auto stats = proxy.second->stats())
std::cout << " " << stats->toString() << std::endl;
else
std::cout << " (stats not available yet)" << std::endl;
}
for (const auto& proxy : proxies) {
std::cout << "Stats for proxy server on port " << proxy.first << std::endl;
if (auto stats = proxy.second->stats())
std::cout << " " << stats->toString() << std::endl;
else
std::cout << " (stats not available yet)" << std::endl;
}
#endif
});
continue;
} else if (op == "lr") {
std::cout << "IPv4 routing table:" << std::endl;
@@ -191,10 +198,14 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
continue;
} else if (op == "b") {
iss >> idstr;
if (not idstr.empty())
node->bootstrap(idstr);
else
std::cerr << "No service provided. Syntax: b hostname:port" << std::endl;
try {
auto addr = splitPort(idstr);
if (not addr.first.empty() and addr.second.empty())
addr.second = std::to_string(dht::net::DHT_DEFAULT_PORT);
node->bootstrap(addr.first.c_str(), addr.second.c_str());
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
continue;
} else if (op == "log") {
iss >> idstr;
@@ -218,11 +229,14 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
iss >> idstr;
#endif // OPENDHT_PUSH_NOTIFICATIONS
try {
in_port_t port = std::stoi(idstr);
ProxyServerConfig serverConfig;
serverConfig.port = port;
serverConfig.pushServer = pushServer;
proxies.emplace(port, std::make_unique<DhtProxyServer>(node, serverConfig));
unsigned int port = std::stoi(idstr);
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(
new DhtProxyServer(
dht::crypto::Identity{}, node, port
#ifdef OPENDHT_PUSH_NOTIFICATIONS
,pushServer
#endif
)));
} catch (...) { }
continue;
} else if (op == "psx") {
@@ -233,12 +247,13 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
#endif // OPENDHT_PUSH_NOTIFICATIONS
try {
if (params.proxy_id.first and params.proxy_id.second){
in_port_t port = std::stoi(idstr);
ProxyServerConfig serverConfig;
serverConfig.identity = params.proxy_id;
serverConfig.port = port;
serverConfig.pushServer = pushServer;
proxies.emplace(port, std::make_unique<DhtProxyServer>(node, serverConfig));
unsigned int port = std::stoi(idstr);
proxies.emplace(port, std::unique_ptr<DhtProxyServer>(
new DhtProxyServer(params.proxy_id, node, port
#ifdef OPENDHT_PUSH_NOTIFICATIONS
,pushServer
#endif
)));
}
else {
std::cerr << "Missing Identity private key or certificate" << std::endl;
@@ -507,7 +522,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
int
main(int argc, char **argv)
{
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_init();
#endif
auto params = parseArgs(argc, argv);
@@ -530,32 +545,25 @@ main(int argc, char **argv)
auto dhtConf = getDhtConfig(params);
node->run(params.port, dhtConf.first, std::move(dhtConf.second));
if (not params.bootstrap.empty()) {
std::cout << "Bootstrap: " << params.bootstrap << std::endl;
node->bootstrap(params.bootstrap);
if (not params.bootstrap.first.empty()) {
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
std::map<in_port_t, std::unique_ptr<DhtProxyServer>> proxies;
#endif
if (params.proxyserver or params.proxyserverssl) {
if (params.proxyserverssl and params.proxy_id.first and params.proxy_id.second){
#ifdef OPENDHT_PROXY_SERVER
ProxyServerConfig serverConfig;
serverConfig.pushServer = params.pushserver;
if (params.proxyserverssl and params.proxy_id.first and params.proxy_id.second){
serverConfig.identity = params.proxy_id;
serverConfig.port = params.proxyserverssl;
if (not params.persist_path.empty())
serverConfig.persistStatePath = params.persist_path + '_' + std::to_string(serverConfig.port);
proxies.emplace(params.proxyserverssl, std::make_unique<DhtProxyServer>(node, serverConfig, dhtConf.second.logger));
}
if (params.proxyserver) {
serverConfig.identity = {};
serverConfig.port = params.proxyserver;
if (not params.persist_path.empty())
serverConfig.persistStatePath = params.persist_path + '_' + std::to_string(serverConfig.port);
proxies.emplace(params.proxyserver, std::make_unique<DhtProxyServer>(node, serverConfig, dhtConf.second.logger));
}
proxies.emplace(params.proxyserverssl, std::unique_ptr<DhtProxyServer>(
new DhtProxyServer(params.proxy_id,
node, params.proxyserverssl, params.pushserver, dhtConf.second.logger)));
}
if (params.proxyserver) {
proxies.emplace(params.proxyserver, std::unique_ptr<DhtProxyServer>(
new DhtProxyServer(
dht::crypto::Identity{},
node, params.proxyserver, params.pushserver, dhtConf.second.logger)));
#else
std::cerr << "DHT proxy server requested but OpenDHT built without proxy server support." << std::endl;
exit(EXIT_FAILURE);
@@ -590,7 +598,7 @@ main(int argc, char **argv)
cv.wait(lk, [&](){ return done; });
node->join();
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_deinit();
#endif
return 0;
+11 -8
View File
@@ -7,7 +7,7 @@ stats_total = {"users":0, "pushListenersCount":0, "listenCount":0, "totalListene
for i in range(80,101):
print("Collecting stats for proxy " + str(i))
response = requests.request('GET', 'http://127.0.0.1:' + str(i) + '/node/stats')
response = requests.request('STATS', 'http://dhtproxy.jami.net:' + str(i))
if response.status_code == 200:
result = response.json()
@@ -38,17 +38,20 @@ for i in range(80,101):
except:
pass
try:
stats['totalPermanentPuts'] = int(result["totalPermanentPuts"])
stats_total['totalPermanentPuts'] += int(result["totalPermanentPuts"])
total = 0
for h,v in result["puts"].items():
total += int(v)
stats['totalPermanentPuts'] = total
stats_total['totalPermanentPuts'] += total
except:
pass
stats['timestamp'] = str(ts)
#with open("stats_proxy_" + str(i), "a") as stat_file:
# stat_file.write(str(stats))
# stat_file.write('\n')
with open("stats_proxy_" + str(i), "a") as stat_file:
stat_file.write(str(stats))
stat_file.write('\n')
with open("stats_proxy_total", "w") as stat_file:
with open("stats_proxy_total", "a") as stat_file:
stat_file.write(str(stats_total))
stat_file.write('\n')
+5 -5
View File
@@ -77,7 +77,7 @@ step(DhtRunner& dht, std::atomic_uint& done, std::shared_ptr<NodeSet> all_nodes,
int
main(int argc, char **argv)
{
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_init();
#endif
auto params = parseArgs(argc, argv);
@@ -91,10 +91,10 @@ main(int argc, char **argv)
auto dhtConf = getDhtConfig(params);
dht.run(params.port, dhtConf.first, std::move(dhtConf.second));
if (not params.bootstrap.empty())
dht.bootstrap(params.bootstrap);
if (not params.bootstrap.first.empty())
dht.bootstrap(params.bootstrap.first.c_str(), params.bootstrap.second.c_str());
print_node_info(dht.getNodeInfo());
print_node_info(dht, params);
std::cout << "Scanning network..." << std::endl;
auto all_nodes = std::make_shared<NodeSet>();
@@ -123,7 +123,7 @@ main(int argc, char **argv)
}
dht.join();
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_deinit();
#endif
return 0;
-4
View File
@@ -20,11 +20,7 @@
#include <opendht/log.h>
#include <asio/io_context.hpp>
#ifndef _MSC_VER
#include <getopt.h>
#else
#include "wingetopt.h"
#endif
using namespace dht;
+2 -2
View File
@@ -132,7 +132,7 @@ benchPingPong(unsigned netSize, unsigned n_parallel) {
int
main(int argc, char **argv)
{
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_init();
#endif
auto params = parseArgs(argc, argv);
@@ -173,7 +173,7 @@ main(int argc, char **argv)
std::cout << print_duration(totalTime/totalOps) << " per rt, "
<< totalOps/std::chrono::duration<double>(totalTime).count() << " ping per s" << std::endl << std::endl;
#ifdef _MSC_VER
#ifdef WIN32_NATIVE
gnutls_global_deinit();
#endif
return 0;
+18 -16
View File
@@ -32,14 +32,13 @@
#include <opendht/dht_proxy_server.h>
#endif
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
#include <getopt.h>
#include <readline/readline.h>
#include <readline/history.h>
#else
#define SIGHUP 0
#include "wingetopt.h"
#include <io.h>
#endif
#include <sys/types.h>
@@ -125,7 +124,7 @@ struct dht_params {
bool log {false};
bool syslog {false};
std::string logfile {};
std::string bootstrap {};
std::pair<std::string, std::string> bootstrap {};
dht::NetId network {0};
in_port_t port {0};
in_port_t proxyserver {0};
@@ -171,8 +170,6 @@ getDhtConfig(dht_params& params)
if (params.no_rate_limit) {
config.dht_config.node_config.max_req_per_sec = -1;
config.dht_config.node_config.max_peer_req_per_sec = -1;
config.dht_config.node_config.max_searches = -1;
config.dht_config.node_config.max_store_size = -1;
}
dht::DhtRunner::Context context {};
@@ -192,14 +189,16 @@ getDhtConfig(dht_params& params)
return {std::move(config), std::move(context)};
}
void print_node_info(const dht::NodeInfo& info) {
std::cout << "OpenDHT node " << info.node_id << " running on ";
if (info.bound4 == info.bound6)
std::cout << "port " << info.bound4 << std::endl;
void print_node_info(const dht::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 " << info.bound4 << ", IPv6 port " << info.bound6 << std::endl;
if (info.id)
std::cout << "Public key ID " << info.id << std::endl;
std::cout << "IPv4 port " << port4 << ", IPv6 port " << port6 << std::endl;
if (params.id.first)
std::cout << "Public key ID " << node.getId() << std::endl;
}
static const constexpr struct option long_options[] = {
@@ -290,7 +289,10 @@ parseArgs(int argc, char **argv) {
params.public_stable = true;
break;
case 'b':
params.bootstrap = (optarg[0] == '=') ? optarg+1 : optarg;
params.bootstrap = dht::splitPort((optarg[0] == '=') ? optarg+1 : optarg);
if (not params.bootstrap.first.empty() and params.bootstrap.second.empty()) {
params.bootstrap.second = std::to_string(dht::net::DHT_DEFAULT_PORT);
}
break;
case 'V':
params.version = true;
@@ -378,7 +380,7 @@ static const constexpr char* PROMPT = ">> ";
std::string
readLine(const char* prefix = PROMPT)
{
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
const char* line_read = readline(prefix);
if (line_read && *line_read)
add_history(line_read);
@@ -425,7 +427,7 @@ void signal_handler(int sig)
void setupSignals()
{
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
signal(SIGCHLD,SIG_IGN); /* ignore child */
signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
signal(SIGTTOU,SIG_IGN);
@@ -438,7 +440,7 @@ void setupSignals()
void daemonize()
{
#ifndef _MSC_VER
#ifndef WIN32_NATIVE
pid_t pid = fork();
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS);