Compare commits

..
Author SHA1 Message Date
Adrien Béraud 2bc8bf8e99 build: use msgpack cmake 2022-02-24 13:55:13 -05:00
151 changed files with 1589 additions and 2909 deletions

No files matched your search

-12
View File
@@ -1,12 +0,0 @@
{
"name": "C++",
"build": {
"dockerfile": "../docker/DockerfileDepsLlvm",
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
"settings": {},
"extensions": [
"ms-vscode.cpptools"
],
"forwardPorts": [4222],
}
+5 -58
View File
@@ -1,13 +1,14 @@
name: C/C++ CI
on: [push, pull_request]
on: [push]
jobs:
build-ubuntu:
name: Ubuntu/GCC build
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v1
- name: deps
run: |
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
@@ -28,57 +29,3 @@ jobs:
run: make
- name: make check
run: make check
build-ubuntu-minimal:
name: Ubuntu/GCC minimal build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: deps
run: |
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libcppunit-dev libmsgpack-dev libargon2-0-dev
- name: cmake
run: |
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug \
-DOPENDHT_C=Off -DOPENDHT_TESTS=On -DOPENDHT_PEER_DISCOVERY=Off -DOPENDHT_PYTHON=Off \
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=Off -DOPENDHT_PROXY_CLIENT=Off
- name: make
run: cd build && make
build-macos:
name: macOS/Clang build
runs-on: macos-11
steps:
- uses: actions/checkout@v3
- name: deps
run: |
brew install msgpack-cxx asio gnutls nettle readline fmt jsoncpp argon2 openssl http-parser cppunit
- name: restinio
run: |
mkdir restinio && cd restinio
wget https://github.com/aberaud/restinio/archive/bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz
ls -l && tar -xzf bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz
cd restinio-bbaa034dbcc7555ce67df0f8a1475591a7441733/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -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 && sudo make install
cd ../../.. && rm -rf restinio
- name: cmake
run: |
mkdir build && cd build
export PATH="/opt/homebrew/opt/openssl@3/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@3/include"
export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig"
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug \
-DOPENDHT_C=On -DOPENDHT_TESTS=On -DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off \
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
- name: make
run: cd build && make
-35
View File
@@ -1,35 +0,0 @@
name: Clang Static Analysis
on: [push, pull_request]
jobs:
clang-analyzer:
name: Clang Static Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: deps
run: |
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev libasio-dev \
llvm llvm-dev clang clang-tools && \
sudo apt remove gcc g++
- name: restinio
run: |
mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& ls -l && tar -xzf bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& cd restinio-bbaa034dbcc7555ce67df0f8a1475591a7441733/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 && sudo make install \
&& cd ../../.. && rm -rf restinio
- name: cmake
run: |
mkdir build && cd build && \
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DOPENDHT_C=On -DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off -DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
- name: scan-build
run: cd build && scan-build --status-bugs make
-53
View File
@@ -1,53 +0,0 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
container:
image: ghcr.io/savoirfairelinux/opendht/opendht-deps:latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
-223
View File
@@ -1,223 +0,0 @@
name: Release actions
on:
push:
tags:
- 'v*'
env:
REGISTRY: ghcr.io
IMAGE_NAME_DEPS: ${{ github.repository }}/opendht-deps
IMAGE_NAME: ${{ github.repository }}/opendht
IMAGE_NAME_DEPS_LLVM: ${{ github.repository }}/opendht-deps-llvm
IMAGE_NAME_LLVM: ${{ github.repository }}/opendht-llvm
IMAGE_NAME_DHTNODE: ${{ github.repository }}/dhtnode
jobs:
build-and-push-deps-image:
name: Dependency Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: docker/DockerfileDeps
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image:
name: OpenDHT Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: docker/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-deps-image-llvm:
name: Dependency Docker image (LLVM)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS_LLVM }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: docker/DockerfileDepsLlvm
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-llvm:
name: OpenDHT Docker image (LLVM)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LLVM }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: docker/DockerfileLlvm
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-dhtnode:
name: dhtnode Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DHTNODE }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
file: docker/DockerfileDhtnode
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-python-wheel:
name: Release and build Python Wheel package
runs-on: ubuntu-latest
container: ghcr.io/savoirfairelinux/opendht/opendht-deps:latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: cmake
run: |
mkdir build && cd build && \
cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_BUILD_TYPE=Release \
-DOPENDHT_STATIC=Off \
-DOPENDHT_PYTHON=On \
-DOPENDHT_C=Off \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_TOOLS=Off \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On
- name: build
run: cd build && make dist
- uses: actions/upload-artifact@v3
with:
name: opendht-wheels-linux
path: build/python/dist/*.whl
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
with:
draft: true
files: build/python/dist/*.whl
-1
View File
@@ -76,5 +76,4 @@ doc/Doxyfile
# build dir
build
build_dev
.DS_Store
+67
View File
@@ -0,0 +1,67 @@
dist: xenial
sudo: required
services:
- docker
language: cpp
env:
matrix:
- OPENDHT_TEST_JOB="opendht.classic"
- OPENDHT_TEST_JOB="opendht.llvm"
- OPENDHT_TEST_JOB="opendht.proxyserver"
- OPENDHT_TEST_JOB="opendht.proxyclient"
- OPENDHT_TEST_JOB="opendht.push"
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
docker pull aberaud/opendht-deps;
fi
if [[ "$OPENDHT_TEST_JOB" == *"opendht.llvm"* ]]; then
docker pull aberaud/opendht-deps-llvm
fi
script:
- |
# classic build
if [[ "$OPENDHT_TEST_JOB" == *"opendht.classic"* ]]; then
docker build -t opendht -f docker/DockerfileTravis .;
fi
- |
# proxy builds
if [[ "$OPENDHT_TEST_JOB" != *"opendht.llvm"* ]] && [[ "$OPENDHT_TEST_JOB" != *"opendht.classic"* ]]; then
docker build -t opendht-proxy -f docker/DockerfileTravisProxy .;
options='-DOPENDHT_SANITIZE=On ';
if [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyserver"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.push"* ]]; then
options+='-DOPENDHT_PROXY_SERVER=ON ';
else
options+='-DOPENDHT_PROXY_SERVER=OFF ';
fi
if [[ "$OPENDHT_TEST_JOB" == *"opendht.proxyclient"* ]] || [[ "$OPENDHT_TEST_JOB" == *"opendht.push"* ]]; then
options+='-DOPENDHT_PROXY_CLIENT=ON ';
else
options+='-DOPENDHT_PROXY_CLIENT=OFF ';
fi
if [[ "$OPENDHT_TEST_JOB" == *"opendht.push"* ]]; then
options+='-DOPENDHT_PUSH_NOTIFICATIONS=ON ';
else
options+='-DOPENDHT_PUSH_NOTIFICATIONS=OFF ';
fi
docker run opendht-proxy /bin/sh -c "cd /root/opendht && mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=ON -DOPENDHT_LTO=ON -DOPENDHT_TESTS=ON $options .. && make -j8 && ./opendht_unit_tests && make install";
fi
- |
# llvm build
if [[ "$OPENDHT_TEST_JOB" == *"opendht.llvm"* ]]; then
docker build -f docker/DockerfileTravisLlvm .
fi
notifications:
email:
- adrien.beraud@savoirfairelinux.com
-54
View File
@@ -1,54 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "dhtnode",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build_dev/tools/dhtnode",
"args": ["-v", "-p", "4222"],
"cwd": "${workspaceFolder}/build_dev",
"environment": [],
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"linux": {
"MIMode": "gdb",
"externalConsole": false,
},
"osx": {
"MIMode": "lldb",
"externalConsole": true,
},
},
{
"name": "tests",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build_dev/opendht_unit_tests",
"cwd": "${workspaceFolder}/build_dev",
"environment": [],
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"linux": {
"MIMode": "gdb",
"externalConsole": false,
},
"osx": {
"MIMode": "lldb",
"externalConsole": true,
},
}
]
}
-46
View File
@@ -1,46 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/build_dev"
},
"command": "make",
"args": ["-j4"],
"dependsOn": "cmake"
},
{
"label": "cmake",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/build_dev"
},
"command": "cmake",
"args": [
"${workspaceRoot}",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=On",
"-DCMAKE_BUILD_TYPE=Debug",
"-DOPENDHT_SANITIZE=On",
"-DOPENDHT_PROXY_CLIENT=On",
"-DOPENDHT_PROXY_SERVER=On",
"-DOPENDHT_TESTS=On",
"-DOPENDHT_C=On"
],
"dependsOn": "builddir"
},
{
"label": "builddir",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}"
},
"command": "mkdir",
"args": [
"-p",
"${workspaceRoot}/build_dev"
]
},
]
}
+76 -66
View File
@@ -1,4 +1,10 @@
cmake_minimum_required (VERSION 3.10..3.20)
cmake_minimum_required (VERSION 3.1)
if(POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
if(POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
if(POLICY CMP0073)
cmake_policy(SET CMP0073 NEW)
endif()
@@ -9,12 +15,11 @@ project (opendht)
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(CheckIncludeFileCXX)
include(FindPkgConfig)
include(cmake/CheckAtomic.cmake)
set (opendht_VERSION_MAJOR 2)
set (opendht_VERSION_MINOR 4.12)
set (opendht_VERSION_MINOR 3.2)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -27,6 +32,7 @@ option (OPENDHT_PYTHON "Build Python bindings" OFF)
option (OPENDHT_TOOLS "Build DHT tools" ON)
option (OPENDHT_SYSTEMD "Install systemd module" OFF)
option (OPENDHT_SYSTEMD_UNIT_FILE_LOCATION "Where to install systemd unit file")
option (OPENDHT_LTO "Build with LTO" OFF)
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp" OFF)
option (OPENDHT_PUSH_NOTIFICATIONS "Enable push notifications support" OFF)
@@ -43,32 +49,22 @@ option (OPENDHT_C "Build C bindings" OFF)
find_package(Doxygen)
option (OPENDHT_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND})
# Build flags
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED on)
# Dependencies
if (NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
link_libraries (atomic)
endif ()
list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
if (NOT MSVC)
set (THREADS_PREFER_PTHREAD_FLAG TRUE)
find_package (Threads)
find_package (PkgConfig REQUIRED)
pkg_search_module (GnuTLS REQUIRED IMPORTED_TARGET gnutls)
pkg_search_module (Nettle REQUIRED IMPORTED_TARGET nettle)
find_package (msgpack REQUIRED NAMES msgpackc-cxx msgpack msgpack-cxx)
find_package (GnuTLS 3.3 REQUIRED)
pkg_search_module (Nettle REQUIRED nettle)
find_package (msgpack REQUIRED)
if (OPENDHT_TOOLS)
find_package (Readline 6 REQUIRED)
endif ()
pkg_search_module(argon2 REQUIRED IMPORTED_TARGET libargon2)
set(argon2_lib ", libargon2")
pkg_search_module(Jsoncpp IMPORTED_TARGET jsoncpp)
pkg_search_module(argon2 REQUIRED libargon2)
pkg_search_module(Jsoncpp jsoncpp)
if (Jsoncpp_FOUND)
add_definitions(-DOPENDHT_JSONCPP)
set(jsoncpp_lib ", jsoncpp")
list (APPEND opendht_SOURCES
src/base64.h
src/base64.cpp
@@ -85,16 +81,16 @@ if (NOT MSVC)
add_library(fmt SHARED IMPORTED)
find_library(HTTP_PARSER_LIBRARY http_parser)
add_library(http_parser SHARED IMPORTED)
set(http_parser_lib "-lhttp_parser")
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 IMPORTED_TARGET openssl)
pkg_search_module(OPENSSL REQUIRED openssl)
if (OPENSSL_FOUND)
message(STATUS "Found OpenSSL ${OPENSSL_VERSION} ${OPENSSL_INCLUDE_DIRS}")
set(openssl_lib ", openssl")
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIRS})
link_directories (${OPENSSL_LIBRARY_DIRS})
else ()
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
endif()
@@ -128,8 +124,12 @@ if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
add_definitions(-DASIO_STANDALONE)
endif()
# Build flags
set (CMAKE_CXX_STANDARD 14)
set (CMAKE_CXX_STANDARD_REQUIRED on)
if (NOT MSVC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wno-deprecated -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
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 ()
@@ -154,13 +154,37 @@ if (OPENDHT_LOG)
else ()
add_definitions(-DOPENDHT_LOG=false)
endif()
if (OPENDHT_LTO AND NOT MSVC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
if (CMAKE_COMPILER_IS_GNUCC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-linker-plugin")
set (CMAKE_AR "gcc-ar")
set (CMAKE_NM "gcc-nm")
set (CMAKE_RANLIB "gcc-ranlib")
endif ()
endif ()
if (MSGPACK_INCLUDE_DIRS)
include_directories (SYSTEM "${MSGPACK_INCLUDE_DIRS}")
endif ()
if (GNUTLS_INCLUDE_DIRS)
include_directories (SYSTEM "${GNUTLS_INCLUDE_DIRS}")
endif ()
if (Nettle_INCLUDE_DIRS)
include_directories (SYSTEM "${Nettle_INCLUDE_DIRS}")
endif ()
if (ASIO_INCLUDE_DIR)
include_directories (SYSTEM "${ASIO_INCLUDE_DIR}")
endif ()
if (Restinio_INCLUDE_DIR)
include_directories (SYSTEM "${Restinio_INCLUDE_DIR}")
endif ()
if (Jsoncpp_INCLUDE_DIRS)
include_directories (SYSTEM "${Jsoncpp_INCLUDE_DIRS}")
endif ()
link_directories (${Nettle_LIBRARY_DIRS})
link_directories (${Jsoncpp_LIBRARY_DIRS})
link_directories (${argon2_LIBRARY_DIRS})
include_directories (
./
include/
@@ -302,18 +326,10 @@ if (OPENDHT_STATIC)
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
target_link_libraries(opendht-static
PRIVATE PkgConfig::argon2
PUBLIC ${CMAKE_THREAD_LIBS_INIT} PkgConfig::GnuTLS PkgConfig::Nettle msgpackc-cxx
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
if (Jsoncpp_FOUND)
target_link_libraries(opendht-static PUBLIC PkgConfig::Jsoncpp)
endif()
if (OPENDHT_PROXY_OPENSSL)
target_link_libraries(opendht-static PUBLIC PkgConfig::OPENSSL)
endif()
if (APPLE)
target_link_libraries(opendht-static PRIVATE SYSTEM "-framework CoreFoundation" "-framework Security")
endif()
PRIVATE ${argon2_LIBRARIES}
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_STATIC_LIBRARIES}
${Jsoncpp_STATIC_LIBRARIES} ${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
${OPENSSL_STATIC_LIBRARIES} msgpackc-cxx)
else ()
if (OPENDHT_TOOLS)
function (add_obj_lib name libfile)
@@ -373,43 +389,35 @@ if (OPENDHT_SHARED)
set_target_properties (opendht PROPERTIES IMPORT_SUFFIX "_import.lib")
set_target_properties (opendht PROPERTIES SOVERSION ${opendht_VERSION_MAJOR} VERSION ${opendht_VERSION})
target_compile_definitions(opendht PRIVATE OPENDHT_BUILD)
target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT} msgpackc-cxx
PRIVATE PkgConfig::GnuTLS PkgConfig::Nettle
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} PkgConfig::argon2)
if (Jsoncpp_FOUND)
target_link_libraries(opendht PUBLIC PkgConfig::Jsoncpp)
endif()
if (OPENDHT_PROXY_OPENSSL)
target_link_libraries(opendht PUBLIC PkgConfig::OPENSSL)
endif()
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
if (APPLE)
target_link_libraries(opendht PRIVATE SYSTEM "-framework CoreFoundation" "-framework Security")
target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} msgpackc-cxx
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${argon2_LIBRARIES}
SYSTEM "-framework CoreFoundation" "-framework Security")
else ()
target_link_libraries(opendht
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} msgpackc-cxx
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
${Jsoncpp_LIBRARIES}
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${argon2_LIBRARIES})
endif ()
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif ()
if (OPENDHT_C)
add_library (opendht-c SHARED
c/opendht.cpp
c/opendht_c.h
)
target_compile_definitions(opendht-c PRIVATE OPENDHT_C_BUILD)
if (OPENDHT_SHARED)
add_library (opendht-c SHARED
c/opendht.cpp
c/opendht_c.h
)
target_compile_definitions(opendht-c PRIVATE OPENDHT_C_BUILD)
target_link_libraries(opendht-c PRIVATE opendht)
set_target_properties (opendht-c PROPERTIES SOVERSION ${opendht_VERSION_MAJOR} VERSION ${opendht_VERSION})
install (TARGETS opendht-c DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht-c)
endif ()
if (OPENDHT_STATIC)
add_library (opendht-c-static STATIC
c/opendht.cpp
c/opendht_c.h
)
set_target_properties (opendht-c-static PROPERTIES OUTPUT_NAME "opendht-c")
target_link_libraries(opendht-c-static PRIVATE opendht-static)
install (TARGETS opendht-c-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht-c-static)
target_link_libraries(opendht-c opendht)
else ()
target_link_libraries(opendht-c opendht-static)
endif ()
# PkgConfig module
@@ -418,6 +426,7 @@ if (OPENDHT_C)
opendht-c.pc
@ONLY
)
install (TARGETS opendht-c DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht-c)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/opendht-c.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install (FILES c/opendht_c.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include/opendht)
endif ()
@@ -451,7 +460,7 @@ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/opendhtConfigVersion.cmake DESTINATIO
# Unit tests
if (OPENDHT_TESTS)
pkg_search_module(Cppunit REQUIRED IMPORTED_TARGET cppunit)
pkg_search_module(Cppunit REQUIRED cppunit)
# unit testing
list (APPEND test_FILES
tests/infohashtester.h
@@ -494,11 +503,12 @@ if (OPENDHT_TESTS)
endif ()
target_link_libraries(opendht_unit_tests
${CMAKE_THREAD_LIBS_INIT}
PkgConfig::Cppunit
${Cppunit_LIBRARIES}
${GNUTLS_LIBRARIES}
${Jsoncpp_LIBRARIES}
)
if (OPENDHT_PROXY_OPENSSL)
target_link_libraries(opendht_unit_tests PkgConfig::OPENSSL)
target_link_libraries(opendht_unit_tests ${OPENSSL_LIBRARIES})
endif()
enable_testing()
add_test(TEST opendht_unit_tests)
-4
View File
@@ -4,10 +4,6 @@ SUBDIRS =
SUBDIRS += src
if ENABLE_C
SUBDIRS += c
endif
if ENABLE_TOOLS
SUBDIRS += tools
endif
+6 -6
View File
@@ -4,7 +4,7 @@
<a id="user-content-opendht-" class="anchor" href="/savoirfairelinux/opendht/blob/master/README.md#opendht-" aria-hidden="true"></a>OpenDHT
</h1>
A lightweight C++17 Distributed Hash Table implementation.
A lightweight C++14 Distributed Hash Table implementation.
OpenDHT provides an easy to use distributed in-memory data store.
Every node in the network can read and write values to the store.
@@ -14,7 +14,7 @@ Values are distributed over the network, with redundancy.
* High resilience to network disruption
* Public key cryptography layer providing optional data signature and encryption (using GnuTLS)
* IPv4 and IPv6 support
* Clean and powerful **C++17** map API
* Clean and powerful **C++14** map API
* Bindings for **C, Rust & Python 3**
* REST API with optional HTTP client+server with push notification support
@@ -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++17 -lopendht
g++ main.cpp -std=c++14 -lopendht
```
## Examples
@@ -98,15 +98,15 @@ for r in results:
- Nettle 2.4+, a GnuTLS dependency for crypto.
- (optional) restinio used for the REST API.
- (optional) jsoncpp 1.7.4-3+, used for the REST API.
- Build tested with GCC 7+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
- Build tested with Microsoft Visual Studio 2017, 2019, 2022
- Build tested with GCC 5.2+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
- Build tested with Microsoft Visual Studio 2015, 2017, 2019
## Contact
IRC: join us on Libera.chat at [`#opendht`](https://web.libera.chat/#opendht).
## License
Copyright (C) 2014-2022 Savoir-faire Linux Inc.
Copyright (C) 2014-2020 Savoir-faire Linux Inc.
OpenDHT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
-15
View File
@@ -1,15 +0,0 @@
lib_LTLIBRARIES = libopendht-c.la
noinst_HEADERS = opendht_c.h
AM_CPPFLAGS = -DOPENDHT_C_BUILD -isystem @top_srcdir@/include @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@
if OPENDHT_SHARED
AM_CPPFLAGS += -Dopendht_c_EXPORTS
endif
libopendht_c_la_LIBADD = $(LIBOBJS) ../src/.libs/libopendht.la
libopendht_c_la_SOURCES = \
opendht.cpp
nobase_include_HEADERS = \
opendht_c.h
+39 -116
View File
@@ -1,25 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "opendht_c.h"
#include <opendht.h>
#include <opendht/log.h>
#include "opendht.h"
using ValueSp = std::shared_ptr<dht::Value>;
using PrivkeySp = std::shared_ptr<dht::crypto::PrivateKey>;
@@ -30,13 +10,6 @@ using CertSp = std::shared_ptr<dht::crypto::Certificate>;
extern "C" {
#endif
#include <errno.h>
const char* dht_version()
{
return dht::version();
}
// dht::InfoHash
inline dht_infohash dht_infohash_to_c(const dht::InfoHash& h) {
@@ -76,11 +49,7 @@ bool dht_infohash_is_zero(const dht_infohash* h) {
}
void dht_infohash_from_hex(dht_infohash* h, const char* dat) {
*h = dht_infohash_to_c(dht::InfoHash(std::string_view(dat, HASH_LEN*2)));
}
void dht_infohash_from_hex_null(dht_infohash* h, const char* dat) {
*h = dht_infohash_to_c(dht::InfoHash(std::string_view(dat)));
*h = dht_infohash_to_c(dht::InfoHash(std::string(dat, HASH_LEN*2)));
}
const char* dht_pkid_print(const dht_pkid* h) {
@@ -185,13 +154,9 @@ bool dht_publickey_check_signature(const dht_publickey* pk, const char* data, si
dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_t data_size) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
try {
auto rdata = std::make_unique<dht::Blob>();
*rdata = pkey->encrypt((const uint8_t*)data, data_size);
return (dht_blob*)rdata.release();
} catch (...) {
return nullptr;
}
auto rdata = new dht::Blob;
*rdata = pkey->encrypt((const uint8_t*)data, data_size);
return (dht_blob*)rdata;
}
// dht::crypto::PrivateKey
@@ -221,17 +186,6 @@ dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
return reinterpret_cast<dht_publickey*>(new PubkeySp(key->getSharedPublicKey()));
}
dht_blob* dht_privatekey_decrypt(const dht_privatekey* k, const char* data, size_t data_size) {
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
try {
auto rdata = std::make_unique<dht::Blob>();
*rdata = key->decrypt((const uint8_t*)data, data_size);
return (dht_blob*)rdata.release();
} catch (...) {
return nullptr;
}
}
void dht_privatekey_delete(dht_privatekey* pk) {
delete reinterpret_cast<PrivkeySp*>(pk);
}
@@ -303,7 +257,7 @@ void dht_runner_config_default(dht_runner_config* config) {
}
// dht::DhtRunner
dht_runner* dht_runner_new(void) {
dht_runner* dht_runner_new() {
return reinterpret_cast<dht_runner*>(new dht::DhtRunner);
}
@@ -311,62 +265,39 @@ void dht_runner_delete(dht_runner* runner) {
delete reinterpret_cast<dht::DhtRunner*>(runner);
}
int dht_runner_run(dht_runner* r, in_port_t port) {
void dht_runner_run(dht_runner* r, in_port_t port) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
try {
runner->run(port, {}, true);
} catch(...) {
return ENOTCONN;
}
return 0;
runner->run(port, {}, true);
}
int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
void dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
try {
dht::DhtRunner::Config config;
config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(&conf->dht_config.node_config.node_id);
config.dht_config.node_config.network = conf->dht_config.node_config.network;
config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
? std::string(conf->dht_config.node_config.persist_path) : std::string{};
dht::DhtRunner::Config config;
config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(&conf->dht_config.node_config.node_id);
config.dht_config.node_config.network = conf->dht_config.node_config.network;
config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
? std::string(conf->dht_config.node_config.persist_path) : std::string{};
if (conf->dht_config.id.privatekey)
config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
if (conf->dht_config.id.privatekey)
config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
if (conf->dht_config.id.certificate)
config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
if (conf->dht_config.id.certificate)
config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
config.threaded = conf->threaded;
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
config.push_topic = conf->push_topic ? std::string(conf->push_topic) : std::string{};
config.push_platform = conf->push_platform ? std::string(conf->push_platform) : std::string{};
config.peer_discovery = conf->peer_discovery;
config.peer_publish = conf->peer_publish;
dht::DhtRunner::Context context;
if (conf->log) {
context.logger = dht::log::getStdLogger();
}
runner->run(port, config, std::move(context));
} catch(...) {
return ENOTCONN;
}
return 0;
config.threaded = conf->threaded;
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
config.peer_discovery = conf->peer_discovery;
config.peer_publish = conf->peer_publish;
runner->run(port, config);
}
void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len, dht_done_cb done_cb, void* cb_user_data) {
void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
if (done_cb) {
runner->bootstrap(dht::SockAddr(addr, addr_len), [done_cb, cb_user_data](bool ok){
done_cb(ok, cb_user_data);
});
} else {
runner->bootstrap(dht::SockAddr(addr, addr_len));
}
runner->bootstrap(dht::SockAddr(addr, addr_len));
}
void dht_runner_bootstrap(dht_runner* r, const char* host, const char* service) {
@@ -405,11 +336,8 @@ dht_op_token* dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto fret = new std::future<size_t>;
*fret = runner->listen(*hash, [
cb,
cb_user_data,
guard = done_cb ? std::make_shared<ScopeGuardCb>(done_cb, cb_user_data) : std::shared_ptr<ScopeGuardCb>{}
](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) {
auto guard = done_cb ? std::make_shared<ScopeGuardCb>(done_cb, cb_user_data) : std::shared_ptr<ScopeGuardCb>{};
*fret = runner->listen(*hash, [cb,cb_user_data, guard](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) {
for (const auto& value : values) {
if (not cb(reinterpret_cast<const dht_value*>(&value), expired, cb_user_data))
return false;
@@ -475,17 +403,6 @@ void dht_runner_shutdown(dht_runner* r, dht_shutdown_cb done_cb, void* cb_user_d
});
}
bool dht_runner_is_running(const dht_runner* r) {
if (not r) return false;
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
return runner->isRunning();
}
in_port_t dht_runner_get_bound_port(const dht_runner* r, sa_family_t af) {
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
return runner->getBoundPort(af);
}
dht_infohash dht_runner_get_node_id(const dht_runner* r) {
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
dht_infohash ret;
@@ -506,8 +423,14 @@ struct sockaddr** dht_runner_get_public_address(const dht_runner* r) {
if (addrs.empty())
return nullptr;
auto ret = (struct sockaddr**)malloc(sizeof(struct sockaddr*) * (addrs.size() + 1));
for (size_t i=0; i<addrs.size(); i++)
ret[i] = addrs[i].release();
for (size_t i=0; i<addrs.size(); i++) {
if (auto len = addrs[i].getLength()) {
ret[i] = (struct sockaddr*)malloc(len);
memcpy((struct sockaddr*)ret[i], addrs[i].get(), len);
} else {
ret[i] = nullptr;
}
}
ret[addrs.size()] = nullptr;
return ret;
}
+5 -35
View File
@@ -1,28 +1,10 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <opendht/def.h>
#include "def.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdbool.h>
@@ -36,8 +18,6 @@ struct OPENDHT_C_PUBLIC dht_data_view {
};
typedef struct dht_data_view dht_data_view;
OPENDHT_C_PUBLIC const char* dht_version(void);
// dht::Blob
struct OPENDHT_C_PUBLIC dht_blob;
typedef struct dht_blob dht_blob;
@@ -50,7 +30,6 @@ typedef struct dht_infohash dht_infohash;
OPENDHT_C_PUBLIC void dht_infohash_zero(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_random(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_from_hex(dht_infohash* h, const char* dat);
OPENDHT_C_PUBLIC void dht_infohash_from_hex_null(dht_infohash* h, const char* dat);
OPENDHT_C_PUBLIC void dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC void dht_infohash_get_from_string(dht_infohash* h, const char* str);
OPENDHT_C_PUBLIC const char* dht_infohash_print(const dht_infohash* h);
@@ -79,7 +58,6 @@ OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_generate(unsigned key_length_bit
OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password);
OPENDHT_C_PUBLIC int dht_privatekey_export(const dht_privatekey*, char* out, size_t* out_size, const char* password);
OPENDHT_C_PUBLIC dht_publickey* dht_privatekey_get_publickey(const dht_privatekey*);
OPENDHT_C_PUBLIC dht_blob* dht_privatekey_decrypt(const dht_privatekey*, const char* data, size_t data_size);
OPENDHT_C_PUBLIC void dht_privatekey_delete(dht_privatekey*);
// dht::crypto::Certificate
@@ -146,13 +124,10 @@ struct OPENDHT_PUBLIC dht_runner_config {
const char* proxy_server;
const char* push_node_id;
const char* push_token;
const char* push_topic;
const char* push_platform;
bool peer_discovery;
bool peer_publish;
dht_certificate* server_ca;
dht_identity client_identity;
bool log;
};
typedef struct dht_runner_config dht_runner_config;
OPENDHT_C_PUBLIC void dht_runner_config_default(dht_runner_config* config);
@@ -160,13 +135,11 @@ OPENDHT_C_PUBLIC void dht_runner_config_default(dht_runner_config* config);
// dht::DhtRunner
struct OPENDHT_C_PUBLIC dht_runner;
typedef struct dht_runner dht_runner;
OPENDHT_C_PUBLIC dht_runner* dht_runner_new(void);
OPENDHT_C_PUBLIC dht_runner* dht_runner_new();
OPENDHT_C_PUBLIC void dht_runner_delete(dht_runner* runner);
/* Returns 0 on success, standard error code on failure */
OPENDHT_C_PUBLIC int dht_runner_run(dht_runner* runner, in_port_t port);
/* Returns 0 on success, standard error code on failure */
OPENDHT_C_PUBLIC int dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
OPENDHT_C_PUBLIC void dht_runner_ping(dht_runner* runner, struct sockaddr* addr, socklen_t addr_len, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_run(dht_runner* runner, in_port_t port);
OPENDHT_C_PUBLIC void dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
OPENDHT_C_PUBLIC void dht_runner_ping(dht_runner* runner, struct sockaddr* addr, socklen_t addr_len);
OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host, const char* service);
OPENDHT_C_PUBLIC void dht_runner_get(dht_runner* runner, const dht_infohash* hash, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_op_token* dht_runner_listen(dht_runner* runner, const dht_infohash* hash, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data);
@@ -178,9 +151,6 @@ OPENDHT_C_PUBLIC void dht_runner_cancel_put(dht_runner* runner, const dht_infoha
OPENDHT_C_PUBLIC void dht_runner_shutdown(dht_runner* runner, dht_shutdown_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_node_id(const dht_runner* runner);
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_id(const dht_runner* runner);
OPENDHT_C_PUBLIC bool dht_runner_is_running(const dht_runner* runner);
OPENDHT_C_PUBLIC in_port_t dht_runner_get_bound_port(const dht_runner* runner, sa_family_t af);
/** Returns null-terminated array that must be freed after use as well as each element */
OPENDHT_C_PUBLIC struct sockaddr** dht_runner_get_public_address(const dht_runner* runner);
#ifdef __cplusplus
+75 -83
View File
@@ -1,103 +1,95 @@
# atomic builtins are required for threading support.
# University of Illinois/NCSA
# Open Source License
#
# Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
# All rights reserved.
#
# Developed by:
#
# LLVM Team
#
# University of Illinois at Urbana-Champaign
#
# http://llvm.org
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal with
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimers.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimers in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the names of the LLVM Team, University of Illinois at
# Urbana-Champaign, nor the names of its contributors may be used to
# endorse or promote products derived from this Software without specific
# prior written permission.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
# SOFTWARE.
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/DetermineGCCCompatible.cmake")
include(CheckCXXSourceCompiles)
include(CheckLibraryExists)
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() {
++z;
++y;
return ++x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
function(check_working_cxx_atomics64 varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
get_directory_property(compile_options COMPILE_OPTIONS)
set(CMAKE_REQUIRED_FLAGS ${compile_options})
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0;
}
" ${varname})
std::atomic<int64_t> v1;
std::atomic<int64_t> v2;
int main(int, char**) {
return v1 + v2;
}" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics64)
endfunction(check_working_cxx_atomics)
# Check for (non-64-bit) atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)
elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
if(NOT DEFINED PROXYGEN_COMPILER_IS_GCC_COMPATIBLE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
elseif(MSVC)
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE OFF)
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel")
set(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE ON)
endif()
endif()
# This isn't necessary on MSVC, so avoid command-line switch annoyance
# by only running on GCC-like hosts.
if(PROXYGEN_COMPILER_IS_GCC_COMPATIBLE)
# First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if(HAVE_LIBATOMIC)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
list(APPEND CMAKE_CXX_STANDARD_LIBRARIES -latomic)
else()
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif()
endif()
# Check for 64 bit atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
# First check if atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
endif()
endif()
endif()
## TODO: This define is only used for the legacy atomic operations in
## llvm's Atomic.h, which should be replaced. Other code simply
## assumes C++11 <atomic> works.
CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER
#include <windows.h>
#endif
int main() {
#ifdef _MSC_VER
volatile LONG val = 1;
MemoryBarrier();
InterlockedCompareExchange(&val, 0, 1);
InterlockedIncrement(&val);
InterlockedDecrement(&val);
#else
volatile unsigned long val = 1;
__sync_synchronize();
__sync_val_compare_and_swap(&val, 1, 0);
__sync_add_and_fetch(&val, 1);
__sync_sub_and_fetch(&val, 1);
#endif
return 0;
}
" LLVM_HAS_ATOMICS)
if( NOT LLVM_HAS_ATOMICS )
message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")
endif()
-13
View File
@@ -1,13 +0,0 @@
# Determine if the compiler has GCC-compatible command-line syntax.
if(NOT DEFINED LLVM_COMPILER_IS_GCC_COMPATIBLE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( MSVC )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE OFF)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
endif()
endif()
+18 -31
View File
@@ -1,7 +1,7 @@
dnl define macros
m4_define([opendht_major_version], 2)
m4_define([opendht_minor_version], 4)
m4_define([opendht_patch_version], 12)
m4_define([opendht_minor_version], 3)
m4_define([opendht_patch_version], 2)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
@@ -18,33 +18,18 @@ AC_SUBST(OPENDHT_PATCH_VERSION, opendht_patch_version)
AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Build in debug mode, adds stricter warnings, disables optimization]))
AS_IF([test "x$enable_debug" = "xyes"],
[CXXFLAGS="${CXXFLAGS} -g -Og -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -Wno-deprecated -pedantic-errors"],
[CXXFLAGS="${CXXFLAGS} -O3 -Wno-deprecated -pedantic-errors -fvisibility=hidden"])
[CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -O0 -pedantic-errors"],
[CXXFLAGS="${CXXFLAGS} -O3 -pedantic-errors"])
CPPFLAGS+=" -DOPENDHT_BUILD"
AM_CONDITIONAL([OPENDHT_SHARED], [test "x$enable_shared" != xno])
AM_COND_IF(OPENDHT_SHARED, [
CPPFLAGS+=" -Dopendht_EXPORTS"
])
AM_PROG_AR
LT_INIT()
LT_LANG(C++)
AC_LANG(C++)
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX(17,[noext],[mandatory])
AM_PROG_AR
dnl Check for logs
AC_ARG_ENABLE([logs], [AS_HELP_STRING([--disable-logs], [Disable DHT logs])])
AS_IF([test "x$enable_logs" != "xno"], [], [
AC_DEFINE([OPENDHT_LOG], [false], [Define if DHT logs are disabled])
])
dnl Check for C binding
AC_ARG_ENABLE([c], [AS_HELP_STRING([--disable-c], [Disable DHT C binding])])
AM_CONDITIONAL(ENABLE_C, test x$enable_c != "xno")
AM_COND_IF(ENABLE_C, [
AC_DEFINE([OPENDHT_C], [], [Define if DHT C biding is enabled])
AS_IF([test "x$enable_logs" != "xno"], [
AC_DEFINE([OPENDHT_LOG], [true], [Define if DHT logs are enabled])
], [
AC_DEFINE([OPENDHT_LOG], [false], [Define if DHT logs are enabled])
])
dnl Check for indexation
@@ -114,6 +99,11 @@ AM_CONDITIONAL(WIN32, [test "x$SYS" = "xmingw32"])
AS_IF([test "x$SYS" = "xandroid"],
[], [LDFLAGS="${LDFLAGS} -lpthread"])
LT_INIT()
LT_LANG(C++)
AX_CXX_COMPILE_STDCXX(14,[noext],[mandatory])
PKG_PROG_PKG_CONFIG()
AC_ARG_ENABLE([proxy_server], AS_HELP_STRING([--enable-proxy-server], [Enable proxy server ability]), proxy_server=yes, proxy_server=no)
@@ -132,8 +122,8 @@ AC_ARG_ENABLE([proxy_client], AS_HELP_STRING([--enable-proxy-client], [Enable pr
AM_CONDITIONAL(ENABLE_PROXY_CLIENT, test x$proxy_client == xyes)
AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [Enable tests]), build_tests=yes, build_tests=no)
AM_CONDITIONAL(ENABLE_TESTS, test "x$build_tests" == xyes)
AS_IF([test "x$build_tests" == xyes], [
AM_CONDITIONAL(ENABLE_TESTS, test x$build_tests == xyes)
AM_COND_IF([ENABLE_TESTS], [
PKG_CHECK_MODULES([CppUnit], [cppunit >= 1.12])
])
@@ -141,9 +131,7 @@ AM_CONDITIONAL(PROXY_CLIENT_OR_SERVER, test x$proxy_client == xyes || test x$pro
PKG_CHECK_MODULES([Nettle], [nettle >= 2.4])
PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.3])
AC_CHECK_HEADERS([msgpack.hpp], [], [
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
])
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
PKG_CHECK_MODULES([Argon2], [libargon2])
AC_SUBST(argon2_lib, [", libargon2"])
@@ -172,7 +160,7 @@ AS_IF([test "x$have_openssl" = "xyes"], [
])
AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
AC_CHECK_HEADERS([asio.hpp],, AC_MSG_ERROR([Missing Asio headers files]))
AC_CHECK_HEADERS([asio.hpp], exit,, AC_MSG_ERROR([Missing Asio headers files]))
CXXFLAGS="${CXXFLAGS} -DASIO_STANDALONE"
PKG_CHECK_MODULES([Fmt], [fmt >= 5.3.0], [have_fmt=yes], [have_fmt=no])
AS_IF([test "x$have_fmt" = "xyes"], [
@@ -210,7 +198,6 @@ AC_SUBST(PROJECT_BINARY_DIR, "../src/.libs")
AC_CONFIG_FILES([Makefile
src/Makefile
c/Makefile
tools/Makefile
python/Makefile
python/setup.py
+3 -14
View File
@@ -1,17 +1,6 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
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 \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+8 -11
View File
@@ -1,16 +1,13 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-bionic:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.1.3
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
&& make -j8 && make install \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_C=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_LTO=On \
&& make -j8 && make install \
&& cd ../.. && rm -rf opendht
+8 -9
View File
@@ -1,6 +1,5 @@
FROM ubuntu:22.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
FROM ubuntu:20.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y \
dialog apt-utils \
@@ -9,18 +8,18 @@ RUN apt-get update && apt-get install -y \
RUN apt-get update && apt-get install -y \
build-essential pkg-config cmake git wget \
libtool autotools-dev autoconf \
cython3 python3-dev python3-setuptools python3-build python3-virtualenv \
autotools-dev autoconf \
cython3 python3-dev python3-setuptools \
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
libssl-dev libfmt-dev libhttp-parser-dev libasio-dev libmsgpack-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
&& apt-get clean
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& ls -l && tar -xzf bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& cd restinio-bbaa034dbcc7555ce67df0f8a1475591a7441733/dev \
&& wget https://github.com/aberaud/restinio/archive/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
+4 -6
View File
@@ -1,16 +1,14 @@
FROM ubuntu:18.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
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 \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
libargon2-0-dev \
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev python3-pip \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev \
&& apt-get clean
RUN pip3 install --upgrade cmake
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 ***" \
-28
View File
@@ -1,28 +0,0 @@
FROM ubuntu:20.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
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 \
libtool autotools-dev autoconf \
cython3 python3-dev python3-setuptools \
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
libssl-dev libfmt-dev libhttp-parser-dev libasio-dev libmsgpack-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
&& ls -l && tar -xzf e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
&& cd restinio-e0a261dd8488246a3cb8bbb3ea781ea5139c3c94/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
+8 -12
View File
@@ -1,30 +1,26 @@
FROM ubuntu:22.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
FROM ubuntu:20.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update \
&& apt-get install -y llvm llvm-dev lldb clang gdb make cmake pkg-config \
libtool git wget libncurses5-dev libreadline-dev \
&& apt-get install -y llvm llvm-dev clang make cmake pkg-config git wget libncurses5-dev libreadline-dev \
nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev cython3 python3-dev \
python3-setuptools libcppunit-dev python3-pip python3-build python3-virtualenv \
python3-setuptools libcppunit-dev python3-pip \
autotools-dev autoconf libssl-dev libargon2-dev \
libfmt-dev libhttp-parser-dev libasio-dev \
&& apt-get remove -y gcc g++ && apt-get autoremove -y \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
ENV CC cc
ENV CXX c++
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& ls -l && tar -xzf bbaa034dbcc7555ce67df0f8a1475591a7441733.tar.gz \
&& cd restinio-bbaa034dbcc7555ce67df0f8a1475591a7441733/dev \
&& wget https://github.com/aberaud/restinio/archive/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
-4
View File
@@ -1,4 +0,0 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht:latest
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
EXPOSE 4222/udp
EXPOSE 8080/tcp
-16
View File
@@ -1,16 +0,0 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-bionic:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
RUN git clone https://github.com/savoirfairelinux/opendht.git \
&& cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
&& make -j8 && make install \
&& cd ../.. && rm -rf opendht
+3 -14
View File
@@ -1,17 +1,6 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-llvm:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
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 \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
&& cd ../.. && rm -rf opendht
+9
View File
@@ -0,0 +1,9 @@
FROM aberaud/opendht-deps-bionic
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
COPY . /root/opendht
RUN cd /root/opendht && mkdir build && cd build \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_C=On -DOPENDHT_LTO=On -DOPENDHT_TESTS=ON .. \
&& make -j8 && ./opendht_unit_tests && make install
+7
View File
@@ -0,0 +1,7 @@
FROM aberaud/opendht-deps-llvm
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
COPY . /root/opendht
RUN cd /root/opendht && mkdir build && cd build \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_C=On -DOPENDHT_TESTS=ON .. \
&& make -j8 && ./opendht_unit_tests && make install
+4
View File
@@ -0,0 +1,4 @@
FROM aberaud/opendht-deps
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
COPY . /root/opendht
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -82,8 +82,6 @@ struct OPENDHT_PUBLIC NodeInfo {
NodeStats ipv4 {};
NodeStats ipv6 {};
size_t ongoing_ops {0};
size_t storage_values {0};
size_t storage_size {0};
in_port_t bound4 {0};
in_port_t bound6 {0};
@@ -134,9 +132,6 @@ struct OPENDHT_PUBLIC Config {
/* If non-0, overrides the default maximum store size. -1 means no limit. */
ssize_t max_store_size {0};
/* If non-0, overrides the default maximum store key count. -1 means no limit. */
ssize_t max_store_keys {0};
/**
* Use appropriate bahavior for a public IP, stable node:
* - No connectivity change triggered when a search fails
+14 -31
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
@@ -32,9 +32,6 @@ extern "C" {
#include <vector>
#include <memory>
#include <atomic>
#include <mutex>
#include <string_view>
#ifdef _WIN32
#include <iso646.h>
@@ -87,13 +84,12 @@ struct OPENDHT_PUBLIC PublicKey
/** Import public key from serialized data */
PublicKey(const uint8_t* dat, size_t dat_size);
PublicKey(const Blob& pk) : PublicKey(pk.data(), pk.size()) {}
PublicKey(std::string_view pk) : PublicKey((const uint8_t*)pk.data(), pk.size()) {}
PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; }
PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; };
~PublicKey();
explicit operator bool() const { return pk; }
bool operator ==(const PublicKey& o) const {
return pk == o.pk || getLongId() == o.getLongId();
return pk == o.pk || getId() == o.getId();
}
bool operator !=(const PublicKey& o) const {
return !(*this == o);
@@ -104,12 +100,12 @@ struct OPENDHT_PUBLIC PublicKey
/**
* Get public key fingerprint
*/
const InfoHash& getId() const;
InfoHash getId() const;
/**
* Get public key long fingerprint
*/
const PkId& getLongId() const;
PkId getLongId() const;
bool checkSignature(const uint8_t* data, size_t data_len, const uint8_t* signature, size_t signature_len) const;
inline bool checkSignature(const Blob& data, const Blob& signature) const {
@@ -120,9 +116,7 @@ struct OPENDHT_PUBLIC PublicKey
inline Blob encrypt(const Blob& data) const {
return encrypt(data.data(), data.size());
}
inline Blob encrypt(std::string_view data) const {
return encrypt((const uint8_t*)data.data(), data.size());
}
void pack(Blob& b) const;
int pack(uint8_t* out, size_t* out_len) const;
void unpack(const uint8_t* dat, size_t dat_size);
@@ -144,11 +138,6 @@ struct OPENDHT_PUBLIC PublicKey
gnutls_pubkey_t pk {nullptr};
private:
mutable InfoHash cachedId_ {};
mutable PkId cachedLongId_ {};
mutable std::atomic_bool idCached_ {false};
mutable std::atomic_bool longIdCached_ {false};
PublicKey(const PublicKey&) = delete;
PublicKey& operator=(const PublicKey&) = delete;
void encryptBloc(const uint8_t* src, size_t src_size, uint8_t* dst, size_t dst_size) const;
@@ -171,9 +160,7 @@ struct OPENDHT_PUBLIC PrivateKey
PrivateKey& operator=(PrivateKey&& o) noexcept;
PrivateKey(const uint8_t* src, size_t src_size, const char* password = nullptr);
PrivateKey(const Blob& src, const std::string& password = {}) : PrivateKey(src.data(), src.size(), password.c_str()) {}
PrivateKey(std::string_view src, const std::string& password = {}) : PrivateKey((const uint8_t*)src.data(), src.size(), password.c_str()) {}
PrivateKey(const Blob& src, const std::string& password = {}) : PrivateKey(src.data(), src.size(), password.data()) {}
~PrivateKey();
explicit operator bool() const { return key; }
@@ -188,7 +175,6 @@ struct OPENDHT_PUBLIC PrivateKey
* @returns the signature data.
*/
Blob sign(const uint8_t* data, size_t data_len) const;
inline Blob sign(std::string_view dat) const { return sign((const uint8_t*)dat.data(), dat.size()); }
inline Blob sign(const Blob& dat) const { return sign(dat.data(), dat.size()); }
/**
@@ -215,7 +201,6 @@ private:
PrivateKey& operator=(const PrivateKey&) = delete;
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
mutable std::mutex publicKeyMutex_ {};
mutable std::shared_ptr<PublicKey> publicKey_ {};
};
@@ -301,7 +286,6 @@ class OPENDHT_PUBLIC CertificateRequest {
public:
CertificateRequest();
CertificateRequest(const uint8_t* data, size_t size);
CertificateRequest(std::string_view src) : CertificateRequest((const uint8_t*)src.data(), src.size()) {}
CertificateRequest(const Blob& data) : CertificateRequest(data.data(), data.size()) {}
CertificateRequest(CertificateRequest&& o) noexcept : request(std::move(o.request)) {
@@ -335,9 +319,8 @@ private:
class OPENDHT_PUBLIC OcspRequest
{
public:
OcspRequest(gnutls_ocsp_req_t r) : request(r) {}
OcspRequest(gnutls_ocsp_req_t r) : request(r) {};
OcspRequest(const uint8_t* dat_ptr, size_t dat_size);
OcspRequest(std::string_view dat): OcspRequest((const uint8_t*)dat.data(), dat.size()) {}
~OcspRequest();
/*
@@ -355,7 +338,7 @@ class OPENDHT_PUBLIC OcspResponse
{
public:
OcspResponse(const uint8_t* dat_ptr, size_t dat_size);
OcspResponse(std::string_view response) : OcspResponse((const uint8_t*)response.data(), response.size()) {}
OcspResponse(const std::string& response) : OcspResponse((const uint8_t*)response.data(), response.size()) {};
~OcspResponse();
Blob pack() const;
@@ -397,10 +380,12 @@ struct OPENDHT_PUBLIC Certificate {
* ordered from subject to issuer
*/
Certificate(const Blob& crt);
Certificate(const std::string& pem) : cert(nullptr) {
unpack((const uint8_t*)pem.data(), pem.size());
}
Certificate(const uint8_t* dat, size_t dat_size) : cert(nullptr) {
unpack(dat, dat_size);
}
Certificate(std::string_view pem) : Certificate((const uint8_t*)pem.data(), pem.size()) {}
/**
* Import certificate chain (PEM or DER),
@@ -501,9 +486,9 @@ struct OPENDHT_PUBLIC Certificate {
PublicKey getPublicKey() const;
/** Same as getPublicKey().getId() */
const InfoHash& getId() const;
InfoHash getId() const;
/** Same as getPublicKey().getLongId() */
const PkId& getLongId() const;
PkId getLongId() const;
Blob getSerialNumber() const;
@@ -621,8 +606,6 @@ private:
Certificate& operator=(const Certificate&) = delete;
mutable InfoHash cachedId_ {};
mutable PkId cachedLongId_ {};
mutable std::atomic_bool idCached_ {false};
mutable std::atomic_bool longIdCached_ {false};
struct crlNumberCmp {
bool operator() (const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const {
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+4 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -302,9 +302,6 @@ public:
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
max_store_size = limit;
}
size_t getStorageLimit() const override {
return max_store_size;
}
/**
* Returns the total memory usage of stored values and the number
@@ -343,7 +340,7 @@ private:
static constexpr unsigned LISTEN_NODES {4};
/* The maximum number of hashes we're willing to track. */
static constexpr unsigned MAX_HASHES {1024 * 1024 * 1024};
static constexpr unsigned MAX_HASHES {1024 * 1024};
/* The maximum number of searches we keep data about. */
static constexpr unsigned MAX_SEARCHES {1024 * 1024};
@@ -450,13 +447,13 @@ private:
// Storage
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {}, int version = 0);
bool storageStore(const InfoHash& id, const Sp<Value>& value, time_point created, const SockAddr& sa = {}, bool permanent = false);
bool storageErase(const InfoHash& id, Value::Id vid);
bool storageRefresh(const InfoHash& id, Value::Id vid);
void expireStore();
void expireStorage(InfoHash h);
void expireStore(decltype(store)::iterator);
void storageRemoved(const InfoHash& id, Storage& st, const std::vector<Sp<Value>>& values, size_t totalSize);
void storageChanged(const InfoHash& id, Storage& st, const Sp<Value>&, bool newValue);
void storageChanged(const InfoHash& id, Storage& st, ValueStorage&, bool newValue);
std::string printStorageLog(const decltype(store)::value_type&) const;
/**
+1 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -221,7 +221,6 @@ public:
* Set the in-memory storage limit in bytes
*/
virtual void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) = 0;
virtual size_t getStorageLimit() const = 0;
/**
* Returns the total memory usage of stored values and the number
@@ -265,9 +264,6 @@ public:
virtual void setPushNotificationToken(const std::string&) {};
virtual void setPushNotificationTopic(const std::string&) {};
virtual void setPushNotificationPlatform(const std::string&) {};
/**
* Call linked callback with a push notification
* @param notification to process
+1 -40
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
@@ -67,22 +67,6 @@ public:
#endif
}
virtual void setPushNotificationTopic(const std::string& topic) override {
#ifdef OPENDHT_PUSH_NOTIFICATIONS
notificationTopic_ = topic;
#else
(void) topic;
#endif
}
virtual void setPushNotificationPlatform(const std::string& platform) override {
#ifdef OPENDHT_PUSH_NOTIFICATIONS
platform_ = platform;
#else
(void) platform;
#endif
}
virtual ~DhtProxyClient();
/**
@@ -279,7 +263,6 @@ public:
void dumpTables() const override {}
std::vector<unsigned> getNodeMessageStats(bool) override { return {}; }
void setStorageLimit(size_t) override {}
virtual size_t getStorageLimit() const override { return 0; }
void connectivityChanged(sa_family_t) override {
getProxyInfos();
}
@@ -352,8 +335,6 @@ private:
NodeStatus statusIpv6_ {NodeStatus::Disconnected};
NodeStats stats4_ {};
NodeStats stats6_ {};
SockAddr localAddrv4_;
SockAddr localAddrv6_;
SockAddr publicAddressV4_;
SockAddr publicAddressV6_;
std::atomic_bool launchConnectedCbs_ {false};
@@ -368,7 +349,6 @@ private:
* Note: Each context is used in one thread only
*/
asio::io_context httpContext_;
mutable std::mutex resolverLock_;
std::shared_ptr<http::Resolver> resolver_;
mutable std::mutex requestLock_;
@@ -419,25 +399,6 @@ private:
*/
std::string deviceKey_ {};
/**
* Notification topic for ios notifications.
*/
std::string notificationTopic_ {};
/**
* Platform for push notifications (supported android, ios, unifiedpush)
*/
std::string platform_
#ifdef __ANDROID__
{"android"};
#else
#ifdef __APPLE__
{"ios"};
#else
{};
#endif
#endif
const std::function<void()> loopSignal_;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
+8 -25
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
@@ -40,8 +40,7 @@ namespace dht {
enum class PushType {
None = 0,
Android,
iOS,
UnifiedPush
iOS
};
}
MSGPACK_ADD_ENUM(dht::PushType)
@@ -62,13 +61,11 @@ class DhtRunner;
using RestRouter = restinio::router::express_router_t<>;
using RequestStatus = restinio::request_handling_status_t;
struct OPENDHT_PUBLIC ProxyServerConfig {
std::string address {};
struct ProxyServerConfig {
in_port_t port {8000};
std::string pushServer {};
std::string persistStatePath {};
dht::crypto::Identity identity {};
std::string bundleId {};
};
/**
@@ -276,11 +273,6 @@ private:
restinio::router::route_params_t params);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
PushType getTypeFromString(const std::string& type);
std::string getDefaultTopic(PushType type);
RequestStatus pingPush(restinio::request_handle_t request,
restinio::router::route_params_t /*params*/);
/**
* Subscribe to push notifications for an iOS or Android device.
* Method: SUBSCRIBE "/{InfoHash: .*}"
@@ -308,7 +300,7 @@ 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, const std::string& topic);
void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority);
/**
* Send push notification with an expire timeout.
@@ -316,10 +308,9 @@ private:
* @param pushToken
* @param json
* @param type
* @param topic
*/
void handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
std::function<Json::Value()> json, PushType type, const std::string& topic);
std::function<Json::Value()> json, PushType type);
/**
* Remove a push listener between a client and a hash
@@ -391,12 +382,11 @@ private:
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
Sp<Value> value;
PushType type;
std::string topic;
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) + (topic.empty() ? 0 : 1));
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()) {
@@ -410,9 +400,6 @@ private:
p.pack("t"); p.pack(type);
p.pack("token"); p.pack(pushToken);
}
if (not topic.empty()) {
p.pack("top"); p.pack(topic);
}
}
void msgpack_unpack(const msgpack::object& o);
@@ -428,7 +415,6 @@ private:
mutable std::atomic<time_point> lastStatsReset_ {time_point::min()};
std::string pushServer_;
std::string bundleId_;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
struct Listener {
@@ -439,12 +425,11 @@ private:
std::unique_ptr<asio::steady_timer> expireTimer;
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
PushType type;
std::string topic;
template <typename Packer>
void msgpack_pack(Packer& p) const
{
p.pack_map(3 + (sessionCtx ? 1 : 0) + (topic.empty() ? 0 : 1));
p.pack_map(sessionCtx ? 4 : 3);
p.pack("cid"); p.pack(clientId);
p.pack("exp"); p.pack(to_time_t(expiration));
if (sessionCtx) {
@@ -452,9 +437,6 @@ private:
p.pack("sid"); p.pack(sessionCtx->sessionId);
}
p.pack("t"); p.pack(type);
if (!topic.empty()) {
p.pack("top"); p.pack(topic);
}
}
void msgpack_unpack(const msgpack::object& o);
@@ -464,6 +446,7 @@ private:
MSGPACK_DEFINE_ARRAY(listeners)
};
std::map<std::string, PushListener> pushListeners_;
proxy::ListenToken tokenPushNotif_ {0};
#endif //OPENDHT_PUSH_NOTIFICATIONS
};
+22 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -61,8 +61,6 @@ public:
std::string proxy_server {};
std::string push_node_id {};
std::string push_token {};
std::string push_topic {};
std::string push_platform {};
bool peer_discovery {false};
bool peer_publish {false};
std::shared_ptr<dht::crypto::Certificate> server_ca;
@@ -274,14 +272,14 @@ public:
* Insert known nodes to the routing table, without necessarly ping them.
* Usefull to restart a node and get things running fast without putting load on the network.
*/
void bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb={});
void bootstrap(SockAddr addr, DoneCallbackSimple cb={});
void bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple&& cb={});
void bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb={});
/**
* Insert known nodes to the routing table, without necessarly ping them.
* Usefull to restart a node and get things running fast without putting load on the network.
*/
void bootstrap(std::vector<NodeExport> nodes);
void bootstrap(const std::vector<NodeExport>& nodes);
/**
* Add host:service to bootstrap nodes, and ping this node.
@@ -337,7 +335,6 @@ public:
std::pair<size_t, size_t> getStoreSize() const;
void getStorageLimit() const;
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT);
std::vector<NodeExport> exportNodes() const;
@@ -374,8 +371,8 @@ public:
std::string getRoutingTablesLog(sa_family_t af) const;
std::string getSearchesLog(sa_family_t af = AF_UNSPEC) const;
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;
std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC) const;
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC) const;
std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC);
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC);
void getPublicAddress(std::function<void(std::vector<SockAddr>&&)>, sa_family_t af = AF_UNSPEC);
// securedht methods
@@ -439,6 +436,7 @@ public:
/**
* Start or stop the proxy
* @param proxify if we want to use the proxy
* @param deviceKey non empty to enable push notifications
*/
void enableProxy(bool proxify);
@@ -449,16 +447,6 @@ public:
*/
void setPushNotificationToken(const std::string& token);
/**
* Sets the push notification topic
*/
void setPushNotificationTopic(const std::string& topic);
/**
* Sets the push notification platform
*/
void setPushNotificationPlatform(const std::string& platform);
/**
* Insert a push notification to process for OpenDHT
*/
@@ -485,9 +473,12 @@ private:
DoneCallback bindOpDoneCallback(DoneCallback&& cb);
DoneCallbackSimple bindOpDoneCallback(DoneCallbackSimple&& cb);
/** DHT instance */
/** Local DHT instance */
std::unique_ptr<SecureDht> dht_;
/** Proxy client instance */
std::unique_ptr<SecureDht> dht_via_proxy_;
/** true if we are currently using a proxy */
std::atomic_bool use_proxy {false};
@@ -499,6 +490,17 @@ private:
* reset dht clients
*/
void resetDht();
/**
* @return the current active DHT
*/
SecureDht* activeDht() const;
/**
* Store current listeners and translates global tokens for each client.
*/
struct Listener;
std::map<size_t, Listener> listeners_;
size_t listener_token_ {1};
mutable std::mutex dht_mtx {};
std::thread dht_thread {};
+3 -16
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -114,16 +114,13 @@ public:
void async_read(size_t bytes, BytesHandlerCb cb);
void async_read_some(size_t bytes, BytesHandlerCb cb);
const asio::ip::address& local_address() const;
void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {});
void timeout(const std::chrono::seconds timeout, HandlerCb cb = {});
void close();
private:
template<typename T>
T wrapCallback(T cb) const {
T wrapCallabck(T cb) const {
return [t=shared_from_this(),cb=std::move(cb)](auto ...params) {
cb(params...);
};
@@ -145,8 +142,6 @@ private:
asio::streambuf read_buf_;
std::istream istream_;
asio::ip::address local_address_;
std::unique_ptr<asio::steady_timer> timeout_timer_;
std::shared_ptr<dht::Logger> logger_;
bool checkOcsp_ {false};
@@ -266,11 +261,6 @@ public:
return resolver_->get_url();
};
void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {}) {
timeout_ = timeout;
timeoutCb_ = cb;
}
/** The previous request in case of redirect following */
std::shared_ptr<Request> getPrevious() const {
return prev_.lock();
@@ -380,9 +370,6 @@ private:
std::weak_ptr<Request> prev_;
unsigned num_redirect {0};
bool follow_redirect {true};
HandlerCb timeoutCb_ {};
std::chrono::seconds timeout_ {0};
};
} // namespace http
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Nicolas Reynaud <nicolas.reynaud@savoirfairelinux.com>
+20 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -40,12 +40,10 @@ typedef uint16_t in_port_t;
#include <iomanip>
#include <array>
#include <vector>
#include <string_view>
#include <algorithm>
#include <stdexcept>
#include <sstream>
#include <cstring>
#include <cstddef>
namespace dht {
@@ -67,10 +65,10 @@ public:
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
Hash() noexcept {
Hash () noexcept {
data_.fill(0);
}
Hash(const uint8_t* h, size_t data_len) {
Hash (const uint8_t* h, size_t data_len) {
if (data_len < N)
data_.fill(0);
else
@@ -81,12 +79,7 @@ public:
* hex must be at least 2.HASH_LEN characters long.
* If too long, only the first 2.HASH_LEN characters are read.
*/
explicit Hash(std::string_view hex) {
if (hex.size() < 2*N)
data_.fill(0);
else
fromString(hex.data());
}
explicit Hash(const std::string& hex);
Hash(const msgpack::object& o) {
msgpack_unpack(o);
@@ -103,7 +96,13 @@ public:
static constexpr inline Hash zero() noexcept { return Hash{}; }
bool operator==(const Hash& h) const {
return data_ == h.data_;
auto a = reinterpret_cast<const uint32_t*>(data_.data());
auto b = reinterpret_cast<const uint32_t*>(h.data_.data());
constexpr unsigned n = N / sizeof(uint32_t);
for (unsigned i=0; i < n; i++)
if (a[i] != b[i])
return false;
return true;
}
bool operator!=(const Hash& h) const { return !(*this == h); }
@@ -220,7 +219,7 @@ public:
return v;
}
static inline Hash get(std::string_view data) {
static inline Hash get(const std::string& data) {
return get((const uint8_t*)data.data(), data.size());
}
@@ -249,8 +248,6 @@ public:
template <size_t M>
OPENDHT_PUBLIC friend std::istream& operator>> (std::istream& s, Hash<M>& h);
/** Returns view to thread-allocated memory, only valid until the next call to this function. */
std::string_view to_view() const { return std::string_view(to_c_str(), N*2); }
const char* to_c_str() const;
std::string toString() const;
@@ -294,6 +291,14 @@ std::istream& operator>> (std::istream& s, Hash<N>& h)
return s;
}
template <size_t N>
Hash<N>::Hash(const std::string& hex) {
if (hex.size() < 2*N)
data_.fill(0);
else
fromString(hex.c_str());
}
template <size_t N>
void
Hash<N>::fromString(const char* in) {
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+11 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -252,12 +252,12 @@ public:
* @param values The values to send.
* @param version If version = 1, a request will be used to answer to the listener
*/
void tellListener(const Sp<Node>& n, Tid socket_id, const InfoHash& hash, want_t want, const Blob& ntoken,
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);
void tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
void tellListenerExpired(const 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, int version);
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
bool isRunning(sa_family_t af) const;
inline want_t want () const { return dht_socket->hasIPv4() and dht_socket->hasIPv6() ? (WANT4 | WANT6) : -1; }
@@ -278,7 +278,7 @@ public:
* @return the request with information concerning its success.
*/
Sp<Request>
sendPing(const Sp<Node>& n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
sendPing(Sp<Node> n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
/**
* Send a "ping" request to a given node.
@@ -309,7 +309,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendFindNode(const Sp<Node>& n,
Sp<Request> sendFindNode(Sp<Node> n,
const InfoHash& hash,
want_t want = -1,
RequestCb&& on_done = {},
@@ -328,7 +328,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendGetValues(const Sp<Node>& n,
Sp<Request> sendGetValues(Sp<Node> n,
const InfoHash& hash,
const Query& query,
want_t want,
@@ -357,7 +357,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendListen(const Sp<Node>& n,
Sp<Request> sendListen(Sp<Node> n,
const InfoHash& hash,
const Query& query,
const Blob& token,
@@ -377,7 +377,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendAnnounceValue(const Sp<Node>& n,
Sp<Request> sendAnnounceValue(Sp<Node> n,
const InfoHash& hash,
const Sp<Value>& v,
time_point created,
@@ -397,7 +397,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendRefreshValue(const Sp<Node>& n,
Sp<Request> sendRefreshValue(Sp<Node> n,
const InfoHash& hash,
const Value::Id& vid,
const Blob& token,
@@ -416,7 +416,7 @@ public:
*
* @return the request with information concerning its success.
*/
Sp<Request> sendUpdateValues(const Sp<Node>& n,
Sp<Request> sendUpdateValues(Sp<Node> n,
const InfoHash& infohash,
const std::vector<Sp<Value>>& values,
time_point created,
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -42,7 +42,7 @@ namespace dht {
namespace net {
static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
static const constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 64;
static const constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 16;
static const constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(650);
int bindSocket(const SockAddr& addr, SockAddr& bound);
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+11 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -36,9 +36,8 @@ namespace dht {
class Scheduler {
public:
struct Job {
Job(std::function<void()>&& f, time_point t) : do_(std::move(f)), t_(t) {}
Job(std::function<void()>&& f) : do_(std::move(f)) {}
std::function<void()> do_;
const time_point t_;
void cancel() { do_ = {}; }
};
@@ -51,12 +50,17 @@ public:
* @return pointer to the newly scheduled job.
*/
Sp<Scheduler::Job> add(time_point t, std::function<void()>&& job_func) {
auto job = std::make_shared<Job>(std::move(job_func), t);
auto job = std::make_shared<Job>(std::move(job_func));
if (t != time_point::max())
timers.emplace(std::move(t), job);
return job;
}
void add(const Sp<Scheduler::Job>& job, time_point t) {
if (t != time_point::max())
timers.emplace(std::move(t), job);
}
/**
* Reschedules a job.
*
@@ -64,29 +68,16 @@ public:
* @param t The time at which the job shall be rescheduled.
*/
void edit(Sp<Scheduler::Job>& job, time_point t) {
if (not job)
if (not job) {
return;
}
// std::function move doesn't garantee to leave the object empty.
// Force clearing old value.
auto task = std::move(job->do_);
cancel(job);
job->do_ = {};
job = add(t, std::move(task));
}
bool cancel(Sp<Scheduler::Job>& job) {
if (job) {
job->cancel();
for (auto r = timers.equal_range(job->t_); r.first != r.second; ++r.first) {
if (r.first->second == job) {
timers.erase(r.first);
job.reset();
return true;
}
}
}
return false;
}
/**
* Runs the jobs to do up to now.
*
+1 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -173,10 +173,6 @@ public:
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
dht_->setStorageLimit(limit);
}
size_t getStorageLimit() const override {
return dht_->getStorageLimit();
}
std::vector<NodeExport> exportNodes() const override {
return dht_->exportNodes();
}
+1 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -236,15 +236,6 @@ public:
return *reinterpret_cast<sockaddr_in6*>(get());
}
/**
* Releases the ownership of the managed object, if any.
* The caller is responsible for deleting the object with free().
*/
inline sockaddr* release() {
len = 0;
return addr.release();
}
/**
* Return true if address is a loopback IP address.
*/
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -178,8 +178,8 @@ msgpack::object* findMapValue(const msgpack::object& map, const char* key, size_
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, std::string_view key) {
return findMapValue(map, key.data(), key.size());
inline msgpack::object* findMapValue(const msgpack::object& map, const std::string& key) {
return findMapValue(map, key.c_str(), key.size());
}
} // namespace dht
+70 -73
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -27,7 +27,6 @@
#include <msgpack.hpp>
#include <string>
#include <string_view>
#include <sstream>
#include <bitset>
#include <vector>
@@ -43,9 +42,8 @@
#endif
namespace dht {
using namespace std::literals;
static constexpr auto VALUE_KEY_ID("id");
static const std::string VALUE_KEY_ID("id");
static const std::string VALUE_KEY_DAT("dat");
static const std::string VALUE_KEY_PRIO("p");
static const std::string VALUE_KEY_SIGNATURE("sig");
@@ -171,29 +169,29 @@ struct OPENDHT_PUBLIC Value
template<typename Functor>
Filter(Functor f) : std::function<bool(const Value&)>::function(f) {}
inline Filter chain(Filter&& f2) {
Filter chain(Filter&& f2) {
auto f1 = *this;
return chain(std::move(f1), std::move(f2));
}
inline Filter chainOr(Filter&& f2) {
Filter chainOr(Filter&& f2) {
auto f1 = *this;
return chainOr(std::move(f1), std::move(f2));
}
static inline Filter chain(Filter&& f1, Filter&& f2) {
static Filter chain(Filter&& f1, Filter&& f2) {
if (not f1) return std::move(f2);
if (not f2) return std::move(f1);
return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
return f1(v) and f2(v);
};
}
static inline Filter chain(const Filter& f1, const Filter& f2) {
static Filter chain(const Filter& f1, const Filter& f2) {
if (not f1) return f2;
if (not f2) return f1;
return [f1,f2](const Value& v) {
return f1(v) and f2(v);
};
}
static inline Filter chainAll(std::vector<Filter>&& set) {
static Filter chainAll(std::vector<Filter>&& set) {
if (set.empty()) return {};
return [set = std::move(set)](const Value& v) {
for (const auto& f : set)
@@ -202,18 +200,18 @@ struct OPENDHT_PUBLIC Value
return true;
};
}
static inline Filter chain(std::initializer_list<Filter> l) {
static Filter chain(std::initializer_list<Filter> l) {
return chainAll(std::vector<Filter>(l.begin(), l.end()));
}
static inline Filter chainOr(Filter&& f1, Filter&& f2) {
static Filter chainOr(Filter&& f1, Filter&& f2) {
if (not f1 or not f2) return {};
return [f1=std::move(f1),f2=std::move(f2)](const Value& v) {
return f1(v) or f2(v);
};
}
static inline Filter notFilter(Filter&& f) {
static Filter notFilter(Filter&& f) {
if (not f) return [](const Value&) { return false; };
return [f = std::move(f)](const Value& v) { return not f(v); };
return [f](const Value& v) { return not f(v); };
}
std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
if (not (*this))
@@ -228,51 +226,51 @@ struct OPENDHT_PUBLIC Value
/* Sneaky functions disguised in classes */
static inline Filter AllFilter() {
static const Filter AllFilter() {
return {};
}
static inline Filter TypeFilter(const ValueType& t) {
static Filter TypeFilter(const ValueType& t) {
return [tid = t.id](const Value& v) {
return v.type == tid;
};
}
static inline Filter TypeFilter(const ValueType::Id& tid) {
static Filter TypeFilter(const ValueType::Id& tid) {
return [tid](const Value& v) {
return v.type == tid;
};
}
static inline Filter IdFilter(const Id id) {
static Filter IdFilter(const Id id) {
return [id](const Value& v) {
return v.id == id;
};
}
static inline Filter RecipientFilter(const InfoHash& r) {
static Filter RecipientFilter(const InfoHash& r) {
return [r](const Value& v) {
return v.recipient == r;
};
}
static inline Filter OwnerFilter(const crypto::PublicKey& pk) {
static Filter OwnerFilter(const crypto::PublicKey& pk) {
return OwnerFilter(pk.getId());
}
static inline Filter OwnerFilter(const InfoHash& pkh) {
static Filter OwnerFilter(const InfoHash& pkh) {
return [pkh](const Value& v) {
return v.owner and v.owner->getId() == pkh;
};
}
static inline Filter SeqNumFilter(uint16_t seq_no) {
static Filter SeqNumFilter(uint16_t seq_no) {
return [seq_no](const Value& v) {
return v.seq == seq_no;
};
}
static inline Filter UserTypeFilter(std::string ut) {
return [ut = std::move(ut)](const Value& v) {
static Filter UserTypeFilter(const std::string& ut) {
return [ut](const Value& v) {
return v.user_type == ut;
};
}
@@ -343,10 +341,10 @@ struct OPENDHT_PUBLIC Value
return unpack<T>(*this);
}
inline bool isEncrypted() const {
bool isEncrypted() const {
return not cypher.empty();
}
inline bool isSigned() const {
bool isSigned() const {
return owner and not signature.empty();
}
@@ -355,24 +353,37 @@ struct OPENDHT_PUBLIC Value
* Afterward, checkSignature() will return true and owner will
* be set to the corresponding public key.
*/
void sign(const crypto::PrivateKey& key);
void sign(const crypto::PrivateKey& key) {
if (isEncrypted())
throw DhtException("Can't sign encrypted data.");
owner = key.getSharedPublicKey();
signature = key.sign(getToSign());
}
/**
* Check that the value is signed and that the signature matches.
* If true, the owner field will contain the signer public key.
*/
inline bool checkSignature() const {
bool checkSignature() const {
return isSigned() and owner->checkSignature(getToSign(), signature);
}
inline std::shared_ptr<crypto::PublicKey> getOwner() const {
return owner;
std::shared_ptr<crypto::PublicKey> getOwner() const {
return std::static_pointer_cast<crypto::PublicKey>(owner);
}
/**
* Sign the value with from and returns the encrypted version for to.
*/
Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to);
Value encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to) {
if (isEncrypted())
throw DhtException("Data is already encrypted.");
setRecipient(to.getId());
sign(from);
Value nv {id};
nv.setCypher(to.encrypt(getToEncrypt()));
return nv;
}
Value() {}
@@ -427,7 +438,7 @@ struct OPENDHT_PUBLIC Value
/**
* Returns true if value contents are equals (not considering the value ID)
*/
inline bool contentEquals(const Value& o) const {
inline bool contentEquals(const Value& o) {
return isEncrypted() ? cypher == o.cypher :
((owner == o.owner || (owner and o.owner and *owner == *o.owner))
&& type == o.type
@@ -436,25 +447,22 @@ struct OPENDHT_PUBLIC Value
&& signature == o.signature);
}
inline bool operator== (const Value& o) const {
inline bool operator== (const Value& o) {
return id == o.id and contentEquals(o);
}
inline bool operator!= (const Value& o) const {
return !(*this == o);
}
inline void setRecipient(const InfoHash& r) {
void setRecipient(const InfoHash& r) {
recipient = r;
}
inline void setCypher(Blob&& c) {
void setCypher(Blob&& c) {
cypher = std::move(c);
}
/**
* Pack part of the data to be signed (must always be done the same way)
*/
inline Blob getToSign() const {
Blob getToSign() const {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
msgpack_pack_to_sign(pk);
@@ -464,7 +472,7 @@ struct OPENDHT_PUBLIC Value
/**
* Pack part of the data to be encrypted
*/
inline Blob getToEncrypt() const {
Blob getToEncrypt() const {
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
msgpack_pack_to_encrypt(pk);
@@ -474,7 +482,7 @@ struct OPENDHT_PUBLIC Value
/** print value for debugging */
OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
inline std::string toString() const {
std::string toString() const {
std::stringstream ss;
ss << *this;
return ss.str();
@@ -628,16 +636,8 @@ struct OPENDHT_PUBLIC Value
*/
unsigned priority {0};
inline bool isSignatureChecked() const {
return signatureChecked;
}
inline bool isDecrypted() const {
return decrypted;
}
bool checkSignature();
Sp<Value> decrypt(const crypto::PrivateKey& key);
private:
friend class SecureDht;
/* Cache for crypto ops */
bool signatureChecked {false};
bool signatureValid {false};
@@ -659,7 +659,7 @@ struct OPENDHT_PUBLIC FieldValue
FieldValue() {}
FieldValue(Value::Field f, uint64_t int_value) : field(f), intValue(int_value) {}
FieldValue(Value::Field f, InfoHash hash_value) : field(f), hashValue(hash_value) {}
FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(blob_value) {}
bool operator==(const FieldValue& fd) const;
@@ -672,9 +672,9 @@ struct OPENDHT_PUBLIC FieldValue
template <typename Packer>
void msgpack_pack(Packer& p) const {
p.pack_map(2);
p.pack("f"sv); p.pack(static_cast<uint8_t>(field));
p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
p.pack("v"sv);
p.pack(std::string("v"));
switch (field) {
case Value::Field::Id:
case Value::Field::ValueType:
@@ -696,12 +696,12 @@ struct OPENDHT_PUBLIC FieldValue
hashValue = {};
blobValue.clear();
if (auto f = findMapValue(msg, "f"sv))
if (auto f = findMapValue(msg, "f"))
field = (Value::Field)f->as<unsigned>();
else
throw msgpack::type_error();
auto v = findMapValue(msg, "v"sv);
auto v = findMapValue(msg, "v");
if (not v)
throw msgpack::type_error();
else
@@ -741,7 +741,7 @@ private:
struct OPENDHT_PUBLIC Select
{
Select() { }
Select(std::string_view q_str);
Select(const std::string& q_str);
bool isSatisfiedBy(const Select& os) const;
@@ -796,7 +796,7 @@ private:
struct OPENDHT_PUBLIC Where
{
Where() { }
Where(std::string_view q_str);
Where(const std::string& q_str);
bool isSatisfiedBy(const Where& where) const;
@@ -807,11 +807,11 @@ struct OPENDHT_PUBLIC Where
*
* @return the resulting Where instance.
*/
Where&& id(Value::Id id) {
Where& id(Value::Id id) {
FieldValue fv {Value::Field::Id, id};
if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
filters_.emplace_back(std::move(fv));
return std::move(*this);
return *this;
}
/**
@@ -821,11 +821,11 @@ struct OPENDHT_PUBLIC Where
*
* @return the resulting Where instance.
*/
Where&& valueType(ValueType::Id type) {
Where& valueType(ValueType::Id type) {
FieldValue fv {Value::Field::ValueType, type};
if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
filters_.emplace_back(std::move(fv));
return std::move(*this);
return *this;
}
/**
@@ -835,11 +835,11 @@ struct OPENDHT_PUBLIC Where
*
* @return the resulting Where instance.
*/
Where&& owner(InfoHash owner_pk_hash) {
Where& owner(InfoHash owner_pk_hash) {
FieldValue fv {Value::Field::OwnerPk, owner_pk_hash};
if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
filters_.emplace_back(std::move(fv));
return std::move(*this);
return *this;
}
/**
@@ -849,11 +849,11 @@ struct OPENDHT_PUBLIC Where
*
* @return the resulting Where instance.
*/
Where&& seq(uint16_t seq_no) {
Where& seq(uint16_t seq_no) {
FieldValue fv {Value::Field::SeqNum, seq_no};
if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
filters_.emplace_back(std::move(fv));
return std::move(*this);
return *this;
}
/**
@@ -863,11 +863,11 @@ struct OPENDHT_PUBLIC Where
*
* @return the resulting Where instance.
*/
Where&& userType(std::string_view user_type) {
Where& userType(std::string user_type) {
FieldValue fv {Value::Field::UserType, Blob {user_type.begin(), user_type.end()}};
if (std::find(filters_.begin(), filters_.end(), fv) == filters_.end())
filters_.emplace_back(std::move(fv));
return std::move(*this);
return *this;
}
/**
@@ -876,10 +876,7 @@ struct OPENDHT_PUBLIC Where
* @return the resulting Value::Filter.
*/
Value::Filter getFilter() const {
if (filters_.empty())
return {};
if (filters_.size() == 1)
return filters_[0].getLocalFilter();
if (filters_.empty()) return {};
std::vector<Value::Filter> fset;
fset.reserve(filters_.size());
for (const auto& f : filters_) {
@@ -939,11 +936,11 @@ struct OPENDHT_PUBLIC Query
* - $string$: a simple string WITHOUT SPACES.
* - $integer$: a simple integer.
*/
Query(std::string_view q_str) {
Query(std::string q_str) {
auto pos_W = q_str.find("WHERE");
auto pos_w = q_str.find("where");
auto pos = std::min(pos_W != std::string_view::npos ? pos_W : q_str.size(),
pos_w != std::string_view::npos ? pos_w : q_str.size());
auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
pos_w != std::string::npos ? pos_w : q_str.size());
select = q_str.substr(0, pos);
where = q_str.substr(pos, q_str.size()-pos);
}
+5 -59
View File
@@ -10,13 +10,13 @@
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for
# the respective C++ standard version.
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for no added switch, and then for an extended mode.
# preference for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
@@ -35,15 +35,13 @@
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
# Copyright (c) 2020 Jason Merrill <jason@redhat.com>
# Copyright (c) 2021 Jörn Heusipp <osmanx@problemloesungsmaschine.de>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 14
#serial 11
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
@@ -52,7 +50,6 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[$1], [20], [ax_cxx_compile_alternatives="20"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
@@ -65,16 +62,6 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
m4_if([$2], [], [dnl
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
ax_cv_cxx_compile_cxx$1,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[ax_cv_cxx_compile_cxx$1=yes],
[ax_cv_cxx_compile_cxx$1=no])])
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
ac_success=yes
fi])
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for alternative in ${ax_cxx_compile_alternatives}; do
@@ -153,6 +140,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
@@ -160,24 +148,12 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
dnl Test body for checking C++17 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
)
dnl Test body for checking C++20 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
_AX_CXX_COMPILE_STDCXX_testbody_new_in_20
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
@@ -973,33 +949,3 @@ namespace cxx17
#endif // __cplusplus < 201703L
]])
dnl Tests for new features in C++20
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 202002L
#error "This is not a C++20 compiler"
#else
#include <version>
namespace cxx20
{
// As C++20 supports feature test macros in the standard, there is no
// immediate need to actually test for feature availability on the
// Autoconf side.
} // namespace cxx20
#endif // __cplusplus < 202002L
]])
+1 -1
View File
@@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenDHT
Description: C++17 Distributed Hash Table library
Description: C++14 Distributed Hash Table library
Version: @VERSION@
Libs: -L${libdir} -lopendht
Libs.private: @http_parser_lib@ -pthread
+1 -6
View File
@@ -3,15 +3,10 @@ set(CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(setup.py.in setup.py)
configure_file(pyproject.toml pyproject.toml COPYONLY)
add_custom_target(python ALL
COMMAND python3 setup.py build
DEPENDS opendht opendht_cpp.pxd opendht.pyx pyproject.toml)
add_custom_target(dist
COMMAND python3 -m build
DEPENDS opendht opendht_cpp.pxd opendht.pyx pyproject.toml)
DEPENDS opendht opendht_cpp.pxd opendht.pyx)
install(CODE "execute_process(COMMAND python3 setup.py install --root=\$ENV{DESTDIR}/ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
if (OPENDHT_TOOLS)
+1 -2
View File
@@ -2,8 +2,7 @@ if USE_CYTHON
noinst_HEADERS = \
opendht.pyx \
opendht_cpp.pxd \
pyproject.toml
opendht_cpp.pxd
PYTHON_INSTALL_RECORD = $(builddir)/install_record.txt
+2 -2
View File
@@ -1,11 +1,11 @@
# distutils: language = c++
# distutils: extra_compile_args = -std=c++17
# distutils: extra_compile_args = -std=c++14
# distutils: include_dirs = ../../include
# distutils: library_dirs = ../../src
# distutils: libraries = opendht gnutls
# cython: language_level=3
#
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
# Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
-3
View File
@@ -1,3 +0,0 @@
[build-system]
requires = ["setuptools", "wheel", "Cython"]
build-backend = "setuptools.build_meta"
+3 -3
View File
@@ -1,4 +1,4 @@
# Copyright (C) 2014-2022 Savoir-faire Linux Inc.
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
@@ -50,8 +50,8 @@ setup(name="opendht",
["@CURRENT_SOURCE_DIR@/opendht.pyx"],
include_dirs = ['@PROJECT_SOURCE_DIR@/include'],
language="c++",
extra_compile_args=["-std=c++17"],
extra_link_args=["-std=c++17"],
extra_compile_args=["-std=c++14"],
extra_link_args=["-std=c++14"],
libraries=["opendht"],
library_dirs = ['@CURRENT_BINARY_DIR@', '@PROJECT_BINARY_DIR@']
))
+1 -1
View File
@@ -20,7 +20,7 @@ help).
## Python dependencies
- pyroute2 >=0.6.9
- pyroute2 >=0.3.14
- matplotlib
- GeoIP (used by `scanner.py` for drawing map of the world)
- ipaddress
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2022 Savoir-faire Linux Inc.
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
+2 -2
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
@@ -30,7 +30,7 @@ import traceback
import ipaddress
import netifaces
import numpy as np
from pyroute2 import NSPopen
from pyroute2.netns.process.proxy import NSPopen
import msgpack
from opendht import *
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2015-2022 Savoir-Faire Linux Inc.
# Copyright (C) 2015-2019 Savoir-Faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
+89 -235
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -15,253 +15,107 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; If not, see <http://www.gnu.org/licenses/>.
import argparse
import os
import subprocess
from pyroute2 import NDB, NSPopen
import argparse, subprocess
from pyroute2 import IPDB, NetNS
from pyroute2.netns.process.proxy import NSPopen
def int_range(mini, maxi):
def check_ifnum(arg):
try:
ret = int(arg)
except ValueError:
raise argparse.ArgumentTypeError('must be an integer')
if ret > maxi or ret < mini:
raise argparse.ArgumentTypeError(
f'must be {mini} <= int <= {maxi}'
)
return ret
return check_ifnum
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Creates a virtual network topology for testing'
)
parser.add_argument(
'-i', '--ifname', help='interface name', default='ethdht'
)
parser.add_argument(
'-n',
'--ifnum',
type=int_range(1, 245),
help='number of isolated interfaces to create',
default=1,
)
parser.add_argument(
'-r',
'--remove',
help='remove instead of adding network interfaces',
action='store_true',
)
parser.add_argument(
'-l',
'--loss',
help='simulated packet loss (percent)',
type=int,
default=0,
)
parser.add_argument(
'-d', '--delay', help='simulated latency (ms)', type=int, default=0
)
parser.add_argument(
'-4', '--ipv4', help='Enable IPv4', action='store_true'
)
parser.add_argument(
'-6', '--ipv6', help='Enable IPv6', action='store_true'
)
parser.add_argument(
'-b',
'--debug',
help='Turn on debug logging and dump topology databases',
action='store_true',
)
parser.add_argument(
'-v',
'--verbose',
help='Turn on verbose output on netns and interfaces operations',
action='store_true',
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Creates a virtual network topology for testing')
parser.add_argument('-i', '--ifname', help='interface name', default='ethdht')
parser.add_argument('-n', '--ifnum', type=int, help='number of isolated interfaces to create', default=1)
parser.add_argument('-r', '--remove', help='remove instead of adding network interfaces', action="store_true")
parser.add_argument('-l', '--loss', help='simulated packet loss (percent)', type=int, default=0)
parser.add_argument('-d', '--delay', help='simulated latency (ms)', type=int, default=0)
parser.add_argument('-4', '--ipv4', help='Enable IPv4', action="store_true")
parser.add_argument('-6', '--ipv6', help='Enable IPv6', action="store_true")
args = parser.parse_args()
local_addr4 = '10.0.42.'
local_addr6 = '2001:db9::'
bripv4 = f'{local_addr4}1/24'
bripv6 = f'{local_addr6}1/64'
bridge_name = f'br{args.ifname}'
tap_name = f'tap{args.ifname}'
veth_names = []
namespaces = []
ipv4addrs = []
ipv6addrs = []
for ifn in range(args.ifnum):
namespaces.append(f'node{ifn}')
veth_names.append(f'{args.ifname}{ifn}')
ipv4addrs.append(f'{local_addr4}{ifn+8}/24' if args.ipv4 else None)
ipv6addrs.append(f'{local_addr6}{ifn+8}/64' if args.ipv6 else None)
brige_name = 'br'+args.ifname
with NDB(log='debug' if args.debug else None) as ndb:
ip = None
try:
ip = IPDB()
if args.remove:
# cleanup interfaces in the main namespace
for iface in veth_names + [bridge_name] + [tap_name]:
if iface in ndb.interfaces:
ndb.interfaces[iface].remove().commit()
if args.verbose:
print(f'link: del main/{iface}')
# cleanup namespaces
for nsname in namespaces:
try:
ndb.netns[nsname].remove().commit()
if args.verbose:
print(f'netns: del {nsname}')
except KeyError:
pass
else:
# create ports
for veth, nsname, ipv4addr, ipv6addr in zip(
veth_names, namespaces, ipv4addrs, ipv6addrs
):
# create a network namespace and launch NDB for it
#
# another possible solution could be simply to attach
# the namespace to the main NDB instance, but it can
# take a lot of memory in case of many interfaces, thus
# launch and discard netns NDB instances
netns = NDB(
log='debug' if args.debug else None,
sources=[
{
'target': 'localhost',
'netns': nsname,
'kind': 'netns',
}
],
)
if args.verbose:
print(f'netns: add {nsname}')
# create the port and push the peer into the namespace
(
ndb.interfaces.create(
**{
'ifname': veth,
'kind': 'veth',
'state': 'up',
'peer': {'ifname': veth, 'net_ns_fd': nsname},
}
).commit()
)
if args.verbose:
print(f'link: add main/{veth} <-> {nsname}/{veth}')
# bring up namespace's loopback
(
netns.interfaces.wait(ifname='lo', timeout=3)
.set('state', 'up')
.commit()
)
if args.verbose:
print(f'link: set {nsname}/lo')
# bring up the peer
with netns.interfaces.wait(ifname=veth, timeout=3) as i:
i.set('state', 'up')
if args.ipv4:
i.add_ip(ipv4addr)
if args.ipv6:
i.add_ip(ipv6addr)
if args.verbose:
print(f'link: set {nsname}/{veth}, {ipv4addr}, {ipv6addr}')
# disconnect the namespace NDB agent, not removing the NS
if args.debug:
fname = f'{nsname}-ndb.db'
print(f'dump: netns topology database {fname}')
netns.schema.backup(fname)
# cleanup interfaces
for ifn in range(args.ifnum):
iface = args.ifname+str(ifn)
if iface in ip.interfaces:
with ip.interfaces[iface] as i:
i.remove()
if 'tap'+args.ifname in ip.interfaces:
with ip.interfaces['tap'+args.ifname] as i:
i.remove()
if brige_name in ip.interfaces:
with ip.interfaces[brige_name] as i:
i.remove()
for ifn in range(args.ifnum):
netns = NetNS('node'+str(ifn))
netns.close()
# set up the emulation QDisc
nsp = NSPopen(
nsname,
[
'tc',
'qdisc',
'add',
'dev',
veth,
'root',
'netem',
'delay',
f'{args.delay}ms',
f'{int(args.delay)/2}ms',
'loss',
f'{args.loss}%',
'25%',
],
stdout=subprocess.PIPE,
)
netns.remove()
else:
for ifn in range(args.ifnum):
iface = args.ifname+str(ifn)
if not iface in ip.interfaces:
ip.create(kind='veth', ifname=iface, peer=iface+'.1').commit()
ip.create(kind='tuntap', ifname='tap'+args.ifname, mode='tap').commit()
with ip.create(kind='bridge', ifname=brige_name) as i:
for ifn in range(args.ifnum):
iface = args.ifname+str(ifn)
i.add_port(ip.interfaces[iface])
i.add_port(ip.interfaces['tap'+args.ifname])
if args.ipv4:
i.add_ip(local_addr4+'1/24')
if args.ipv6:
i.add_ip(local_addr6+'1/64')
i.up()
with ip.interfaces['tap'+args.ifname] as tap:
tap.up()
for ifn in range(args.ifnum):
iface = args.ifname+str(ifn)
nns = NetNS('node'+str(ifn))
iface1 = iface+'.1'
with ip.interfaces[iface1] as i:
i.net_ns_fd = nns.netns
with ip.interfaces[iface] as i:
i.up()
ip_ns = IPDB(nl=nns)
try:
with ip_ns.interfaces.lo as lo:
lo.up()
with ip_ns.interfaces[iface1] as i:
if args.ipv4:
i.add_ip(local_addr4+str(ifn+8)+'/24')
if args.ipv6:
i.add_ip(local_addr6+str(ifn+8)+'/64')
i.up()
finally:
ip_ns.release()
nsp = NSPopen(nns.netns, ["tc", "qdisc", "add", "dev", iface1, "root", "netem", "delay", str(args.delay)+"ms", str(int(args.delay/2))+"ms", "loss", str(args.loss)+"%", "25%"], stdout=subprocess.PIPE)
#print(nsp.communicate()[0].decode())
nsp.communicate()
nsp.wait()
nsp.release()
if args.verbose:
print(
f'netem: add {nsname}/{veth}, '
f'{args.delay}, {args.loss}'
)
# create the tap
#
# for some reason we should create the tap inteface first,
# and only then bring it up, thus two commit() calls
(
ndb.interfaces.create(
kind='tuntap', ifname=tap_name, mode='tap'
)
.commit()
.set('state', 'up')
.commit()
)
if args.verbose:
print(f'link: add main/{tap_name}')
if args.ipv4:
subprocess.call(["sysctl", "-w", "net.ipv4.conf."+brige_name+".forwarding=1"])
if args.ipv6:
subprocess.call(["sysctl", "-w", "net.ipv6.conf."+brige_name+".forwarding=1"])
# create the bridge and add all the ports
with ndb.interfaces.create(
ifname=bridge_name, kind='bridge', state='up'
) as i:
if args.ipv4:
i.add_ip(bripv4)
if args.ipv6:
i.add_ip(bripv6)
for iface in veth_names + [tap_name]:
i.add_port(iface)
if args.verbose:
print(f'link: add main/{bridge_name}, {bripv4}, {bripv6}')
with open(os.devnull, 'w') as fnull:
if args.ipv4:
subprocess.call(
[
'sysctl',
'-w',
f'net.ipv4.conf.{bridge_name}.forwarding=1',
],
stdout=fnull,
)
if args.verbose:
print(f'sysctl: set {bridge_name} ipv4 forwarding')
if args.ipv6:
subprocess.call(
[
'sysctl',
'-w',
f'net.ipv6.conf.{bridge_name}.forwarding=1',
],
stdout=fnull,
)
if args.verbose:
print(f'sysctl: set {bridge_name} ipv4 forwarding')
if args.debug:
fname = 'main-ndb.db'
print('dump: the main netns topology database')
ndb.schema.backup(fname)
except Exception as e:
print('Error',e)
finally:
if ip:
ip.release()
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2014-2022 Savoir-faire Linux Inc.
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2016-2022 Savoir-faire Linux Inc.
# Copyright (c) 2016-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -8,4 +8,4 @@ edition = "2018"
[dependencies]
libc="0.2.0"
os_socketaddr="0.2.3"
os_socketaddr="0.1.0"
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -47,8 +47,6 @@ impl DhtRunnerConfig {
proxy_server: ptr::null(),
push_node_id: ptr::null(),
push_token: ptr::null(),
push_topic: ptr::null(),
push_platform: ptr::null(),
peer_discovery: false,
peer_publish: false,
server_ca: ptr::null_mut(),
@@ -75,14 +73,6 @@ impl DhtRunnerConfig {
self.push_token = CString::new(push_token).unwrap().as_ptr();
}
pub fn set_push_topic(&mut self, push_topic: &str) {
self.push_topic = CString::new(push_topic).unwrap().as_ptr();
}
pub fn set_push_platform(&mut self, push_platform: &str) {
self.push_platform = CString::new(push_platform).unwrap().as_ptr();
}
pub fn set_identity(&mut self, certificate: Box<DhtCertificate>, privatekey: Box<PrivateKey>) {
self.dht_config.id.privatekey = Box::into_raw(privatekey);
self.dht_config.id.certificate = Box::into_raw(certificate);
+1 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -118,8 +118,6 @@ pub struct DhtRunnerConfig
pub proxy_server: *const c_char,
pub push_node_id: *const c_char,
pub push_token: *const c_char,
pub push_topic: *const c_char,
pub push_platform: *const c_char,
pub peer_discovery: bool,
pub peer_publish: bool,
pub server_ca: *mut DhtCertificate,
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+3
View File
@@ -84,3 +84,6 @@ if ENABLE_INDEXATION
libopendht_la_SOURCES += indexation/pht.cpp
nobase_include_HEADERS += ../include/opendht/indexation/pht.h
endif
clean-local:
rm -rf libargon2.la
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
*
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* 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
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* 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
+80 -59
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
*
@@ -43,6 +43,18 @@ static std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint
static std::uniform_int_distribution<uint8_t> rand_byte;
#endif
// support for GnuTLS < 3.4.
#if GNUTLS_VERSION_NUMBER < 0x030400
#define GNUTLS_PKCS_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES
#define GNUTLS_PKCS_PKCS12_ARCFOUR GNUTLS_PKCS_USE_PKCS12_ARCFOUR
#define GNUTLS_PKCS_PKCS12_RC2_40 GNUTLS_PKCS_USE_PKCS12_RC2_40
#define GNUTLS_PKCS_PBES2_3DES GNUTLS_PKCS_USE_PBES2_3DES
#define GNUTLS_PKCS_PBES2_AES_128 GNUTLS_PKCS_USE_PBES2_AES_128
#define GNUTLS_PKCS_PBES2_AES_192 GNUTLS_PKCS_USE_PBES2_AES_192
#define GNUTLS_PKCS_PBES2_AES_256 GNUTLS_PKCS_USE_PBES2_AES_256
#endif
#define DHT_AES_LEGACY_ENCRYPT 0
#define DHT_AES_LEGACY_DECRYPT 1
namespace dht {
@@ -98,6 +110,10 @@ Blob aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
struct gcm_aes_ctx aes;
gcm_aes_set_key(&aes, key.size(), key.data());
gcm_aes_set_iv(&aes, GCM_IV_SIZE, ret.data());
#if DHT_AES_LEGACY_ENCRYPT
gcm_aes_update(&aes, data_length, data);
#endif
gcm_aes_encrypt(&aes, data_length, ret.data() + GCM_IV_SIZE, data);
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, ret.data() + GCM_IV_SIZE + data_length);
return ret;
@@ -361,13 +377,12 @@ PrivateKey::getPublicKey() const
const std::shared_ptr<PublicKey>&
PrivateKey::getSharedPublicKey() const
{
std::lock_guard<std::mutex> lock(publicKeyMutex_);
if (not publicKey_) {
auto pk = std::make_shared<PublicKey>();
if (auto err = gnutls_pubkey_import_privkey(pk->pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
publicKey_ = pk;
}
if (publicKey_)
return publicKey_;
auto pk = std::make_shared<PublicKey>();
if (auto err = gnutls_pubkey_import_privkey(pk->pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
publicKey_ = pk;
return publicKey_;
}
@@ -527,36 +542,36 @@ PublicKey::encrypt(const uint8_t* data, size_t data_len) const
return ret;
}
const InfoHash&
InfoHash
PublicKey::getId() const
{
if (pk and not idCached_.load()) {
InfoHash id;
size_t sz = id.size();
if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz))
throw CryptoException(std::string("Can't get public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get public key ID: wrong output length.");
cachedId_ = id;
idCached_.store(true);
}
return cachedId_;
if (not pk)
return {};
InfoHash id;
size_t sz = id.size();
if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz))
throw CryptoException(std::string("Can't get public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get public key ID: wrong output length.");
return id;
}
const PkId&
PkId
PublicKey::getLongId() const
{
if (pk and not longIdCached_.load()) {
PkId h;
size_t sz = h.size();
if (auto err = gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz))
throw CryptoException(std::string("Can't get 256 bits public key ID: ") + gnutls_strerror(err));
if (sz != h.size())
throw CryptoException("Can't get 256 bits public key ID: wrong output length.");
cachedLongId_ = h;
longIdCached_.store(true);
}
return cachedLongId_;
if (not pk)
return {};
#if GNUTLS_VERSION_NUMBER < 0x030401
throw CryptoException("Can't get 256 bits public key ID: GnuTLS 3.4.1 or higher required.");
#else
PkId h;
size_t sz = h.size();
if (auto err = gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz))
throw CryptoException(std::string("Can't get 256 bits public key ID: ") + gnutls_strerror(err));
if (sz != h.size())
throw CryptoException("Can't get 256 bits public key ID: wrong output length.");
return h;
#endif
}
gnutls_digest_algorithm_t
@@ -833,36 +848,42 @@ Certificate::getPublicKey() const
return pk_ret;
}
const InfoHash&
InfoHash
Certificate::getId() const
{
if (cert and not idCached_.load()) {
InfoHash id;
size_t sz = id.size();
if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz))
throw CryptoException(std::string("Can't get certificate public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get certificate public key ID: wrong output length.");
cachedId_ = id;
idCached_.store(true);
}
return cachedId_;
if (not cert)
return {};
if (cachedId_)
return cachedId_;
InfoHash id;
size_t sz = id.size();
if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz))
throw CryptoException(std::string("Can't get certificate public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get certificate public key ID: wrong output length.");
cachedId_ = id;
return id;
}
const PkId&
PkId
Certificate::getLongId() const
{
if (cert and not longIdCached_.load()) {
PkId id;
size_t sz = id.size();
if (auto err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz))
throw CryptoException(std::string("Can't get certificate 256 bits public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length.");
cachedLongId_ = id;
longIdCached_.store(true);
}
return cachedLongId_;
if (not cert)
return {};
if (cachedLongId_)
return cachedLongId_;
#if GNUTLS_VERSION_NUMBER < 0x030401
throw CryptoException("Can't get certificate 256 bits public key ID: GnuTLS 3.4.1 or higher required.");
#else
PkId id;
size_t sz = id.size();
if (auto err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz))
throw CryptoException(std::string("Can't get certificate 256 bits public key ID: ") + gnutls_strerror(err));
if (sz != id.size())
throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length.");
cachedLongId_ = id;
return id;
#endif
}
Blob
@@ -1036,8 +1057,6 @@ Certificate::generateOcspRequest(gnutls_x509_crt_t& issuer)
Blob noncebuf(32);
gnutls_datum_t nonce = { noncebuf.data(), (unsigned)noncebuf.size() };
err = gnutls_rnd(GNUTLS_RND_NONCE, nonce.data, nonce.size);
if (err < 0)
throw CryptoException(gnutls_strerror(err));
err = gnutls_ocsp_req_set_nonce(req.get(), 0, &nonce);
if (err < 0)
throw CryptoException(gnutls_strerror(err));
@@ -1454,7 +1473,7 @@ RevocationList::RevocationList(const Blob& b)
} catch (const std::exception& e) {
gnutls_x509_crl_deinit(crl);
crl = nullptr;
throw;
throw e;
}
}
@@ -1750,8 +1769,10 @@ std::ostream& operator<< (std::ostream& o, const TrustList::VerifyResult& h)
o << "* Certificate has expired" << std::endl;
if (h.result & GNUTLS_CERT_UNEXPECTED_OWNER)
o << "* The owner is not the expected one" << std::endl;
#if GNUTLS_VERSION_NUMBER >= 0x030401
if (h.result & GNUTLS_CERT_PURPOSE_MISMATCH)
o << "* Certificate or an intermediate does not match the intended purpose" << std::endl;
#endif
if (h.result & GNUTLS_CERT_MISMATCH)
o << "* Certificate presented isn't the expected one" << std::endl;
} else {
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+83 -78
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -491,7 +491,10 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
auto next_refresh_time = now + getType(a.value->type).expiration;
auto& acked = sn->acked[a.value->id];
scheduler.cancel(acked.refresh);
if (acked.refresh) {
acked.refresh->cancel();
acked.refresh.reset();
}
/* only put the value if the node doesn't already have it */
if (not hasValue or seq_no < a.value->seq) {
if (logger_)
@@ -1194,20 +1197,15 @@ Dht::cancelPut(const InfoHash& id, const Value::Id& vid)
};
canceled |= sr_cancel_put(dht4.searches);
canceled |= sr_cancel_put(dht6.searches);
if (canceled) {
auto st = store.find(id);
if (st != store.end()) {
if (auto value = st->second.remove(id, vid))
storageRemoved(id, st->second, {value}, value->size());
}
}
if (canceled)
storageErase(id, vid);
return canceled;
}
// Storage
void
Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool newValue)
Dht::storageChanged(const InfoHash& id, Storage& st, ValueStorage& v, bool newValue)
{
if (newValue) {
if (not st.local_listeners.empty()) {
@@ -1217,8 +1215,8 @@ Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool ne
cbs.reserve(st.local_listeners.size());
for (const auto& l : st.local_listeners) {
std::vector<Sp<Value>> vals;
if (not l.second.filter or l.second.filter(*v))
vals.push_back(v);
if (not l.second.filter or l.second.filter(*v.data))
vals.push_back(v.data);
if (not vals.empty()) {
if (logger_)
logger_->d(id, "[store %s] sending update local listener with token %lu",
@@ -1239,14 +1237,14 @@ Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool ne
for (const auto& node_listeners : st.listeners) {
for (const auto& l : node_listeners.second) {
auto f = l.second.query.where.getFilter();
if (f and not f(*v))
if (f and not f(*v.data))
continue;
if (logger_)
logger_->w(id, node_listeners.first->id, "[store %s] [node %s] sending update",
id.toString().c_str(),
node_listeners.first->toString().c_str());
std::vector<Sp<Value>> vals {};
vals.push_back(v);
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);
@@ -1282,24 +1280,32 @@ Dht::storageStore(const InfoHash& id, const Sp<Value>& value, time_point created
if (auto vs = store.first) {
total_store_size += store.second.size_diff;
total_values += store.second.values_diff;
scheduler.cancel(vs->expiration_job);
if (vs->expiration_job)
vs->expiration_job->cancel();
if (not permanent) {
vs->expiration_job = scheduler.add(expiration, std::bind(&Dht::expireStorage, this, id));
}
if (total_store_size > max_store_size) {
auto value = vs->data;
auto value_diff = store.second.values_diff;
auto value_edit = store.second.edited_values;
expireStore();
storageChanged(id, st->second, value, value_diff > 0 || value_edit > 0);
} else {
storageChanged(id, st->second, vs->data, store.second.values_diff > 0 || store.second.edited_values > 0);
}
storageChanged(id, st->second, *vs, store.second.values_diff > 0);
}
return std::get<0>(store);
}
bool
Dht::storageErase(const InfoHash& id, Value::Id vid)
{
auto st = store.find(id);
if (st == store.end())
return false;
auto ret = st->second.remove(id, vid);
total_store_size += ret.size_diff;
total_values += ret.values_diff;
return ret.values_diff;
}
void
Dht::storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t socket_id, Query&& query, int version)
{
@@ -1331,8 +1337,36 @@ Dht::expireStore(decltype(store)::iterator i)
const auto& id = i->first;
auto& st = i->second;
auto stats = st.expire(id, scheduler.time());
total_store_size += stats.first;
total_values -= stats.second.size();
if (not stats.second.empty()) {
storageRemoved(id, st, stats.second, -stats.first);
if (logger_)
logger_->d(id, "[store %s] discarded %ld expired values (%ld bytes)",
id.toString().c_str(), stats.second.size(), -stats.first);
if (not st.listeners.empty()) {
if (logger_)
logger_->d(id, "[store %s] %lu remote listeners", id.toString().c_str(), st.listeners.size());
std::vector<Value::Id> ids;
ids.reserve(stats.second.size());
for (const auto& v : stats.second)
ids.emplace_back(v->id);
for (const auto& node_listeners : st.listeners) {
for (const auto& l : node_listeners.second) {
if (logger_)
logger_->w(id, node_listeners.first->id, "[store %s] [node %s] sending expired",
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);
}
}
}
for (const auto& local_listeners : st.local_listeners) {
local_listeners.second.get_cb(stats.second, true);
}
}
}
@@ -1344,41 +1378,6 @@ Dht::expireStorage(InfoHash h)
expireStore(i);
}
void
Dht::storageRemoved(const InfoHash& id, Storage& st, const std::vector<Sp<Value>>& values, size_t totalSize)
{
if (logger_)
logger_->d(id, "[store %s] discarded %ld values (%ld bytes)",
id.toString().c_str(), values.size(), totalSize);
total_store_size -= totalSize;
total_values -= values.size();
if (not st.listeners.empty()) {
if (logger_)
logger_->d(id, "[store %s] %lu remote listeners", id.toString().c_str(), st.listeners.size());
std::vector<Value::Id> ids;
ids.reserve(values.size());
for (const auto& v : values)
ids.emplace_back(v->id);
for (const auto& node_listeners : st.listeners) {
for (const auto& l : node_listeners.second) {
if (logger_)
logger_->w(id, node_listeners.first->id, "[store %s] [node %s] sending expired",
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);
}
}
}
for (const auto& local_listeners : st.local_listeners) {
local_listeners.second.get_cb(values, true);
}
}
void
Dht::expireStore()
{
@@ -1404,23 +1403,23 @@ Dht::expireStore()
break;
}
auto largest = store_quota.begin();
for (auto it = std::next(largest); it != store_quota.end(); ++it) {
for (auto it = ++largest; it != store_quota.end(); ++it) {
if (it->second.size() > largest->second.size())
largest = it;
}
if (largest != store_quota.end()) {
while (true) {
auto exp_value = largest->second.getOldest();
auto storage = store.find(exp_value.first);
if (storage != store.end()) {
if (logger_)
logger_->w("Storage quota full: discarding value from %s at %s %016" PRIx64, largest->first.toString().c_str(), exp_value.first.to_c_str(), exp_value.second);
if (auto value = storage->second.remove(exp_value.first, exp_value.second)) {
storageRemoved(storage->first, storage->second, {value}, value->size());
break;
}
}
if (logger_)
logger_->w("No space left: discarding value of largest consumer %s", largest->first.toString().c_str());
while (true) {
auto exp_value = largest->second.getOldest();
auto storage = store.find(exp_value.first);
if (storage != store.end()) {
auto ret = storage->second.remove(exp_value.first, exp_value.second);
total_store_size += ret.size_diff;
total_values += ret.values_diff;
if (logger_)
logger_->w("Discarded %ld bytes, still %ld used", largest->first.toString().c_str(), total_store_size);
if (ret.values_diff)
break;
}
}
}
@@ -1669,7 +1668,7 @@ Dht::dumpTables() const
std::string
Dht::getStorageLog() const
{
std::ostringstream out;
std::stringstream out;
for (const auto& s : store)
out << printStorageLog(s);
out << std::endl << std::endl;
@@ -1794,8 +1793,7 @@ Dht::Dht(std::unique_ptr<net::DatagramSocket>&& sock, const Config& config, cons
myid(config.node_id ? config.node_id : InfoHash::getRandom(rd)),
store(),
store_quota(),
max_store_keys(config.max_store_keys ? (int)config.max_store_keys : MAX_HASHES),
max_store_size(config.max_store_size ? (int)config.max_store_size : DEFAULT_STORAGE_LIMIT),
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),
network_engine(myid, fromDhtConfig(config), std::move(sock), logger_, rd, scheduler,
std::bind(&Dht::onError, this, _1, _2),
@@ -2062,7 +2060,8 @@ Dht::bootstrap()
logger_->e(myid, "Can't resolve %s:%s: %s", boootstrap.first.c_str(), boootstrap.second.c_str(), e.what());
}
}
scheduler.cancel(bootstrapJob);
if (bootstrapJob)
bootstrapJob->cancel();
bootstrapJob = scheduler.add(scheduler.time() + bootstrap_period, std::bind(&Dht::bootstrap, this));
bootstrap_period = std::min(bootstrap_period * 2, BOOTSTRAP_PERIOD_MAX);
}
@@ -2077,7 +2076,10 @@ Dht::startBootstrap()
void
Dht::stopBootstrap()
{
scheduler.cancel(bootstrapJob);
if (bootstrapJob) {
bootstrapJob->cancel();
bootstrapJob.reset();
}
bootstrap_period = BOOTSTRAP_PERIOD;
}
@@ -2564,9 +2566,12 @@ Dht::storageRefresh(const InfoHash& id, Value::Id vid)
}
}
auto expiration = s->second.refresh(id, now, vid, types);
auto expiration = s->second.refresh(now, vid, types);
if (expiration.first) {
scheduler.cancel(expiration.first->expiration_job);
if (expiration.first->expiration_job) {
expiration.first->expiration_job->cancel();
expiration.first->expiration_job.reset();
}
if (expiration.second != time_point::max()) {
expiration.first->expiration_job = scheduler.add(expiration.second, std::bind(&Dht::expireStorage, this, id));
}
+33 -67
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
@@ -26,7 +26,6 @@
#include <http_parser.h>
#include <deque>
namespace dht {
struct DhtProxyClient::InfoState {
@@ -42,15 +41,15 @@ struct DhtProxyClient::OperationState {
struct DhtProxyClient::Listener
{
Listener(OpValueCache&& c):
cache(std::move(c)) {}
cache(std::move(c))
{}
unsigned callbackId;
OpValueCache cache;
CacheValueCallback cb;
Sp<OperationState> opstate;
std::shared_ptr<http::Request> request;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
std::unique_ptr<asio::steady_timer> refreshSubscriberTimer;
#endif
};
struct PermanentPut {
@@ -117,9 +116,6 @@ DhtProxyClient::DhtProxyClient(
, loopSignal_(signal)
, jsonReader_(Json::CharReaderBuilder{}.newCharReader())
{
localAddrv4_.setFamily(AF_INET);
localAddrv6_.setFamily(AF_INET6);
jsonBuilder_["commentStyle"] = "None";
jsonBuilder_["indentation"] = "";
if (logger_) {
@@ -191,10 +187,7 @@ void
DhtProxyClient::stop()
{
if (not isDestroying_.exchange(true)) {
{
std::lock_guard<std::mutex> l(resolverLock_);
resolver_.reset();
}
resolver_.reset();
cancelAllListeners();
if (infoState_)
infoState_->cancel = true;
@@ -318,30 +311,26 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
return;
}
try {
auto request = buildRequest("/key/" + key.toString());
auto request = buildRequest("/" + key.toString());
auto reqid = request->id();
//request->set_connection_type(restinio::http_connection_header_t::keep_alive);
request->set_method(restinio::http_method_get());
setHeaderFields(*request);
auto opstate = std::make_shared<OperationState>();
Value::Filter filter = w.empty() ? f : f.chain(w.getFilter());
request->add_on_body_callback([
this,
key,
opstate,
filter = Value::Filter::chain(std::move(f), w.getFilter()),
rxBuf = std::make_shared<LineSplit>(),
cb
](const char* at, size_t length){
auto rxBuf = std::make_shared<LineSplit>();
request->add_on_body_callback([this, key, opstate, filter, rxBuf, cb](const char* at, size_t length){
try {
rxBuf->append(at, length);
auto& b = *rxBuf;
b.append(at, length);
// one value per body line
std::vector<Sp<Value>> values;
while (rxBuf->getLine('\n') and !opstate->stop) {
while (b.getLine('\n') and !opstate->stop) {
std::string err;
Json::Value json;
const auto& line = rxBuf->line();
const auto& line = b.line();
if (!jsonReader_->parse(line.data(), line.data() + line.size(), &json, &err)){
opstate->ok.store(false);
return;
@@ -471,9 +460,7 @@ DhtProxyClient::handleRefreshPut(const asio::error_code &ec, InfoHash key, Value
std::shared_ptr<http::Request>
DhtProxyClient::buildRequest(const std::string& target)
{
std::unique_lock<std::mutex> l(resolverLock_);
auto resolver = resolver_;
l.unlock();
if (not resolver)
resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
auto request = target.empty()
@@ -494,7 +481,7 @@ DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb,
logger_->d("[proxy:client] [put] [search %s] executing for %s", key.to_c_str(), val->toString().c_str());
try {
auto request = buildRequest("/key/" + key.toString());
auto request = buildRequest("/" + key.toString());
auto reqid = request->id();
request->set_method(restinio::http_method_post());
setHeaderFields(*request);
@@ -639,7 +626,6 @@ DhtProxyClient::getProxyInfos()
auto resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
queryProxyInfo(infoState, resolver, AF_INET);
queryProxyInfo(infoState, resolver, AF_INET6);
std::lock_guard<std::mutex> l(resolverLock_);
resolver_ = resolver;
}
@@ -671,12 +657,6 @@ DhtProxyClient::queryProxyInfo(const Sp<InfoState>& infoState, const Sp<http::Re
if (!jsonReader_->parse(response.body.data(), response.body.data() + response.body.size(), &proxyInfos, &err)){
onProxyInfos(Json::Value{}, family);
} else if (not infoState->cancel) {
if (auto req = response.request.lock()) {
if (auto conn = req->get_connection()) {
const auto& localAddr = conn->local_address();
proxyInfos["local_ip"] = localAddr.to_string();
}
}
onProxyInfos(proxyInfos, family);
}
}
@@ -708,17 +688,10 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
auto& status = family == AF_INET ? statusIpv4_ : statusIpv6_;
auto ipChanged = false;
auto& pubAddress = family == AF_INET? publicAddressV4_ : publicAddressV6_;
auto& localAddress = family == AF_INET? localAddrv4_ : localAddrv6_;
if (not proxyInfos.isMember("node_id")) {
if (logger_)
logger_->e("[proxy:client] [info] request failed for %s", family == AF_INET ? "ipv4" : "ipv6");
status = NodeStatus::Disconnected;
if (pubAddress) {
pubAddress = {};
ipChanged = true;
}
} else {
if (logger_)
logger_->d("[proxy:client] [info] got proxy reply for %s",
@@ -727,25 +700,19 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
myid = InfoHash(proxyInfos["node_id"].asString());
stats4_ = NodeStats(proxyInfos["ipv4"]);
stats6_ = NodeStats(proxyInfos["ipv6"]);
auto publicIp = parsePublicAddress(proxyInfos["public_ip"]);
ipChanged = pubAddress && pubAddress.toString() != publicIp.toString();
pubAddress = publicIp;
if (proxyInfos.isMember("local_ip")) {
std::string localIp = proxyInfos["local_ip"].asString();
if (localAddress.toString() != localIp) {
localAddress.setAddress(localIp.c_str());
ipChanged = (bool)localAddress;
}
}
if (!ipChanged && stats4_.good_nodes + stats6_.good_nodes)
if (stats4_.good_nodes + stats6_.good_nodes)
status = NodeStatus::Connected;
else if (!ipChanged && stats4_.dubious_nodes + stats6_.dubious_nodes)
else if (stats4_.dubious_nodes + stats6_.dubious_nodes)
status = NodeStatus::Connecting;
else
status = NodeStatus::Disconnected;
auto publicIp = parsePublicAddress(proxyInfos["public_ip"]);
auto publicFamily = publicIp.getFamily();
if (publicFamily == AF_INET)
publicAddressV4_ = publicIp;
else if (publicFamily == AF_INET6)
publicAddressV6_ = publicIp;
} catch (const std::exception& e) {
if (logger_)
logger_->e("[proxy:client] [info] error processing: %s", e.what());
@@ -771,10 +738,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
}
else if (newStatus == NodeStatus::Disconnected) {
auto next = std::chrono::steady_clock::now();
if (!ipChanged)
next += std::chrono::minutes(1);
nextProxyConfirmationTimer_->expires_at(next);
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();
@@ -812,7 +776,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
std::lock_guard<std::mutex> lock(searchLock_);
auto& search = searches_[key];
auto query = std::make_shared<Query>(Select{}, std::move(where));
return search.ops.listen(cb, query, std::move(filter), [this, key](Sp<Query>, ValueCallback cb, SyncCallback) -> size_t {
return search.ops.listen(cb, query, filter, [this, key](Sp<Query>, ValueCallback cb, SyncCallback) -> size_t {
// Find search
auto search = searches_.find(key);
if (search == searches_.end()) {
@@ -850,7 +814,6 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
}
return false;
};
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (not deviceKey_.empty()) {
/*
* Relaunch push listeners even if a timeout is not received
@@ -863,7 +826,6 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
l->second.refreshSubscriberTimer->async_wait(std::bind(&DhtProxyClient::handleResubscribe, this,
std::placeholders::_1, key, token, opstate));
}
#endif
ListenMethod method;
restinio::http_request_header_t header;
if (deviceKey_.empty()){ // listen
@@ -874,7 +836,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
else {
method = ListenMethod::SUBSCRIBE;
header.method(restinio::http_method_subscribe());
header.request_target("/key/" + key.toString());
header.request_target("/" + key.toString());
}
sendListen(header, l->second.cb, opstate, l->second, method);
return token;
@@ -960,7 +922,7 @@ DhtProxyClient::handleExpireListener(const asio::error_code &ec, const InfoHash&
if (not deviceKey_.empty()) {
// UNSUBSCRIBE
auto request = buildRequest("/key/" + key.toString());
auto request = buildRequest("/" + key.toString());
auto reqid = request->id();
try {
request->set_method(restinio::http_method_unsubscribe());
@@ -1267,7 +1229,7 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
ids.emplace_back(std::stoull(substr));
}
{
std::lock_guard<std::mutex> lockCb(lockCallbacks_);
std::lock_guard<std::mutex> lock(lockCallbacks_);
callbacks_.emplace_back([this, key, token, opstate, ids, sendTime]() {
if (opstate->stop)
return;
@@ -1335,8 +1297,12 @@ DhtProxyClient::getPushRequest(Json::Value& body) const
body["key"] = deviceKey_;
body["client_id"] = pushClientId_;
body["session_id"] = pushSessionId_;
body["topic"] = notificationTopic_;
body["platform"] = platform_;
#ifdef __ANDROID__
body["platform"] = "android";
#endif
#ifdef __APPLE__
body["platform"] = "apple";
#endif
}
std::string
+101 -204
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
@@ -38,7 +38,6 @@
using namespace std::placeholders;
using namespace std::chrono_literals;
using namespace std::literals;
namespace dht {
constexpr char RESP_MSG_JSON_INCORRECT[] = "{\"err:\":\"Incorrect JSON\"}";
@@ -100,7 +99,7 @@ class DhtProxyServer::ConnectionListener
{
public:
ConnectionListener() {};
explicit ConnectionListener(std::function<void(restinio::connection_id_t)> onClosed) : onClosed_(std::move(onClosed)) {};
ConnectionListener(std::function<void(restinio::connection_id_t)> onClosed) : onClosed_(std::move(onClosed)) {};
~ConnectionListener() {};
/**
@@ -152,54 +151,48 @@ struct DhtProxyServer::RestRouterTraits : public restinio::default_traits_t
void
DhtProxyServer::PermanentPut::msgpack_unpack(const msgpack::object& o)
{
if (auto cid = findMapValue(o, "cid"sv)) {
if (auto cid = findMapValue(o, "cid")) {
clientId = cid->as<std::string>();
}
if (auto exp = findMapValue(o, "exp"sv)) {
if (auto exp = findMapValue(o, "exp")) {
expiration = from_time_t(exp->as<time_t>());
}
if (auto token = findMapValue(o, "token"sv)) {
if (auto token = findMapValue(o, "token")) {
pushToken = token->as<std::string>();
}
if (auto sid = findMapValue(o, "sid"sv)) {
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"sv)) {
if (auto t = findMapValue(o, "t")) {
type = t->as<PushType>();
}
if (auto val = findMapValue(o, "value"sv)) {
if (auto val = findMapValue(o, "value")) {
value = std::make_shared<dht::Value>(*val);
}
if (auto top = findMapValue(o, "top"sv)) {
topic = top->as<std::string>();
}
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
void
DhtProxyServer::Listener::msgpack_unpack(const msgpack::object& o)
{
if (auto cid = findMapValue(o, "cid"sv)) {
if (auto cid = findMapValue(o, "cid")) {
clientId = cid->as<std::string>();
}
if (auto exp = findMapValue(o, "exp"sv)) {
if (auto exp = findMapValue(o, "exp")) {
expiration = from_time_t(exp->as<time_t>());
}
if (auto sid = findMapValue(o, "sid"sv)) {
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"sv)) {
if (auto t = findMapValue(o, "t")) {
type = t->as<PushType>();
}
if (auto top = findMapValue(o, "top"sv)) {
topic = top->as<std::string>();
}
}
#endif
@@ -211,8 +204,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
dht_(dht), persistPath_(config.persistStatePath), 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),
bundleId_(config.bundleId)
pushServer_(config.pushServer)
{
if (not dht_)
throw std::invalid_argument("A DHT instance must be provided");
@@ -271,8 +263,6 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
// build http server
auto settings = restinio::run_on_this_thread_settings_t<RestRouterTraitsTls>();
addServerSettings(settings);
if (not config.address.empty())
settings.address(config.address);
settings.port(config.port);
settings.tls_context(std::move(tls_context));
httpsServer_ = std::make_unique<restinio::http_server_t<RestRouterTraitsTls>>(
@@ -290,8 +280,6 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
else {
auto settings = restinio::run_on_this_thread_settings_t<RestRouterTraits>();
addServerSettings(settings);
if (not config.address.empty())
settings.address(config.address);
settings.port(config.port);
httpServer_ = std::make_unique<restinio::http_server_t<RestRouterTraits>>(
ioContext_,
@@ -357,7 +345,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
while (pac.next(oh)) {
if (oh.get().type != msgpack::type::MAP)
continue;
if (auto puts = findMapValue(oh.get(), "puts"sv)) {
if (auto puts = findMapValue(oh.get(), "puts")) {
std::lock_guard<std::mutex> lock(lockSearchPuts_);
puts_ = puts->as<decltype(puts_)>();
if (logger_)
@@ -383,7 +371,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
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, pput.second.topic));
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);
@@ -394,16 +382,16 @@ DhtProxyServer::loadState(Is& is, size_t size) {
logger_->d("No persistent puts in state");
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (auto pushListeners = findMapValue(oh.get(), "pushListeners"sv)) {
if (auto listeners = findMapValue(oh.get(), "pushListeners")) {
std::lock_guard<std::mutex> lock(lockListener_);
pushListeners_ = pushListeners->as<decltype(pushListeners_)>();
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, topic=listener.topic]
[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;
@@ -415,7 +403,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
json["s"] = sessionCtx->sessionId;
}
if (expired and values.size() < 2){
std::ostringstream ss;
std::stringstream ss;
for(size_t i = 0; i < values.size(); ++i){
if(i != 0) ss << ",";
ss << values[i]->id;
@@ -425,7 +413,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
auto maxPrio = 1000u;
for (const auto& v : values)
maxPrio = std::min(maxPrio, v->priority);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
return true;
}
);
@@ -440,7 +428,7 @@ DhtProxyServer::loadState(Is& is, size_t size) {
return json;
};
listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pushListener.first, std::move(jsonProvider), listener.type, listener.topic));
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,
@@ -631,8 +619,6 @@ DhtProxyServer::createRestRouter()
// key.listen
router->http_get("/key/:hash/listen", std::bind(&DhtProxyServer::listen, this, _1, _2));
#ifdef OPENDHT_PUSH_NOTIFICATIONS
// node.pingPush
router->http_post("/node/pingPush", std::bind(&DhtProxyServer::pingPush, this, _1, _2));
// key.subscribe
router->add_handler(restinio::http_method_subscribe(),
"/key/:hash", std::bind(&DhtProxyServer::subscribe, this, _1, _2));
@@ -697,9 +683,9 @@ DhtProxyServer::get(restinio::request_handle_t request,
{
requestNum_++;
try {
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
auto response = std::make_shared<ResponseByPartsBuilder>(
initHttpResponse(request->create_response<ResponseByParts>()));
response->flush();
@@ -728,9 +714,9 @@ DhtProxyServer::listen(restinio::request_handle_t request,
requestNum_++;
try {
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
auto response = std::make_shared<ResponseByPartsBuilder>(
initHttpResponse(request->create_response<ResponseByParts>()));
response->flush();
@@ -758,68 +744,15 @@ DhtProxyServer::listen(restinio::request_handle_t request,
#ifdef OPENDHT_PUSH_NOTIFICATIONS
PushType
DhtProxyServer::getTypeFromString(const std::string& type) {
if (type == "android")
return PushType::Android;
else if (type == "ios")
return PushType::iOS;
else if (type == "unifiedpush")
return PushType::UnifiedPush;
return PushType::None;
}
std::string
DhtProxyServer::getDefaultTopic(PushType) {
return bundleId_;
}
RequestStatus
DhtProxyServer::pingPush(restinio::request_handle_t request,
restinio::router::route_params_t /*params*/)
{
requestNum_++;
try {
std::string err;
Json::Value r;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
if (!reader->parse(char_data, char_data + request->body().size(), &r, &err)){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
response.set_body(RESP_MSG_JSON_INCORRECT);
return response.done();
}
const Json::Value& root(r); // parse using const Json so [] never creates element
auto pushToken = root["key"].asString();
if (pushToken.empty()){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
response.set_body(RESP_MSG_NO_TOKEN);
return response.done();
}
auto type = getTypeFromString(root["platform"].asString());
auto topic = root["topic"].asString();
if (topic.empty()) {
topic = getDefaultTopic(type);
}
Json::Value json;
json["to"] = root["client_id"];
json["pong"] = true;
sendPushNotification(pushToken, std::move(json), type, true, topic);
} catch (...) {
return serverError(*request);
}
return restinio::request_handling_status_t::accepted;
}
RequestStatus
DhtProxyServer::subscribe(restinio::request_handle_t request,
restinio::router::route_params_t params)
{
requestNum_++;
try {
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
std::string err;
Json::Value r;
@@ -837,11 +770,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
response.set_body(RESP_MSG_NO_TOKEN);
return response.done();
}
auto type = getTypeFromString(root["platform"].asString());
auto topic = root["topic"].asString();
if (topic.empty()) {
topic = getDefaultTopic(type);
}
auto type = root["platform"].asString() == "android" ? PushType::Android : PushType::iOS;
auto clientId = root["client_id"].asString();
auto sessionId = root["session_id"].asString();
@@ -872,7 +801,6 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
listener.expiration = timeout;
listener.type = type;
listener.topic = topic;
if (listener.expireNotifyTimer)
listener.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
else
@@ -886,7 +814,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
return json;
};
listener.expireNotifyTimer->async_wait(std::bind(&DhtProxyServer::handleNotifyPushListenExpire, this,
std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type, listener.topic));
std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type));
if (!listener.expireTimer)
listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), timeout);
else
@@ -921,7 +849,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
// =========== No existing listener for an infoHash ============
// Add listen on dht
listener.internalToken = dht_->listen(infoHash,
[this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx, topic]
[this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx]
(const std::vector<std::shared_ptr<Value>>& values, bool expired){
// Build message content
Json::Value json;
@@ -933,8 +861,8 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
json["s"] = sessionCtx->sessionId;
}
if (expired and values.size() < 2){
std::ostringstream ss;
for(size_t i = 0; i < values.size(); ++i) {
std::stringstream ss;
for(size_t i = 0; i < values.size(); ++i){
if(i != 0) ss << ",";
ss << values[i]->id;
}
@@ -943,7 +871,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
auto maxPrio = 1000u;
for (const auto& v : values)
maxPrio = std::min(maxPrio, v->priority);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0);
return true;
}
);
@@ -964,9 +892,9 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
{
requestNum_++;
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
if (logger_)
logger_->d("[proxy:server] [unsubscribe %s]", infoHash.toString().c_str());
@@ -999,7 +927,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, const std::string& topic)
std::function<Json::Value()> jsonProvider, PushType type)
{
if (ec == asio::error::operation_aborted)
return;
@@ -1008,8 +936,8 @@ DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const s
logger_->e("[proxy:server] [subscribe] error sending put refresh: %s", ec.message().c_str());
}
if (logger_)
logger_->d("[proxy:server] [subscribe] sending refresh to %s token", pushToken.c_str());
sendPushNotification(pushToken, jsonProvider(), type, false, topic);
logger_->d("[proxy:server] [subscribe] sending put refresh to %s token", pushToken.c_str());
sendPushNotification(pushToken, jsonProvider(), type, false);
}
void
@@ -1051,70 +979,45 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st
}
void
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority, const std::string& topic)
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority)
{
if (pushServer_.empty())
return;
unsigned reqid = 0;
try {
std::shared_ptr<http::Request> request;
http::Url tokenUrl(token);
if (type == PushType::UnifiedPush)
request = std::make_shared<http::Request>(io_context(), tokenUrl.protocol + "://" + tokenUrl.host, logger_);
else
request = std::make_shared<http::Request>(io_context(), pushHostPort_.first, pushHostPort_.second, pushHostPort_.first.find("https://") == 0, logger_);;
auto request = std::make_shared<http::Request>(io_context(), pushHostPort_.first, pushHostPort_.second,
httpsServer_ ? true : false, logger_);
reqid = request->id();
request->set_target(type == PushType::UnifiedPush ? (tokenUrl.target) : "/api/push");
request->set_target("/api/push");
request->set_method(restinio::http_method_post());
request->set_header_field(restinio::http_field_t::host, type == PushType::UnifiedPush ? tokenUrl.host.c_str() : pushServer_.c_str());
request->set_header_field(restinio::http_field_t::host, pushServer_.c_str());
request->set_header_field(restinio::http_field_t::user_agent, "RESTinio client");
request->set_header_field(restinio::http_field_t::accept, "*/*");
request->set_header_field(restinio::http_field_t::content_type, "application/json");
if (type == PushType::UnifiedPush) {
Json::Value notification(Json::objectValue);
notification["message"] = Json::writeString(jsonBuilder_, std::move(json));
notification["topic"] = token;
notification["priority"] = highPriority ? 5 : 1;
request->set_body(Json::writeString(jsonBuilder_, std::move(json)));
} else {
// NOTE: see https://github.com/appleboy/gorush
Json::Value notification(Json::objectValue);
Json::Value tokens(Json::arrayValue);
tokens[0] = token;
notification["tokens"] = std::move(tokens);
notification["platform"] = type == PushType::Android ? 2 : 1;
notification["data"] = std::move(json);
notification["priority"] = highPriority ? "high" : "normal";
if (type == PushType::Android)
notification["time_to_live"] = 3600 * 24; // 24 hours
else {
const auto expiration = std::chrono::system_clock::now() + std::chrono::hours(24);
uint32_t exp = std::chrono::duration_cast<std::chrono::seconds>(expiration.time_since_epoch()).count();
notification["expiration"] = exp;
if (!topic.empty())
notification["topic"] = topic;
if (highPriority) {
Json::Value alert(Json::objectValue);
alert["title"]="hello";
notification["push_type"] = "alert";
notification["alert"] = alert;
notification["mutable_content"] = true;
} else {
notification["push_type"] = "background";
notification["content_available"] = true;
}
}
Json::Value notifications(Json::arrayValue);
notifications[0] = notification;
Json::Value content;
content["notifications"] = std::move(notifications);
request->set_body(Json::writeString(jsonBuilder_, content));
// NOTE: see https://github.com/appleboy/gorush
Json::Value notification(Json::objectValue);
Json::Value tokens(Json::arrayValue);
tokens[0] = token;
notification["tokens"] = std::move(tokens);
notification["platform"] = type == PushType::Android ? 2 : 1;
notification["data"] = std::move(json);
notification["priority"] = highPriority ? "high" : "normal";
if (type == PushType::Android)
notification["time_to_live"] = 3600 * 24; // 24 hours
else {
const auto expiration = std::chrono::system_clock::now() + std::chrono::hours(24);
uint32_t exp = std::chrono::duration_cast<std::chrono::seconds>(expiration.time_since_epoch()).count();
notification["expiration"] = exp;
}
Json::Value notifications(Json::arrayValue);
notifications[0] = notification;
Json::Value content;
content["notifications"] = std::move(notifications);
request->set_body(Json::writeString(jsonBuilder_, content));
request->add_on_state_change_callback([this, reqid]
(http::Request::State state, const http::Response& response){
if (state == http::Request::State::DONE){
@@ -1132,7 +1035,7 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
}
catch (const std::exception &e){
if (logger_)
logger_->e("[proxy:server] [notification] error send push: %s", e.what());
logger_->e("[proxy:server] [notification] error send push: %i", e.what());
if (reqid) {
std::lock_guard<std::mutex> l(requestLock_);
requests_.erase(reqid);
@@ -1177,9 +1080,9 @@ DhtProxyServer::put(restinio::request_handle_t request,
restinio::router::route_params_t params)
{
requestNum_++;
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
if (request->body().empty()){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
@@ -1200,14 +1103,13 @@ DhtProxyServer::put(restinio::request_handle_t request,
logger_->d("[proxy:server] [put %s] %s %s", infoHash.toString().c_str(),
value->toString().c_str(), (permanent ? "permanent" : ""));
if (permanent) {
std::string pushToken, clientId, sessionId, platform, topic;
std::string pushToken, clientId, sessionId, platform;
auto& pVal = root["permanent"];
if (pVal.isObject()){
pushToken = pVal["key"].asString();
clientId = pVal["client_id"].asString();
platform = pVal["platform"].asString();
sessionId = pVal["session_id"].asString();
topic = pVal["topic"].asString();
}
std::lock_guard<std::mutex> lock(lockSearchPuts_);
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
@@ -1230,7 +1132,7 @@ DhtProxyServer::put(restinio::request_handle_t request,
}
}
auto response = initHttpResponse(request->create_response());
response.append_body(Json::writeString(jsonBuilder_, pp.second.value->toJson()) + "\n");
response.append_body(Json::writeString(jsonBuilder_, value->toJson()) + "\n");
return response.done();
}
}
@@ -1242,17 +1144,34 @@ DhtProxyServer::put(restinio::request_handle_t request,
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>(io_context(), timeout);
pput.expireTimer = std::make_unique<asio::steady_timer>(ctx, timeout);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (not pushToken.empty()) {
if (not pushToken.empty()){
bool isAndroid = platform == "android";
pput.pushToken = pushToken;
pput.clientId = clientId;
pput.type = getTypeFromString(platform);
if (topic.empty())
topic = getDefaultTopic(pput.type);
pput.topic = topic;
pput.type = isAndroid ? PushType::Android : PushType::iOS;
pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
// notify push listen expire
auto jsonProvider = [infoHash, clientId, vid, sessionCtx = pput.sessionCtx](){
Json::Value json;
json["timeout"] = infoHash.toString();
json["to"] = clientId;
json["vid"] = std::to_string(vid);
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
return json;
};
if (!pput.expireNotifyTimer)
pput.expireNotifyTimer = std::make_unique<asio::steady_timer>(ctx,
timeout - proxy::OP_MARGIN);
else
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));
}
#endif
} else {
@@ -1265,34 +1184,12 @@ DhtProxyServer::put(restinio::request_handle_t request,
}
}
pput.expireTimer->expires_at(timeout);
if (pput.expireNotifyTimer)
pput.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
}
pput.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPermamentPut, this,
std::placeholders::_1, infoHash, vid));
#ifdef OPENDHT_PUSH_NOTIFICATIONS
// notify put permanent expiration
if (pput.sessionCtx) {
auto jsonProvider = [infoHash, clientId, vid, sessionCtx = pput.sessionCtx](){
Json::Value json;
json["timeout"] = infoHash.toString();
json["to"] = clientId;
json["vid"] = std::to_string(vid);
std::lock_guard<std::mutex> l(sessionCtx->lock);
json["s"] = sessionCtx->sessionId;
return json;
};
if (!pput.expireNotifyTimer)
pput.expireNotifyTimer = std::make_unique<asio::steady_timer>(io_context(),
timeout - proxy::OP_MARGIN);
else
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, pput.topic));
}
#endif
}
dht_->put(infoHash, value, [this, request, value](bool ok){
if (ok){
auto response = initHttpResponse(request->create_response());
@@ -1324,9 +1221,9 @@ DhtProxyServer::putSigned(restinio::request_handle_t request,
restinio::router::route_params_t params) const
{
requestNum_++;
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
if (request->body().empty()){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
@@ -1374,9 +1271,9 @@ DhtProxyServer::putEncrypted(restinio::request_handle_t request,
restinio::router::route_params_t params)
{
requestNum_++;
InfoHash infoHash(params["hash"]);
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
if (request->body().empty()){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
@@ -1446,10 +1343,10 @@ DhtProxyServer::getFiltered(restinio::request_handle_t request,
restinio::router::route_params_t params)
{
requestNum_++;
auto query = params["value"];
InfoHash infoHash(params["hash"]);
auto value = params["value"].to_string();
InfoHash infoHash(params["hash"].to_string());
if (!infoHash)
infoHash = InfoHash::get(params["hash"]);
infoHash = InfoHash::get(params["hash"].to_string());
try {
auto response = std::make_shared<ResponseByPartsBuilder>(
@@ -1464,7 +1361,7 @@ DhtProxyServer::getFiltered(restinio::request_handle_t request,
[response] (bool /*ok*/){
response->done();
},
{}, query);
{}, value);
return restinio::request_handling_status_t::accepted;
} catch (const std::exception& e){
return serverError(*request);
+287 -215
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -38,6 +38,15 @@ namespace dht {
static const std::string PEER_DISCOVERY_DHT_SERVICE = "dht";
struct DhtRunner::Listener {
size_t tokenClassicDht {0};
size_t tokenProxyDht {0};
ValueCallback gcb;
InfoHash hash {};
Value::Filter f;
Where w;
};
struct NodeInsertionPack {
dht::InfoHash nodeId;
in_port_t port;
@@ -46,6 +55,9 @@ struct NodeInsertionPack {
};
DhtRunner::DhtRunner() : dht_()
#ifdef OPENDHT_PROXY_CLIENT
, dht_via_proxy_()
#endif //OPENDHT_PROXY_CLIENT
{
#ifdef _WIN32
WSADATA wsd;
@@ -93,98 +105,91 @@ DhtRunner::run(const Config& config, Context&& context)
auto expected = State::Idle;
if (not running.compare_exchange_strong(expected, State::Running)) {
if (context.logger)
context.logger->w("[runner %p] Node is already running. Call join() first before calling run() again.", this);
context.logger->w("[runner %p] Node is already running. Call join() first before calling run() again.");
return;
}
try {
auto local4 = config.bind4;
auto local6 = config.bind6;
if (not local4 and not local6) {
if (context.logger)
context.logger->w("[runner %p] No address to bind specified in the configuration, using default addresses", this);
local4.setFamily(AF_INET);
local6.setFamily(AF_INET6);
}
auto state_path = config.dht_config.node_config.persist_path;
if (not state_path.empty())
state_path += "_port.txt";
if (not state_path.empty() && (local4.getPort() == 0 || local6.getPort() == 0)) {
std::ifstream inConfig(state_path);
if (inConfig.is_open()) {
in_port_t port;
if (inConfig >> port) {
if (local4.getPort() == 0) {
if (context.logger)
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
local4.setPort(port);
}
auto local4 = config.bind4;
auto local6 = config.bind6;
if (not local4 and not local6) {
if (context.logger)
context.logger->w("[runner %p] No address to bind specified in the configuration, using default addresses");
local4.setFamily(AF_INET);
local6.setFamily(AF_INET6);
}
auto state_path = config.dht_config.node_config.persist_path;
if (not state_path.empty() && (local4.getPort() == 0 || local6.getPort() == 0)) {
state_path += "_port.txt";
std::ifstream inConfig(state_path);
if (inConfig.is_open()) {
in_port_t port;
if (inConfig >> port) {
if (local4.getPort() == 0) {
if (context.logger)
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
local4.setPort(port);
}
if (inConfig >> port) {
if (local6.getPort() == 0) {
if (context.logger)
context.logger->d("[runner %p] Using IPv6 port %hu from saved configuration", this, port);
local6.setPort(port);
}
}
if (inConfig >> port) {
if (local6.getPort() == 0) {
if (context.logger)
context.logger->d("[runner %p] Using IPv6 port %hu from saved configuration", this, port);
local6.setPort(port);
}
}
}
if (context.logger) {
logger_ = context.logger;
logger_->d("[runner %p] state changed to Running", this);
}
#ifdef OPENDHT_PROXY_CLIENT
config_ = config;
identityAnnouncedCb_ = context.identityAnnouncedCb;
#endif
if (config.proxy_server.empty()) {
if (not context.sock) {
context.sock.reset(new net::UdpSocket(local4, local6, context.logger));
}
context.sock->setOnReceive([&] (net::PacketList&& pkts) {
net::PacketList ret;
{
std::lock_guard<std::mutex> lck(sock_mtx);
rcv.splice(rcv.end(), std::move(pkts));
size_t dropped = 0;
while (rcv.size() > net::RX_QUEUE_MAX_SIZE) {
rcv.pop_front();
dropped++;
}
if (dropped and logger_) {
logger_->w("[runner %p] dropped %zu packets: queue is full!", this, dropped);
}
ret = std::move(rcv_free);
}
cv.notify_all();
return ret;
});
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;
}
auto dht = std::make_unique<Dht>(std::move(context.sock), SecureDht::getConfig(config.dht_config), context.logger);
dht_ = std::make_unique<SecureDht>(std::move(dht), config.dht_config, std::move(context.identityAnnouncedCb), context.logger);
} else {
enableProxy(true);
}
} catch(const std::exception& e) {
config_ = {};
identityAnnouncedCb_ = {};
dht_.reset();
running = State::Idle;
throw;
}
if (not context.sock)
context.sock.reset(new net::UdpSocket(local4, local6, context.logger));
if (not state_path.empty()) {
std::ofstream outConfig(state_path);
outConfig << context.sock->getBoundRef(AF_INET).getPort() << std::endl;
outConfig << context.sock->getBoundRef(AF_INET6).getPort() << std::endl;
}
if (context.logger) {
logger_ = context.logger;
logger_->d("[runner %p] state changed to Running", this);
}
context.sock->setOnReceive([&] (net::PacketList&& pkts) {
net::PacketList ret;
{
std::lock_guard<std::mutex> lck(sock_mtx);
auto maxSize = net::RX_QUEUE_MAX_SIZE - pkts.size();
while (rcv.size() > maxSize) {
if (logger_)
logger_->e("Dropping packet: queue is full!");
rcv.pop_front();
}
rcv.splice(rcv.end(), std::move(pkts));
ret = std::move(rcv_free);
}
cv.notify_all();
return ret;
});
#ifdef OPENDHT_PROXY_CLIENT
config_ = config;
identityAnnouncedCb_ = context.identityAnnouncedCb;
#endif
auto dht = std::unique_ptr<DhtInterface>(new Dht(std::move(context.sock), SecureDht::getConfig(config.dht_config), context.logger));
dht_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht), config.dht_config, std::move(context.identityAnnouncedCb), context.logger));
enableProxy(not config.proxy_server.empty());
if (context.logger and dht_via_proxy_) {
dht_via_proxy_->setLogger(context.logger);
}
if (context.statusChangedCallback) {
statusCb = std::move(context.statusChangedCallback);
}
if (context.certificateStore) {
dht_->setLocalCertificateStore(std::move(context.certificateStore));
if (dht_via_proxy_)
dht_via_proxy_->setLocalCertificateStore(std::move(context.certificateStore));
}
if (not config.threaded)
@@ -219,50 +224,46 @@ DhtRunner::run(const Config& config, Context&& context)
}
});
if (config.proxy_server.empty()) {
if (config.peer_discovery or config.peer_publish) {
if (config.peer_discovery or config.peer_publish) {
#ifdef OPENDHT_PEER_DISCOVERY
peerDiscovery_ = context.peerDiscovery ?
std::move(context.peerDiscovery) :
std::make_shared<PeerDiscovery>();
peerDiscovery_ = context.peerDiscovery ?
std::move(context.peerDiscovery) :
std::make_shared<PeerDiscovery>();
#else
std::cerr << "Peer discovery requested but OpenDHT built without peer discovery support." << std::endl;
#endif
}
#ifdef OPENDHT_PEER_DISCOVERY
auto netId = config.dht_config.node_config.network;
if (config.peer_discovery) {
peerDiscovery_->startDiscovery<NodeInsertionPack>(PEER_DISCOVERY_DHT_SERVICE, [this, netId](NodeInsertionPack&& v, SockAddr&& addr){
addr.setPort(v.port);
if (v.nodeId != dht_->getNodeId() && netId == v.net){
bootstrap(v.nodeId, addr);
}
});
}
if (config.peer_publish) {
msgpack::sbuffer sbuf_node;
NodeInsertionPack adc;
adc.net = netId;
adc.nodeId = dht_->getNodeId();
if (auto socket = dht_->getSocket()) {
// IPv4
if (const auto& bound4 = socket->getBoundRef(AF_INET)) {
adc.port = bound4.getPort();
msgpack::pack(sbuf_node, adc);
peerDiscovery_->startPublish(AF_INET, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
}
// IPv6
if (const auto& bound6 = socket->getBoundRef(AF_INET6)) {
adc.port = bound6.getPort();
sbuf_node.clear();
msgpack::pack(sbuf_node, adc);
peerDiscovery_->startPublish(AF_INET6, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
}
}
}
std::cerr << "Peer discovery requested but OpenDHT built without peer discovery support." << std::endl;
#endif
}
#ifdef OPENDHT_PEER_DISCOVERY
auto netId = config.dht_config.node_config.network;
if (config.peer_discovery) {
peerDiscovery_->startDiscovery<NodeInsertionPack>(PEER_DISCOVERY_DHT_SERVICE, [this, netId](NodeInsertionPack&& v, SockAddr&& addr){
addr.setPort(v.port);
if (v.nodeId != dht_->getNodeId() && netId == v.net){
bootstrap(v.nodeId, addr);
}
});
}
if (config.peer_publish) {
msgpack::sbuffer sbuf_node;
NodeInsertionPack adc;
adc.net = netId;
adc.nodeId = dht_->getNodeId();
// IPv4
if (const auto& bound4 = dht_->getSocket()->getBoundRef(AF_INET)) {
adc.port = bound4.getPort();
msgpack::pack(sbuf_node, adc);
peerDiscovery_->startPublish(AF_INET, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
}
// IPv6
if (const auto& bound6 = dht_->getSocket()->getBoundRef(AF_INET6)) {
adc.port = bound6.getPort();
sbuf_node.clear();
msgpack::pack(sbuf_node, adc);
peerDiscovery_->startPublish(AF_INET6, PEER_DISCOVERY_DHT_SERVICE, sbuf_node);
}
}
#endif
}
void
@@ -271,8 +272,7 @@ DhtRunner::shutdown(ShutdownCallback cb, bool stop) {
auto expected = State::Running;
if (not running.compare_exchange_strong(expected, State::Stopping)) {
if (expected == State::Stopping and ongoing_ops) {
if (cb)
shutdownCallbacks_.emplace_back(std::move(cb));
shutdownCallbacks_.emplace_back(std::move(cb));
}
else if (cb) {
lck.unlock();
@@ -286,10 +286,12 @@ DhtRunner::shutdown(ShutdownCallback cb, bool stop) {
shutdownCallbacks_.emplace_back(std::move(cb));
pending_ops.emplace([=](SecureDht&) mutable {
auto onShutdown = [this]{ opEnded(); };
#ifdef OPENDHT_PROXY_CLIENT
if (dht_via_proxy_)
dht_via_proxy_->shutdown(onShutdown, stop);
#endif
if (dht_)
dht_->shutdown(onShutdown, stop);
else
opEnded();
});
cv.notify_all();
}
@@ -392,25 +394,31 @@ void
DhtRunner::dumpTables() const
{
std::lock_guard<std::mutex> lck(dht_mtx);
dht_->dumpTables();
activeDht()->dumpTables();
}
InfoHash
DhtRunner::getId() const
{
return dht_ ? dht_->getId() : InfoHash{};
if (auto dht = activeDht())
return dht->getId();
return {};
}
std::shared_ptr<crypto::PublicKey>
DhtRunner::getPublicKey() const
{
return dht_ ? dht_->getPublicKey() : std::shared_ptr<crypto::PublicKey>{};
if (auto dht = activeDht())
return dht->getPublicKey();
return {};
}
InfoHash
DhtRunner::getNodeId() const
{
return dht_ ? dht_->getNodeId() : InfoHash{};
if (auto dht = activeDht())
return dht->getNodeId();
return {};
}
@@ -452,6 +460,10 @@ DhtRunner::setLogger(const Sp<Logger>& logger) {
logger_ = logger;
if (dht_)
dht_->setLogger(logger);
#ifdef OPENDHT_PROXY_CLIENT
if (dht_via_proxy_)
dht_via_proxy_->setLogger(logger);
#endif
}
void
@@ -465,12 +477,16 @@ DhtRunner::setLogFilter(const InfoHash& f) {
std::lock_guard<std::mutex> lck(dht_mtx);
if (dht_)
dht_->setLogFilter(f);
#ifdef OPENDHT_PROXY_CLIENT
if (dht_via_proxy_)
dht_via_proxy_->setLogFilter(f);
#endif
}
void
DhtRunner::registerType(const ValueType& type) {
std::lock_guard<std::mutex> lck(dht_mtx);
dht_->registerType(type);
activeDht()->registerType(type);
}
void
@@ -483,7 +499,7 @@ unsigned
DhtRunner::getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
const auto stats = dht_->getNodesStats(af);
const auto stats = activeDht()->getNodesStats(af);
if (good_return)
*good_return = stats.good_nodes;
if (dubious_return)
@@ -499,19 +515,19 @@ NodeStats
DhtRunner::getNodesStats(sa_family_t af) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getNodesStats(af);
return activeDht()->getNodesStats(af);
}
NodeInfo
DhtRunner::getNodeInfo() const {
std::lock_guard<std::mutex> lck(dht_mtx);
NodeInfo info {};
if (dht_) {
info.id = dht_->getId();
info.node_id = dht_->getNodeId();
info.ipv4 = dht_->getNodesStats(AF_INET);
info.ipv6 = dht_->getNodesStats(AF_INET6);
if (auto sock = dht_->getSocket()) {
if (auto dht = activeDht()) {
info.id = dht->getId();
info.node_id = dht->getNodeId();
info.ipv4 = dht->getNodesStats(AF_INET);
info.ipv6 = dht->getNodesStats(AF_INET6);
if (auto sock = dht->getSocket()) {
info.bound4 = sock->getBoundRef(AF_INET).getPort();
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
}
@@ -532,7 +548,6 @@ 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);
std::tie(info.storage_size, info.storage_values) = dht.getStoreSize();
if (auto sock = dht.getSocket()) {
info.bound4 = sock->getBoundRef(AF_INET).getPort();
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
@@ -548,49 +563,49 @@ std::vector<unsigned>
DhtRunner::getNodeMessageStats(bool in) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getNodeMessageStats(in);
return activeDht()->getNodeMessageStats(in);
}
std::string
DhtRunner::getStorageLog() const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getStorageLog();
return activeDht()->getStorageLog();
}
std::string
DhtRunner::getStorageLog(const InfoHash& f) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getStorageLog(f);
return activeDht()->getStorageLog(f);
}
std::string
DhtRunner::getRoutingTablesLog(sa_family_t af) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getRoutingTablesLog(af);
return activeDht()->getRoutingTablesLog(af);
}
std::string
DhtRunner::getSearchesLog(sa_family_t af) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getSearchesLog(af);
return activeDht()->getSearchesLog(af);
}
std::string
DhtRunner::getSearchLog(const InfoHash& f, sa_family_t af) const
{
std::lock_guard<std::mutex> lck(dht_mtx);
return dht_->getSearchLog(f, af);
return activeDht()->getSearchLog(f, af);
}
std::vector<SockAddr>
DhtRunner::getPublicAddress(sa_family_t af) const
DhtRunner::getPublicAddress(sa_family_t af)
{
std::lock_guard<std::mutex> lck(dht_mtx);
if (dht_)
return dht_->getPublicAddress(af);
if (auto dht = activeDht())
return dht->getPublicAddress(af);
return {};
}
std::vector<std::string>
DhtRunner::getPublicAddressStr(sa_family_t af) const
DhtRunner::getPublicAddressStr(sa_family_t af)
{
auto addrs = getPublicAddress(af);
std::vector<std::string> ret(addrs.size());
@@ -613,12 +628,15 @@ DhtRunner::getPublicAddress(std::function<void(std::vector<SockAddr>&&)> cb, sa_
void
DhtRunner::registerCertificate(std::shared_ptr<crypto::Certificate> cert) {
std::lock_guard<std::mutex> lck(dht_mtx);
dht_->registerCertificate(cert);
activeDht()->registerCertificate(cert);
}
void
DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method) {
std::lock_guard<std::mutex> lck(dht_mtx);
#ifdef OPENDHT_PROXY_CLIENT
if (dht_via_proxy_)
dht_via_proxy_->setLocalCertificateStore(std::forward<CertificateStoreQuery>(query_method));
#endif
if (dht_)
dht_->setLocalCertificateStore(std::forward<CertificateStoreQuery>(query_method));
}
@@ -626,7 +644,8 @@ DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method) {
time_point
DhtRunner::loop_()
{
if (not dht_)
auto dht = activeDht();
if (not dht)
return {};
decltype(pending_ops) ops {};
@@ -637,7 +656,7 @@ DhtRunner::loop_()
std::move(pending_ops) : std::move(pending_ops_prio);
}
while (not ops.empty()) {
ops.front()(*dht_);
ops.front()(*dht);
ops.pop();
}
@@ -670,13 +689,13 @@ DhtRunner::loop_()
if (now - pkt.received > net::RX_QUEUE_MAX_DELAY)
dropped++;
else
wakeup = dht_->periodic(pkt.data.data(), pkt.data.size(), std::move(pkt.from), now);
wakeup = dht->periodic(pkt.data.data(), pkt.data.size(), std::move(pkt.from), now);
pkt.data.clear();
}
received_treated.splice(received_treated.end(), std::move(received));
} else {
// Or just run the scheduler
wakeup = dht_->periodic(nullptr, 0, nullptr, 0, clock::now());
wakeup = dht->periodic(nullptr, 0, nullptr, 0, clock::now());
}
if (not received_treated.empty()) {
@@ -688,8 +707,8 @@ DhtRunner::loop_()
if (dropped && logger_)
logger_->e("[runner %p] Dropped %zu packets with high delay.", this, dropped);
NodeStatus nstatus4 = dht_->updateStatus(AF_INET);
NodeStatus nstatus6 = dht_->updateStatus(AF_INET6);
NodeStatus nstatus4 = dht->updateStatus(AF_INET);
NodeStatus nstatus6 = dht->updateStatus(AF_INET6);
if (nstatus4 != status4 || nstatus6 != status6) {
status4 = nstatus4;
status6 = nstatus6;
@@ -747,7 +766,27 @@ DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
return ret_token->get_future();
}
pending_ops.emplace([=](SecureDht& dht) mutable {
#ifdef OPENDHT_PROXY_CLIENT
auto tokenbGlobal = listener_token_++;
auto& listener = listeners_[tokenbGlobal];
listener.hash = hash;
listener.f = std::move(f);
listener.w = std::move(w);
listener.gcb = [hash,vcb,tokenbGlobal,this](const std::vector<Sp<Value>>& vals, bool expired) {
if (not vcb(vals, expired)) {
cancelListen(hash, tokenbGlobal);
return false;
}
return true;
};
if (auto token = dht.listen(hash, listener.gcb, listener.f, listener.w)) {
if (use_proxy) listener.tokenProxyDht = token;
else listener.tokenClassicDht = token;
}
ret_token->set_value(tokenbGlobal);
#else
ret_token->set_value(dht.listen(hash, std::move(vcb), std::move(f), std::move(w)));
#endif
});
cv.notify_all();
return ret_token->get_future();
@@ -763,13 +802,21 @@ void
DhtRunner::cancelListen(InfoHash h, size_t token)
{
std::lock_guard<std::mutex> lck(storage_mtx);
if (running != State::Running)
return;
ongoing_ops++;
#ifdef OPENDHT_PROXY_CLIENT
pending_ops.emplace([=](SecureDht&) {
auto it = listeners_.find(token);
if (it == listeners_.end()) return;
if (it->second.tokenClassicDht)
dht_->cancelListen(h, it->second.tokenClassicDht);
if (it->second.tokenProxyDht and dht_via_proxy_)
dht_via_proxy_->cancelListen(h, it->second.tokenProxyDht);
listeners_.erase(it);
});
#else
pending_ops.emplace([=](SecureDht& dht) {
dht.cancelListen(h, token);
opEnded();
});
#endif // OPENDHT_PROXY_CLIENT
cv.notify_all();
}
@@ -777,13 +824,21 @@ void
DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
{
std::lock_guard<std::mutex> lck(storage_mtx);
if (running != State::Running)
return;
ongoing_ops++;
pending_ops.emplace([this, h, ftoken = std::move(ftoken)](SecureDht& dht) {
dht.cancelListen(h, ftoken.get());
opEnded();
#ifdef OPENDHT_PROXY_CLIENT
pending_ops.emplace([=](SecureDht&) {
auto it = listeners_.find(ftoken.get());
if (it == listeners_.end()) return;
if (it->second.tokenClassicDht)
dht_->cancelListen(h, it->second.tokenClassicDht);
if (it->second.tokenProxyDht and dht_via_proxy_)
dht_via_proxy_->cancelListen(h, it->second.tokenProxyDht);
listeners_.erase(it);
});
#else
pending_ops.emplace([=](SecureDht& dht) {
dht.cancelListen(h, ftoken.get());
});
#endif // OPENDHT_PROXY_CLIENT
cv.notify_all();
}
@@ -816,7 +871,7 @@ DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, tim
return;
}
ongoing_ops++;
pending_ops.emplace([=, value = std::move(value), cb = std::move(cb)](SecureDht& dht) mutable {
pending_ops.emplace([=, cb = std::move(cb)](SecureDht& dht) mutable {
dht.put(hash, value, bindOpDoneCallback(std::move(cb)), created, permanent);
});
cv.notify_all();
@@ -966,7 +1021,7 @@ DhtRunner::clearBootstrap()
}
void
DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb)
DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple&& cb)
{
if (running != State::Running) {
cb(false);
@@ -996,7 +1051,7 @@ DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb)
}
void
DhtRunner::bootstrap(SockAddr addr, DoneCallbackSimple cb)
DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb)
{
std::unique_lock<std::mutex> lck(storage_mtx);
if (running != State::Running) {
@@ -1005,7 +1060,7 @@ DhtRunner::bootstrap(SockAddr addr, DoneCallbackSimple cb)
return;
}
ongoing_ops++;
pending_ops_prio.emplace([addr = std::move(addr), cb = bindOpDoneCallback(std::move(cb))](SecureDht& dht) mutable {
pending_ops_prio.emplace([addr, cb = bindOpDoneCallback(std::move(cb))](SecureDht& dht) mutable {
dht.pingNode(std::move(addr), std::move(cb));
});
cv.notify_all();
@@ -1024,12 +1079,12 @@ DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
}
void
DhtRunner::bootstrap(std::vector<NodeExport> nodes)
DhtRunner::bootstrap(const std::vector<NodeExport>& nodes)
{
std::lock_guard<std::mutex> lck(storage_mtx);
if (running != State::Running)
return;
pending_ops_prio.emplace([nodes = std::move(nodes)](SecureDht& dht) {
pending_ops_prio.emplace([=](SecureDht& dht) {
for (auto& node : nodes)
dht.insertNode(node);
});
@@ -1072,9 +1127,23 @@ void
DhtRunner::resetDht()
{
peerDiscovery_.reset();
#ifdef OPENDHT_PROXY_CLIENT
listeners_.clear();
dht_via_proxy_.reset();
#endif // OPENDHT_PROXY_CLIENT
dht_.reset();
}
SecureDht*
DhtRunner::activeDht() const
{
#ifdef OPENDHT_PROXY_CLIENT
return use_proxy? dht_via_proxy_.get() : dht_.get();
#else
return dht_.get();
#endif // OPENDHT_PROXY_CLIENT
}
void
DhtRunner::setProxyServer(const std::string& proxy, const std::string& pushNodeId)
{
@@ -1087,7 +1156,7 @@ DhtRunner::setProxyServer(const std::string& proxy, const std::string& pushNodeI
enableProxy(use_proxy and not config_.proxy_server.empty());
#else
if (not proxy.empty())
throw std::runtime_error("DHT proxy requested but OpenDHT built without proxy support.");
std::cerr << "DHT proxy requested but OpenDHT built without proxy support." << std::endl;
#endif
}
@@ -1095,37 +1164,54 @@ void
DhtRunner::enableProxy(bool proxify)
{
#ifdef OPENDHT_PROXY_CLIENT
if (dht_) {
dht_->shutdown({});
if (dht_via_proxy_) {
dht_via_proxy_->shutdown({});
}
if (proxify) {
// Init the proxy client
auto dht_via_proxy = std::make_unique<DhtProxyClient>(
auto dht_via_proxy = std::unique_ptr<DhtInterface>(
new DhtProxyClient(
config_.server_ca,
config_.client_identity,
[this]{
if (config_.threaded) {
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([=](SecureDht&) mutable {});
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([=](SecureDht&) mutable {});
}
cv.notify_all();
}
},
config_.proxy_server, config_.push_node_id, logger_);
config_.proxy_server, config_.push_node_id, logger_)
);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (not config_.push_token.empty())
dht_via_proxy->setPushNotificationToken(config_.push_token);
if (not config_.push_topic.empty())
dht_via_proxy->setPushNotificationTopic(config_.push_topic);
if (not config_.push_platform.empty())
dht_via_proxy->setPushNotificationPlatform(config_.push_platform);
dht_ = std::make_unique<SecureDht>(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_);
#endif
dht_via_proxy_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_));
// add current listeners
for (auto& l: listeners_)
l.second.tokenProxyDht = dht_via_proxy_->listen(l.second.hash, l.second.gcb, l.second.f, l.second.w);
// and use it
use_proxy = proxify;
} else {
use_proxy = proxify;
std::lock_guard<std::mutex> lck(storage_mtx);
if (not listeners_.empty()) {
pending_ops.emplace([this](SecureDht& /*dht*/) mutable {
if (not dht_)
return;
for (auto& l : listeners_) {
if (not l.second.tokenClassicDht) {
l.second.tokenClassicDht = dht_->listen(l.second.hash, l.second.gcb, l.second.f, l.second.w);
}
}
});
}
}
#else
if (proxify)
throw std::runtime_error("DHT proxy requested but OpenDHT built without proxy support.");
std::cerr << "DHT proxy requested but OpenDHT built without proxy support." << std::endl;
#endif
}
@@ -1133,8 +1219,16 @@ void
DhtRunner::forwardAllMessages(bool forward)
{
std::lock_guard<std::mutex> lck(dht_mtx);
#ifdef OPENDHT_PROXY_SERVER
#ifdef OPENDHT_PROXY_CLIENT
if (dht_via_proxy_)
dht_via_proxy_->forwardAllMessages(forward);
#endif // OPENDHT_PROXY_CLIENT
if (dht_)
dht_->forwardAllMessages(forward);
#else
(void) forward;
#endif // OPENDHT_PROXY_SERVER
}
/**
@@ -1145,46 +1239,24 @@ DhtRunner::setPushNotificationToken(const std::string& token) {
std::lock_guard<std::mutex> lck(dht_mtx);
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
config_.push_token = token;
if (dht_)
dht_->setPushNotificationToken(token);
if (dht_via_proxy_)
dht_via_proxy_->setPushNotificationToken(token);
#else
(void) token;
#endif
}
void
DhtRunner::setPushNotificationTopic(const std::string& topic) {
std::lock_guard<std::mutex> lck(dht_mtx);
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
config_.push_topic = topic;
if (dht_)
dht_->setPushNotificationTopic(topic);
#else
(void) topic;
#endif
}
void
DhtRunner::setPushNotificationPlatform(const std::string& platform) {
std::lock_guard<std::mutex> lck(dht_mtx);
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
config_.push_platform = platform;
if (dht_)
dht_->setPushNotificationPlatform(platform);
#else
(void) platform;
#endif
}
void
DhtRunner::pushNotificationReceived(const std::map<std::string, std::string>& data)
{
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([=](SecureDht&) {
if (dht_)
dht_->pushNotificationReceived(data);
});
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops_prio.emplace([=](SecureDht&) {
if (dht_via_proxy_)
dht_via_proxy_->pushNotificationReceived(data);
});
}
cv.notify_all();
#else
(void) data;
Loaded 100 of 151 files, more files were not shown because too many files have changed in this diff. Show more