mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
183
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4d17c6797 | ||
|
|
44a251de56 | ||
|
|
1c536a4c51 | ||
|
|
502a649f42 | ||
|
|
12a52c78ac | ||
|
|
df2a775927 | ||
|
|
2c86ccbe15 | ||
|
|
b9321a338b | ||
|
|
dc9a211fb0 | ||
|
|
d49b394eae | ||
|
|
f82c68a871 | ||
|
|
3f4235da69 | ||
|
|
e259cb0847 | ||
|
|
08f9b424de | ||
|
|
d33c3515f8 | ||
|
|
0a70b0f80f | ||
|
|
949cbb9fc7 | ||
|
|
37cfbffdca | ||
|
|
efad2ada89 | ||
|
|
d825f4e5ae | ||
|
|
baa2a5d21c | ||
|
|
b3f9683018 | ||
|
|
6d1819acb9 | ||
|
|
d6ee44b640 | ||
|
|
383c53d71f | ||
|
|
833c647524 | ||
|
|
7f6f50411c | ||
|
|
1c7089c055 | ||
|
|
4641780fe6 | ||
|
|
c67df2ead3 | ||
|
|
5f743344e5 | ||
|
|
56442acc84 | ||
|
|
41c9104b8a | ||
|
|
126f0ca966 | ||
|
|
adeca7fa1f | ||
|
|
5527b6553d | ||
|
|
5a6b9db60c | ||
|
|
8f1c075897 | ||
|
|
fca11e621c | ||
|
|
38a7234ae3 | ||
|
|
115a0c683f | ||
|
|
61b7bed0f8 | ||
|
|
dcd8ec7394 | ||
|
|
51880afcce | ||
|
|
db3a4e52b2 | ||
|
|
af8e66b813 | ||
|
|
9646eb9374 | ||
|
|
0df2fbe5de | ||
|
|
c39eceeddf | ||
|
|
11396c315e | ||
|
|
955af06e29 | ||
|
|
e207e59226 | ||
|
|
0302cee8d5 | ||
|
|
8f4031c8cb | ||
|
|
f72d1ffa64 | ||
|
|
90c65fb0be | ||
|
|
c8eb704a92 | ||
|
|
4c5e26922c | ||
|
|
724c3e431c | ||
|
|
a9ddf49ecc | ||
|
|
de3dba7ce4 | ||
|
|
cd9eda6511 | ||
|
|
ed972fd365 | ||
|
|
75834fb08f | ||
|
|
9991c976ff | ||
|
|
92b08bbbc9 | ||
|
|
4f9b50dd60 | ||
|
|
d6d73efa37 | ||
|
|
19a4729bf2 | ||
|
|
405b8739ab | ||
|
|
7ed11a02ae | ||
|
|
3442e0acd9 | ||
|
|
59f86861d2 | ||
|
|
091d01a799 | ||
|
|
1ed45cdcf9 | ||
|
|
c40ba83cb3 | ||
|
|
7dc5aa9dfd | ||
|
|
808eb688b3 | ||
|
|
12b75a612c | ||
|
|
ac79dc5761 | ||
|
|
fe6676f2e6 | ||
|
|
7915b987ec | ||
|
|
29bdc1a46f | ||
|
|
e0d32e80fb | ||
|
|
e753d200c6 | ||
|
|
85fd395c52 | ||
|
|
0f146a354b | ||
|
|
9fcaca9232 | ||
|
|
1bc65bc5f5 | ||
|
|
478d28a326 | ||
|
|
4d544d53a8 | ||
|
|
694c44bbec | ||
|
|
16915ff424 | ||
|
|
a22566599c | ||
|
|
f9b2285593 | ||
|
|
9c2268fa41 | ||
|
|
d4e6fd545a | ||
|
|
dfd0a09361 | ||
|
|
0afa40820a | ||
|
|
f984a6a69a | ||
|
|
b4bbc6ae38 | ||
|
|
bc98d974cb | ||
|
|
785e54838b | ||
|
|
bb7611fc3d | ||
|
|
f675a6bdd3 | ||
|
|
21a71b1559 | ||
|
|
ca5455302d | ||
|
|
f206a8ac9e | ||
|
|
0c4cec66ff | ||
|
|
a03124d889 | ||
|
|
9691746fde | ||
|
|
d7c9311014 | ||
|
|
290e8594b6 | ||
|
|
c59f951e5a | ||
|
|
6919a34f88 | ||
|
|
3480bb1098 | ||
|
|
27b8c870f3 | ||
|
|
be43212a73 | ||
|
|
f0b9bc56a6 | ||
|
|
5654816f5a | ||
|
|
b0fb476d97 | ||
|
|
fada8d067d | ||
|
|
90022ee3e8 | ||
|
|
de68a47a16 | ||
|
|
714af68292 | ||
|
|
e6768edaf0 | ||
|
|
6145e54543 | ||
|
|
ac51c2300e | ||
|
|
f590980c3e | ||
|
|
5dbade3d0b | ||
|
|
2028d4b13e | ||
|
|
a6f7b49b92 | ||
|
|
c2415f38fa | ||
|
|
9cf717ab43 | ||
|
|
d4589bb6f6 | ||
|
|
484878aec3 | ||
|
|
ace3a94e08 | ||
|
|
5d771e119c | ||
|
|
8dcc695947 | ||
|
|
1ae28e07b6 | ||
|
|
2de0737443 | ||
|
|
bc32f848cb | ||
|
|
edee6d63d6 | ||
|
|
af3f6f40bb | ||
|
|
32f72c245d | ||
|
|
043ef8da72 | ||
|
|
6812b733bb | ||
|
|
2ec28dcb83 | ||
|
|
db000a2f88 | ||
|
|
59880df60e | ||
|
|
75f1b07e7a | ||
|
|
f191c4f636 | ||
|
|
1b2bc7b1e3 | ||
|
|
a89e4d626e | ||
|
|
dbbfdaab0f | ||
|
|
536f30ec84 | ||
|
|
b7aec1310c | ||
|
|
31d76b1080 | ||
|
|
2fbafc3591 | ||
|
|
19fe34415a | ||
|
|
2a50f85a30 | ||
|
|
26b71ab993 | ||
|
|
04a78445c6 | ||
|
|
fa19897016 | ||
|
|
3806355509 | ||
|
|
3f6738185b | ||
|
|
e58d09e5da | ||
|
|
71cd9d22c6 | ||
|
|
6c58d4f2e9 | ||
|
|
4070eecea7 | ||
|
|
ffb53ceb1d | ||
|
|
0c00544798 | ||
|
|
471d443e4a | ||
|
|
ba9a445263 | ||
|
|
056bc2850b | ||
|
|
b668d6ad68 | ||
|
|
29fab5560f | ||
|
|
8aef63ce4a | ||
|
|
1ea7a2994e | ||
|
|
208b3fa6fe | ||
|
|
d9ff95da49 | ||
|
|
c8a0b443f3 | ||
|
|
00e595d737 |
No files matched your search
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "C++",
|
||||
"build": {
|
||||
"dockerfile": "../docker/DockerfileDepsLlvm",
|
||||
},
|
||||
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
|
||||
"settings": {},
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools"
|
||||
],
|
||||
"forwardPorts": [4222],
|
||||
}
|
||||
@@ -1,24 +1,20 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
build-ubuntu:
|
||||
name: Ubuntu/GCC build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- 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
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev
|
||||
- name: autogen
|
||||
run: ./autogen.sh
|
||||
- name: argon2
|
||||
run: |
|
||||
cd argon2 && make && sudo make install && cd ..
|
||||
- name: asio
|
||||
run: |
|
||||
wget https://github.com/aberaud/asio/archive/b2b7a1c166390459e1c169c8ae9ef3234b361e3f.tar.gz \
|
||||
@@ -32,3 +28,57 @@ 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/e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz
|
||||
ls -l && tar -xzf e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz
|
||||
cd restinio-e0a261dd8488246a3cb8bbb3ea781ea5139c3c94/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
|
||||
|
||||
- name: make
|
||||
run: cd build && make
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
name: Clang Static Analysis
|
||||
on:
|
||||
push
|
||||
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/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 && 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
|
||||
- name: scan-build
|
||||
run: cd build && scan-build --status-bugs make
|
||||
@@ -19,6 +19,9 @@
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
**/dhtnode
|
||||
**/dhtchat
|
||||
**/dhtscanner
|
||||
|
||||
# Autotools
|
||||
/ac
|
||||
@@ -73,3 +76,5 @@ doc/Doxyfile
|
||||
|
||||
# build dir
|
||||
build
|
||||
build_dev
|
||||
.DS_Store
|
||||
@@ -1,4 +0,0 @@
|
||||
[submodule "argon2"]
|
||||
path = argon2
|
||||
url = https://github.com/P-H-C/phc-winner-argon2
|
||||
ignore = dirty
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
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
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"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,
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"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_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"
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
+50
-71
@@ -1,13 +1,20 @@
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
cmake_minimum_required (VERSION 3.10..3.20)
|
||||
if(POLICY CMP0073)
|
||||
cmake_policy(SET CMP0073 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0074)
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
endif()
|
||||
project (opendht)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(CheckIncludeFileCXX)
|
||||
include(FindPkgConfig)
|
||||
include(cmake/CheckAtomic.cmake)
|
||||
|
||||
set (opendht_VERSION_MAJOR 2)
|
||||
set (opendht_VERSION_MINOR 2.0)
|
||||
set (opendht_VERSION_MINOR 4.7)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -20,15 +27,12 @@ option (OPENDHT_PYTHON "Build Python bindings" OFF)
|
||||
option (OPENDHT_TOOLS "Build DHT tools" ON)
|
||||
option (OPENDHT_SYSTEMD "Install systemd module" OFF)
|
||||
option (OPENDHT_SYSTEMD_UNIT_FILE_LOCATION "Where to install systemd unit file")
|
||||
option (OPENDHT_ARGON2 "Use included argon2 sources" OFF)
|
||||
option (OPENDHT_LTO "Build with LTO" OFF)
|
||||
option (OPENDHT_SANITIZE "Build with address sanitizer and stack protector" OFF)
|
||||
option (OPENDHT_PROXY_SERVER "Enable DHT proxy server, use Restinio and jsoncpp" OFF)
|
||||
option (OPENDHT_PUSH_NOTIFICATIONS "Enable push notifications support" OFF)
|
||||
option (OPENDHT_PROXY_SERVER_IDENTITY "Allow clients to use the node identity" OFF)
|
||||
option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp" OFF)
|
||||
option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
|
||||
option (OPENDHT_PROXY_HTTP_PARSER_FORK "Build DHT proxy with custom http_parser to support old API" OFF)
|
||||
CMAKE_DEPENDENT_OPTION(OPENDHT_HTTP "Build embedded http(s) client" OFF "NOT OPENDHT_PROXY_SERVER;NOT OPENDHT_PROXY_CLIENT" ON)
|
||||
option (OPENDHT_PEER_DISCOVERY "Enable multicast peer discovery" ON)
|
||||
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
|
||||
@@ -40,28 +44,25 @@ find_package(Doxygen)
|
||||
option (OPENDHT_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND})
|
||||
|
||||
# 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)
|
||||
find_package (GnuTLS 3.3 REQUIRED)
|
||||
pkg_search_module (Nettle nettle)
|
||||
find_package (Msgpack 1.2 REQUIRED)
|
||||
pkg_search_module (Nettle REQUIRED nettle)
|
||||
check_include_file_cxx(msgpack.hpp HAVE_MSGPACKCXX)
|
||||
if (NOT HAVE_MSGPACKCXX)
|
||||
find_package (msgpack REQUIRED)
|
||||
endif()
|
||||
if (OPENDHT_TOOLS)
|
||||
find_package (Readline 6 REQUIRED)
|
||||
endif ()
|
||||
if (NOT OPENDHT_ARGON2)
|
||||
pkg_search_module(argon2 libargon2)
|
||||
if (argon2_FOUND)
|
||||
message("-- Found Argon2: " ${argon2_LIBRARY_DIRS} " (found version \"" ${argon2_VERSION} "\")")
|
||||
link_directories (${argon2_LIBRARY_DIRS})
|
||||
else ()
|
||||
message("Argon2 not found, using included version.")
|
||||
set(OPENDHT_ARGON2 ON)
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
pkg_search_module(argon2 REQUIRED libargon2)
|
||||
pkg_search_module(Jsoncpp jsoncpp)
|
||||
if (Jsoncpp_FOUND)
|
||||
add_definitions(-DOPENDHT_JSONCPP)
|
||||
@@ -95,9 +96,6 @@ if (NOT MSVC)
|
||||
message(SEND_ERROR "OpenSSL is required for DHT proxy as specified")
|
||||
endif()
|
||||
endif()
|
||||
if (OPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
add_definitions(-DOPENDHT_PROXY_HTTP_PARSER_FORK)
|
||||
endif()
|
||||
else ()
|
||||
set(OPENDHT_PROXY_OPENSSL OFF)
|
||||
endif ()
|
||||
@@ -128,7 +126,7 @@ if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
endif()
|
||||
|
||||
# Build flags
|
||||
set (CMAKE_CXX_STANDARD 14)
|
||||
set (CMAKE_CXX_STANDARD 17)
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED on)
|
||||
|
||||
if (NOT MSVC)
|
||||
@@ -146,7 +144,7 @@ else ()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DISABLE_MSC_WARNINGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif ()
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_NO_BOOST -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
@@ -157,15 +155,6 @@ 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}")
|
||||
@@ -187,6 +176,7 @@ if (Jsoncpp_INCLUDE_DIRS)
|
||||
endif ()
|
||||
link_directories (${Nettle_LIBRARY_DIRS})
|
||||
link_directories (${Jsoncpp_LIBRARY_DIRS})
|
||||
link_directories (${argon2_LIBRARY_DIRS})
|
||||
include_directories (
|
||||
./
|
||||
include/
|
||||
@@ -233,6 +223,13 @@ list (APPEND opendht_SOURCES
|
||||
src/thread_pool.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
list (APPEND opendht_SOURCES
|
||||
src/compat/apple/apple_utils.h
|
||||
src/compat/apple/apple_utils.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
list (APPEND opendht_HEADERS
|
||||
include/opendht/def.h
|
||||
include/opendht/utils.h
|
||||
@@ -314,23 +311,6 @@ if (OPENDHT_HTTP)
|
||||
)
|
||||
endif ()
|
||||
|
||||
if(OPENDHT_ARGON2)
|
||||
# make sure argon2 submodule is up to date and initialized
|
||||
message("Initializing Argon2 submodule")
|
||||
execute_process(COMMAND git submodule update --init)
|
||||
|
||||
# add local argon2 files to build
|
||||
list (APPEND opendht_SOURCES
|
||||
argon2/src/argon2.c
|
||||
argon2/src/core.c
|
||||
argon2/src/blake2/blake2b.c
|
||||
argon2/src/thread.c
|
||||
argon2/src/ref.c
|
||||
argon2/src/encoding.c
|
||||
)
|
||||
include_directories(argon2/include/)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
list (APPEND opendht_HEADERS src/compat/msvc/unistd.h)
|
||||
endif ()
|
||||
@@ -343,11 +323,7 @@ if (OPENDHT_STATIC)
|
||||
${opendht_HEADERS}
|
||||
)
|
||||
set_target_properties (opendht-static PROPERTIES OUTPUT_NAME "opendht")
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE argon2)
|
||||
else ()
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
target_link_libraries(opendht-static
|
||||
PRIVATE ${argon2_LIBRARIES}
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${Nettle_STATIC_LIBRARIES}
|
||||
@@ -412,40 +388,43 @@ if (OPENDHT_SHARED)
|
||||
set_target_properties (opendht PROPERTIES IMPORT_SUFFIX "_import.lib")
|
||||
set_target_properties (opendht PROPERTIES SOVERSION ${opendht_VERSION_MAJOR} VERSION ${opendht_VERSION})
|
||||
target_compile_definitions(opendht PRIVATE OPENDHT_BUILD)
|
||||
if (OPENDHT_ARGON2)
|
||||
target_include_directories(opendht SYSTEM PRIVATE argon2)
|
||||
else ()
|
||||
target_link_libraries(opendht PRIVATE ${argon2_LIBRARIES})
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
endif ()
|
||||
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
|
||||
if (APPLE)
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY} ${argon2_LIBRARIES}
|
||||
SYSTEM "-framework CoreFoundation" "-framework Security")
|
||||
else ()
|
||||
target_link_libraries(opendht
|
||||
PUBLIC ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES}
|
||||
PRIVATE ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES}
|
||||
${Jsoncpp_LIBRARIES}
|
||||
${FMT_LIBRARY} ${HTTP_PARSER_LIBRARY})
|
||||
${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)
|
||||
target_link_libraries(opendht-c opendht)
|
||||
else ()
|
||||
target_link_libraries(opendht-c opendht-static)
|
||||
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)
|
||||
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
|
||||
)
|
||||
target_link_libraries(opendht-c-static PRIVATE opendht-static)
|
||||
install (TARGETS opendht-c-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht-c-static)
|
||||
endif ()
|
||||
|
||||
# PkgConfig module
|
||||
@@ -454,8 +433,8 @@ 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 ()
|
||||
|
||||
if (OPENDHT_TOOLS)
|
||||
|
||||
@@ -4,6 +4,10 @@ SUBDIRS =
|
||||
|
||||
SUBDIRS += src
|
||||
|
||||
if ENABLE_C
|
||||
SUBDIRS += c
|
||||
endif
|
||||
|
||||
if ENABLE_TOOLS
|
||||
SUBDIRS += tools
|
||||
endif
|
||||
|
||||
@@ -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++14 Distributed Hash Table implementation.
|
||||
A lightweight C++17 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++14** map API
|
||||
* Clean and powerful **C++17** 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++14 -lopendht
|
||||
g++ main.cpp -std=c++17 -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 5.2+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
|
||||
- Build tested with Microsoft Visual Studio 2015, 2017, 2019
|
||||
- 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
|
||||
|
||||
## Contact
|
||||
|
||||
IRC: join us on Freenode at [`#opendht`](https://webchat.freenode.net/?channels=%23opendht).
|
||||
IRC: join us on Libera.chat at [`#opendht`](https://web.libera.chat/#opendht).
|
||||
|
||||
## License
|
||||
Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
|
||||
OpenDHT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
|
||||
-1
Submodule argon2 deleted from 62358ba212.
@@ -1,2 +1 @@
|
||||
git submodule update --init
|
||||
autoreconf --install --verbose -Wall
|
||||
@@ -0,0 +1,15 @@
|
||||
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
|
||||
+126
-40
@@ -1,5 +1,25 @@
|
||||
/*
|
||||
* 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.h>
|
||||
#include <opendht/log.h>
|
||||
|
||||
using ValueSp = std::shared_ptr<dht::Value>;
|
||||
using PrivkeySp = std::shared_ptr<dht::crypto::PrivateKey>;
|
||||
@@ -10,6 +30,13 @@ 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) {
|
||||
@@ -49,7 +76,11 @@ 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(dat, HASH_LEN*2)));
|
||||
*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)));
|
||||
}
|
||||
|
||||
const char* dht_pkid_print(const dht_pkid* h) {
|
||||
@@ -97,10 +128,20 @@ const char* dht_value_get_user_type(const dht_value* data) {
|
||||
return vsp->user_type.c_str();
|
||||
}
|
||||
|
||||
void dht_value_set_user_type(dht_value* data, const char* user_type) {
|
||||
(*reinterpret_cast<ValueSp*>(data))->user_type = user_type;
|
||||
}
|
||||
|
||||
dht_value* dht_value_new(const uint8_t* data, size_t size) {
|
||||
return reinterpret_cast<dht_value*>(new ValueSp(std::make_shared<dht::Value>(data, size)));
|
||||
}
|
||||
|
||||
dht_value* dht_value_new_from_string(const char* str) {
|
||||
ValueSp value = std::make_shared<dht::Value>((const uint8_t*)str, strlen(str));
|
||||
value->user_type = "text/plain";
|
||||
return reinterpret_cast<dht_value*>(new ValueSp(std::move(value)));
|
||||
}
|
||||
|
||||
dht_value* dht_value_ref(const dht_value* v) {
|
||||
return reinterpret_cast<dht_value*>(new ValueSp(*reinterpret_cast<const ValueSp*>(v)));
|
||||
}
|
||||
@@ -144,9 +185,13 @@ 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);
|
||||
auto rdata = new dht::Blob;
|
||||
*rdata = pkey->encrypt((const uint8_t*)data, data_size);
|
||||
return (dht_blob*)rdata;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// dht::crypto::PrivateKey
|
||||
@@ -173,7 +218,18 @@ int dht_privatekey_export(const dht_privatekey* k, char* out, size_t* out_size,
|
||||
|
||||
dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
|
||||
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
|
||||
return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(key->getPublicKey())));
|
||||
return reinterpret_cast<dht_publickey*>(new PubkeySp(key->getSharedPublicKey()));
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -247,7 +303,7 @@ void dht_runner_config_default(dht_runner_config* config) {
|
||||
}
|
||||
|
||||
// dht::DhtRunner
|
||||
dht_runner* dht_runner_new() {
|
||||
dht_runner* dht_runner_new(void) {
|
||||
return reinterpret_cast<dht_runner*>(new dht::DhtRunner);
|
||||
}
|
||||
|
||||
@@ -255,39 +311,61 @@ void dht_runner_delete(dht_runner* runner) {
|
||||
delete reinterpret_cast<dht::DhtRunner*>(runner);
|
||||
}
|
||||
|
||||
void dht_runner_run(dht_runner* r, in_port_t port) {
|
||||
int dht_runner_run(dht_runner* r, in_port_t port) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
runner->run(port, {}, true);
|
||||
try {
|
||||
runner->run(port, {}, true);
|
||||
} catch(...) {
|
||||
return ENOTCONN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
|
||||
int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
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{};
|
||||
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{};
|
||||
|
||||
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.peer_discovery = conf->peer_discovery;
|
||||
config.peer_publish = conf->peer_publish;
|
||||
runner->run(port, config);
|
||||
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.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;
|
||||
}
|
||||
|
||||
void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len) {
|
||||
void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len, dht_done_cb done_cb, void* cb_user_data) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
runner->bootstrap(dht::SockAddr(addr, addr_len));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void dht_runner_bootstrap(dht_runner* r, const char* host, const char* service) {
|
||||
@@ -326,8 +404,11 @@ 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>;
|
||||
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) {
|
||||
*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) {
|
||||
for (const auto& value : values) {
|
||||
if (not cb(reinterpret_cast<const dht_value*>(&value), expired, cb_user_data))
|
||||
return false;
|
||||
@@ -393,6 +474,17 @@ 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;
|
||||
@@ -413,14 +505,8 @@ 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++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
for (size_t i=0; i<addrs.size(); i++)
|
||||
ret[i] = addrs[i].release();
|
||||
ret[addrs.size()] = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
+36
-5
@@ -1,10 +1,28 @@
|
||||
/*
|
||||
* 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 "def.h"
|
||||
#include <opendht/def.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
@@ -18,6 +36,8 @@ 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;
|
||||
@@ -30,6 +50,7 @@ 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);
|
||||
@@ -58,6 +79,7 @@ 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
|
||||
@@ -82,6 +104,7 @@ struct OPENDHT_C_PUBLIC dht_value;
|
||||
typedef struct dht_value dht_value;
|
||||
typedef uint64_t dht_value_id;
|
||||
OPENDHT_C_PUBLIC dht_value* dht_value_new(const uint8_t* data, size_t size);
|
||||
OPENDHT_C_PUBLIC dht_value* dht_value_new_from_string(const char* str);
|
||||
OPENDHT_C_PUBLIC dht_value* dht_value_ref(const dht_value*);
|
||||
OPENDHT_C_PUBLIC void dht_value_unref(dht_value*);
|
||||
OPENDHT_C_PUBLIC dht_data_view dht_value_get_data(const dht_value* data);
|
||||
@@ -89,6 +112,7 @@ OPENDHT_C_PUBLIC dht_value_id dht_value_get_id(const dht_value* data);
|
||||
OPENDHT_C_PUBLIC dht_publickey* dht_value_get_owner(const dht_value* data);
|
||||
OPENDHT_C_PUBLIC dht_infohash dht_value_get_recipient(const dht_value* data);
|
||||
OPENDHT_C_PUBLIC const char* dht_value_get_user_type(const dht_value* data);
|
||||
OPENDHT_C_PUBLIC void dht_value_set_user_type(dht_value* data, const char* user_type);
|
||||
|
||||
// callbacks
|
||||
typedef bool (*dht_get_cb)(const dht_value* value, void* user_data);
|
||||
@@ -122,10 +146,12 @@ struct OPENDHT_PUBLIC dht_runner_config {
|
||||
const char* proxy_server;
|
||||
const char* push_node_id;
|
||||
const char* push_token;
|
||||
const char* push_topic;
|
||||
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);
|
||||
@@ -133,11 +159,13 @@ 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();
|
||||
OPENDHT_C_PUBLIC dht_runner* dht_runner_new(void);
|
||||
OPENDHT_C_PUBLIC void dht_runner_delete(dht_runner* runner);
|
||||
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);
|
||||
/* 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_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);
|
||||
@@ -149,6 +177,9 @@ 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
|
||||
|
||||
+82
-74
@@ -1,95 +1,103 @@
|
||||
# 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.
|
||||
# atomic builtins are required for threading support.
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckLibraryExists)
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/DetermineGCCCompatible.cmake")
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
get_directory_property(compile_options COMPILE_OPTIONS)
|
||||
set(CMAKE_REQUIRED_FLAGS ${compile_options})
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
std::atomic<int64_t> v1;
|
||||
std::atomic<int64_t> v2;
|
||||
int main(int, char**) {
|
||||
return v1 + v2;
|
||||
}" ${varname})
|
||||
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}")
|
||||
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})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_working_cxx_atomics64)
|
||||
|
||||
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)
|
||||
# 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")
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if(HAVE_LIBATOMIC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
list(APPEND CMAKE_CXX_STANDARD_LIBRARIES -latomic)
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
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()
|
||||
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()
|
||||
@@ -0,0 +1,13 @@
|
||||
# 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()
|
||||
@@ -1,64 +0,0 @@
|
||||
# - Try to find msgpack
|
||||
# Once done this will define
|
||||
# MSGPACK_FOUND - System has msgpack
|
||||
# MSGPACK_INCLUDE_DIRS - The msgpack include directories
|
||||
# MSGPACK_LIBRARIES - The libraries needed to use msgpack
|
||||
|
||||
if(NOT MSGPACK_USE_BUNDLED)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PC_MSGPACK QUIET
|
||||
msgpackc>=${Msgpack_FIND_VERSION}
|
||||
msgpack>=${Msgpack_FIND_VERSION})
|
||||
endif()
|
||||
else()
|
||||
set(PC_MSGPACK_INCLUDEDIR)
|
||||
set(PC_MSGPACK_INCLUDE_DIRS)
|
||||
set(PC_MSGPACK_LIBDIR)
|
||||
set(PC_MSGPACK_LIBRARY_DIRS)
|
||||
set(LIMIT_SEARCH NO_DEFAULT_PATH)
|
||||
endif()
|
||||
|
||||
set(MSGPACK_DEFINITIONS ${PC_MSGPACK_CFLAGS_OTHER})
|
||||
|
||||
find_path(MSGPACK_INCLUDE_DIR msgpack/version_master.h
|
||||
HINTS ${PC_MSGPACK_INCLUDEDIR} ${PC_MSGPACK_INCLUDE_DIRS}
|
||||
${LIMIT_SEARCH})
|
||||
|
||||
if(MSGPACK_INCLUDE_DIR)
|
||||
file(READ ${MSGPACK_INCLUDE_DIR}/msgpack/version_master.h msgpack_version_h)
|
||||
string(REGEX REPLACE ".*MSGPACK_VERSION_MAJOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MAJOR "${msgpack_version_h}")
|
||||
string(REGEX REPLACE ".*MSGPACK_VERSION_MINOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MINOR "${msgpack_version_h}")
|
||||
string(REGEX REPLACE ".*MSGPACK_VERSION_REVISION +([0-9]+).*" "\\1" MSGPACK_VERSION_REVISION "${msgpack_version_h}")
|
||||
set(MSGPACK_VERSION_STRING "${MSGPACK_VERSION_MAJOR}.${MSGPACK_VERSION_MINOR}.${MSGPACK_VERSION_REVISION}")
|
||||
else()
|
||||
set(MSGPACK_VERSION_STRING)
|
||||
endif()
|
||||
|
||||
# If we're asked to use static linkage, add libmsgpack{,c}.a as a preferred library name.
|
||||
if(MSGPACK_USE_STATIC)
|
||||
list(APPEND MSGPACK_NAMES
|
||||
"${CMAKE_STATIC_LIBRARY_PREFIX}msgpackc${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
"${CMAKE_STATIC_LIBRARY_PREFIX}msgpack${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
endif()
|
||||
|
||||
list(APPEND MSGPACK_NAMES msgpackc msgpack)
|
||||
|
||||
find_library(MSGPACK_LIBRARY NAMES ${MSGPACK_NAMES}
|
||||
# Check each directory for all names to avoid using headers/libraries from
|
||||
# different places.
|
||||
NAMES_PER_DIR
|
||||
HINTS ${PC_MSGPACK_LIBDIR} ${PC_MSGPACK_LIBRARY_DIRS}
|
||||
${LIMIT_SEARCH})
|
||||
|
||||
mark_as_advanced(MSGPACK_INCLUDE_DIR MSGPACK_LIBRARY)
|
||||
|
||||
set(MSGPACK_LIBRARIES ${MSGPACK_LIBRARY})
|
||||
set(MSGPACK_INCLUDE_DIRS ${MSGPACK_INCLUDE_DIR})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set MSGPACK_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(Msgpack
|
||||
REQUIRED_VARS MSGPACK_LIBRARY MSGPACK_INCLUDE_DIR
|
||||
VERSION_VAR MSGPACK_VERSION_STRING)
|
||||
+37
-47
@@ -1,7 +1,7 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 2)
|
||||
m4_define([opendht_minor_version], 2)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_minor_version], 4)
|
||||
m4_define([opendht_patch_version], 7)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
|
||||
@@ -19,17 +19,33 @@ 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 -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -O0 -pedantic-errors"],
|
||||
[CXXFLAGS="${CXXFLAGS} -O3 -pedantic-errors"])
|
||||
[CXXFLAGS="${CXXFLAGS} -O3 -pedantic-errors -fvisibility=hidden"])
|
||||
|
||||
CPPFLAGS+=" -DOPENDHT_BUILD"
|
||||
AM_CONDITIONAL([OPENDHT_SHARED], [test "x$enable_shared" != xno])
|
||||
AM_COND_IF(OPENDHT_SHARED, [
|
||||
CPPFLAGS+=" -Dopendht_EXPORTS"
|
||||
])
|
||||
|
||||
AC_PROG_CXX
|
||||
AM_PROG_AR
|
||||
LT_INIT()
|
||||
LT_LANG(C++)
|
||||
AC_LANG(C++)
|
||||
AC_PROG_CXX
|
||||
AC_PROG_OBJCXX
|
||||
AX_CXX_COMPILE_STDCXX(17,[noext],[mandatory])
|
||||
|
||||
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], [true], [Define if DHT logs are enabled])
|
||||
], [
|
||||
AC_DEFINE([OPENDHT_LOG], [false], [Define if DHT logs are enabled])
|
||||
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])
|
||||
])
|
||||
|
||||
dnl Check for indexation
|
||||
@@ -76,6 +92,7 @@ case "${host_os}" in
|
||||
SYS=linux
|
||||
;;
|
||||
darwin*)
|
||||
APPLE=1
|
||||
SYS=darwin
|
||||
;;
|
||||
mingw32*)
|
||||
@@ -95,15 +112,11 @@ case "${host_os}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
AM_CONDITIONAL(APPLE, [test "x$SYS" = "xdarwin"])
|
||||
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)
|
||||
@@ -122,8 +135,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)
|
||||
AM_COND_IF([ENABLE_TESTS], [
|
||||
AM_CONDITIONAL(ENABLE_TESTS, test "x$build_tests" == xyes)
|
||||
AS_IF([test "x$build_tests" == xyes], [
|
||||
PKG_CHECK_MODULES([CppUnit], [cppunit >= 1.12])
|
||||
])
|
||||
|
||||
@@ -131,7 +144,11 @@ AM_CONDITIONAL(PROXY_CLIENT_OR_SERVER, test x$proxy_client == xyes || test x$pro
|
||||
|
||||
PKG_CHECK_MODULES([Nettle], [nettle >= 2.4])
|
||||
PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.3])
|
||||
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
|
||||
AC_CHECK_HEADERS([msgpack.hpp], [], [
|
||||
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
|
||||
])
|
||||
PKG_CHECK_MODULES([Argon2], [libargon2])
|
||||
AC_SUBST(argon2_lib, [", libargon2"])
|
||||
|
||||
AC_ARG_WITH([jsoncpp], AS_HELP_STRING([--without-jsoncpp], [Build without JsonCpp support]))
|
||||
AS_IF([test "x$with_jsoncpp" != "xno"],
|
||||
@@ -157,16 +174,8 @@ AS_IF([test "x$have_openssl" = "xyes"], [
|
||||
AC_MSG_NOTICE([Not using OpenSSL])
|
||||
])
|
||||
|
||||
AC_ARG_WITH([http_parser_fork], AS_HELP_STRING([--with-http-parser-fork], [Build with http_parser fork to support old API]))
|
||||
AS_IF([test "x$with_http_parser_fork" = "xyes"],[
|
||||
AC_MSG_NOTICE([Using http_parser fork])
|
||||
AC_DEFINE([OPENDHT_PROXY_HTTP_PARSER_FORK], [], [Define if using http parser fork])
|
||||
], [
|
||||
AC_MSG_NOTICE([Not using http_parser fork])
|
||||
])
|
||||
|
||||
AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
AC_CHECK_HEADERS([asio.hpp], exit,, AC_MSG_ERROR([Missing Asio headers files]))
|
||||
AC_CHECK_HEADERS([asio.hpp],, 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"], [
|
||||
@@ -181,28 +190,8 @@ AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
AS_IF([test "x$http_parser_headers" != "xyes"], AC_MSG_ERROR([Missing HttpParser headers files]))
|
||||
])
|
||||
|
||||
CXXFLAGS="${CXXFLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
|
||||
|
||||
dnl Check for Argon2
|
||||
AC_ARG_WITH([argon2], AS_HELP_STRING([--without-argon2], [Use included Argon2]))
|
||||
AS_IF([test "x$with_argon2" != "xno"],
|
||||
[PKG_CHECK_MODULES([Argon2], [libargon2], [have_argon2=yes], [have_argon2=no])],
|
||||
[have_argon2=no])
|
||||
AS_IF([test "x$have_argon2" = "xyes"], [
|
||||
AC_MSG_NOTICE([Using system Argon2])
|
||||
AC_SUBST(argon2_lib, [", libargon2"])
|
||||
], [
|
||||
AS_IF([test "x$with_argon2" = "xyes"], [
|
||||
AC_MSG_ERROR([Argon2 requested but not found])
|
||||
],[
|
||||
AC_MSG_NOTICE([Using included Argon2])
|
||||
AC_SUBST(Argon2_CFLAGS, "-I\${top_srcdir}/argon2/src -I\${top_srcdir}/argon2/include")
|
||||
AC_SUBST(Argon2_LIBS, "libargon2.la")
|
||||
AC_SUBST(Argon2_LDFLAGS, "-L\${abs_top_srcdir}/argon2/src/.libs")
|
||||
])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([WITH_INCLUDED_ARGON2], [test "x$have_argon2" = "xno"])
|
||||
CXXFLAGS="${CXXFLAGS} -DMSGPACK_NO_BOOST -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
|
||||
OBJCXX="$CXX $CXXFLAGS"
|
||||
|
||||
AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes)
|
||||
AM_CONDITIONAL(ENABLE_TOOLS, test x$build_tools == xyes)
|
||||
@@ -225,6 +214,7 @@ AC_SUBST(PROJECT_BINARY_DIR, "../src/.libs")
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
src/Makefile
|
||||
c/Makefile
|
||||
tools/Makefile
|
||||
python/Makefile
|
||||
python/setup.py
|
||||
|
||||
+13
-3
@@ -1,6 +1,16 @@
|
||||
FROM aberaud/opendht-deps
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
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
|
||||
|
||||
RUN git clone https://github.com/savoirfairelinux/opendht.git \
|
||||
&& cd opendht && mkdir build && cd build \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-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
|
||||
+11
-8
@@ -1,13 +1,16 @@
|
||||
FROM docker.pkg.github.com/savoirfairelinux/opendht/opendht-deps-bionic:2.1.3
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
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 \
|
||||
-DOPENDHT_PROXY_CLIENT=On \
|
||||
-DOPENDHT_PROXY_SERVER=On \
|
||||
-DOPENDHT_C=On \
|
||||
-DOPENDHT_PYTHON=On \
|
||||
-DOPENDHT_LTO=On \
|
||||
&& make -j8 && make install \
|
||||
-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
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
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 \
|
||||
@@ -8,18 +9,18 @@ RUN apt-get update && apt-get install -y \
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential pkg-config cmake git wget \
|
||||
autotools-dev autoconf \
|
||||
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
|
||||
&& 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/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
|
||||
&& 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 . \
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
FROM ubuntu:18.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
|
||||
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
|
||||
|
||||
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 \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev \
|
||||
&& apt-get clean
|
||||
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/*
|
||||
|
||||
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
|
||||
RUN pip3 install --upgrade cmake
|
||||
|
||||
# libasio-dev (1.10) is too old
|
||||
RUN echo "** Building a recent version of asio ***" \
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
FROM ubuntu:20.04
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
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 llvm llvm-dev clang make cmake pkg-config git wget libncurses5-dev libreadline-dev \
|
||||
&& apt-get install -y llvm llvm-dev lldb clang gdb make cmake pkg-config \
|
||||
libtool git wget libncurses5-dev libreadline-dev \
|
||||
nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev cython3 python3-dev \
|
||||
python3-setuptools libcppunit-dev python3-pip \
|
||||
autotools-dev autoconf libssl-dev libargon2-dev \
|
||||
libfmt-dev libhttp-parser-dev libasio-dev \
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y && apt-get clean
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
ENV CC cc
|
||||
ENV CXX c++
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& ls -l && tar -xzf 2224ffedef52cb2b74645d63d871d61dbd0f165e.tar.gz \
|
||||
&& cd restinio-2224ffedef52cb2b74645d63d871d61dbd0f165e/dev \
|
||||
&& 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 . \
|
||||
|
||||
+13
-3
@@ -1,6 +1,16 @@
|
||||
FROM aberaud/opendht-deps-llvm
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
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
|
||||
|
||||
RUN git clone https://github.com/savoirfairelinux/opendht.git \
|
||||
&& cd opendht && mkdir build && cd build \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DOPENDHT_PYTHON=On -DOPENDHT_LTO=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On && make -j8 && make install \
|
||||
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-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
|
||||
@@ -1,9 +0,0 @@
|
||||
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
|
||||
@@ -1,7 +0,0 @@
|
||||
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
|
||||
@@ -1,4 +0,0 @@
|
||||
FROM aberaud/opendht-deps
|
||||
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
|
||||
COPY . /root/opendht
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +82,8 @@ 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};
|
||||
|
||||
@@ -132,6 +134,9 @@ 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -32,6 +32,8 @@ extern "C" {
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <iso646.h>
|
||||
@@ -100,12 +102,12 @@ struct OPENDHT_PUBLIC PublicKey
|
||||
/**
|
||||
* Get public key fingerprint
|
||||
*/
|
||||
InfoHash getId() const;
|
||||
const InfoHash& getId() const;
|
||||
|
||||
/**
|
||||
* Get public key long fingerprint
|
||||
*/
|
||||
PkId getLongId() const;
|
||||
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 {
|
||||
@@ -138,6 +140,11 @@ 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;
|
||||
@@ -164,7 +171,9 @@ struct OPENDHT_PUBLIC PrivateKey
|
||||
~PrivateKey();
|
||||
explicit operator bool() const { return key; }
|
||||
|
||||
PublicKey getPublicKey() const;
|
||||
const PublicKey& getPublicKey() const;
|
||||
const std::shared_ptr<PublicKey>& getSharedPublicKey() const;
|
||||
|
||||
int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const;
|
||||
Blob serialize(const std::string& password = {}) const;
|
||||
|
||||
@@ -199,7 +208,8 @@ private:
|
||||
PrivateKey& operator=(const PrivateKey&) = delete;
|
||||
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
|
||||
|
||||
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
|
||||
mutable std::mutex publicKeyMutex_ {};
|
||||
mutable std::shared_ptr<PublicKey> publicKey_ {};
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC RevocationList
|
||||
@@ -484,9 +494,9 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
PublicKey getPublicKey() const;
|
||||
|
||||
/** Same as getPublicKey().getId() */
|
||||
InfoHash getId() const;
|
||||
const InfoHash& getId() const;
|
||||
/** Same as getPublicKey().getLongId() */
|
||||
PkId getLongId() const;
|
||||
const PkId& getLongId() const;
|
||||
|
||||
Blob getSerialNumber() const;
|
||||
|
||||
@@ -539,8 +549,8 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
void addRevocationList(RevocationList&&);
|
||||
void addRevocationList(std::shared_ptr<RevocationList>);
|
||||
|
||||
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false);
|
||||
static Certificate generate(const CertificateRequest& request, const Identity& ca);
|
||||
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false, int64_t validity = 0);
|
||||
static Certificate generate(const CertificateRequest& request, const Identity& ca, int64_t validity = 0);
|
||||
|
||||
gnutls_x509_crt_t getCopy() const {
|
||||
if (not cert)
|
||||
@@ -590,12 +600,22 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
*/
|
||||
std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
|
||||
|
||||
/**
|
||||
* Change certificate's expiration
|
||||
*/
|
||||
void setValidity(const Identity& ca, int64_t validity);
|
||||
void setValidity(const PrivateKey& key, int64_t validity);
|
||||
|
||||
gnutls_x509_crt_t cert {nullptr};
|
||||
std::shared_ptr<Certificate> issuer {};
|
||||
std::shared_ptr<OcspResponse> ocspResponse;
|
||||
private:
|
||||
Certificate(const Certificate&) = delete;
|
||||
Certificate& operator=(const Certificate&) = delete;
|
||||
mutable InfoHash cachedId_ {};
|
||||
mutable PkId cachedLongId_ {};
|
||||
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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
@@ -66,8 +66,10 @@ private:
|
||||
|
||||
public:
|
||||
virtual void unpackValue(const Value& v) override {
|
||||
if (v.owner)
|
||||
if (v.owner) {
|
||||
owner = v.owner;
|
||||
from = v.owner->getId();
|
||||
}
|
||||
BaseClass::unpackValue(v);
|
||||
}
|
||||
|
||||
@@ -75,6 +77,7 @@ public:
|
||||
return [](const Value& v){ return v.isSigned(); };
|
||||
}
|
||||
|
||||
Sp<crypto::PublicKey> owner;
|
||||
dht::InfoHash from;
|
||||
};
|
||||
|
||||
|
||||
+16
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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>
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
|
||||
void addBootstrap(const std::string& host, const std::string& service) override {
|
||||
bootstrap_nodes.emplace_back(host, service);
|
||||
onDisconnected();
|
||||
startBootstrap();
|
||||
}
|
||||
|
||||
void clearBootstrap() override {
|
||||
@@ -302,6 +302,9 @@ 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
|
||||
@@ -340,7 +343,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};
|
||||
static constexpr unsigned MAX_HASHES {1024 * 1024 * 1024};
|
||||
|
||||
/* The maximum number of searches we keep data about. */
|
||||
static constexpr unsigned MAX_SEARCHES {1024 * 1024};
|
||||
@@ -356,6 +359,8 @@ private:
|
||||
|
||||
static constexpr duration REANNOUNCE_MARGIN {std::chrono::seconds(10)};
|
||||
|
||||
static constexpr std::chrono::seconds BOOTSTRAP_PERIOD {10};
|
||||
|
||||
static constexpr size_t TOKEN_SIZE {32};
|
||||
|
||||
// internal structures
|
||||
@@ -393,7 +398,7 @@ private:
|
||||
Kad dht6 {};
|
||||
|
||||
std::vector<std::pair<std::string,std::string>> bootstrap_nodes {};
|
||||
std::chrono::steady_clock::duration bootstrap_period {std::chrono::seconds(10)};
|
||||
std::chrono::steady_clock::duration bootstrap_period {BOOTSTRAP_PERIOD};
|
||||
Sp<Scheduler::Job> bootstrapJob {};
|
||||
|
||||
std::map<InfoHash, Storage> store;
|
||||
@@ -445,13 +450,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 storageChanged(const InfoHash& id, Storage& st, ValueStorage&, bool newValue);
|
||||
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);
|
||||
std::string printStorageLog(const decltype(store)::value_type&) const;
|
||||
|
||||
/**
|
||||
@@ -480,6 +485,9 @@ private:
|
||||
void sendCachedPing(Bucket& b);
|
||||
bool bucketMaintenance(RoutingTable&);
|
||||
void dumpBucket(const Bucket& b, std::ostream& out) const;
|
||||
void bootstrap();
|
||||
void startBootstrap();
|
||||
void stopBootstrap();
|
||||
|
||||
// Nodes
|
||||
void onNewNode(const Sp<Node>& node, int confirm);
|
||||
@@ -487,7 +495,6 @@ private:
|
||||
bool trySearchInsert(const Sp<Node>& node);
|
||||
|
||||
// Searches
|
||||
|
||||
inline SearchMap& searches(sa_family_t af) { return dht(af).searches; }
|
||||
inline const SearchMap& searches(sa_family_t af) const { return dht(af).searches; }
|
||||
|
||||
@@ -569,7 +576,8 @@ private:
|
||||
*
|
||||
* @param sr The search to execute its operations.
|
||||
*/
|
||||
void searchStep(Sp<Search>);
|
||||
void searchStep(std::weak_ptr<Search> ws);
|
||||
|
||||
void searchSynchedNodeListen(const Sp<Search>&, SearchNode&);
|
||||
|
||||
void dumpSearch(const Search& sr, std::ostream& out) const;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +221,7 @@ 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
|
||||
@@ -264,6 +265,8 @@ public:
|
||||
|
||||
virtual void setPushNotificationToken(const std::string&) {};
|
||||
|
||||
virtual void setPushNotificationTopic(const std::string&) {};
|
||||
|
||||
/**
|
||||
* Call linked callback with a push notification
|
||||
* @param notification to process
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +67,14 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void setPushNotificationTopic(const std::string& topic) override {
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
notificationTopic_ = topic;
|
||||
#else
|
||||
(void) topic;
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~DhtProxyClient();
|
||||
|
||||
/**
|
||||
@@ -263,6 +271,7 @@ 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();
|
||||
}
|
||||
@@ -337,6 +346,7 @@ private:
|
||||
NodeStats stats6_ {};
|
||||
SockAddr publicAddressV4_;
|
||||
SockAddr publicAddressV6_;
|
||||
std::atomic_bool launchConnectedCbs_ {false};
|
||||
|
||||
InfoHash myid {};
|
||||
|
||||
@@ -398,6 +408,11 @@ private:
|
||||
*/
|
||||
std::string deviceKey_ {};
|
||||
|
||||
/**
|
||||
* Notification topic for ios notifications.
|
||||
*/
|
||||
std::string notificationTopic_ {};
|
||||
|
||||
const std::function<void()> loopSignal_;
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,7 +40,8 @@ namespace dht {
|
||||
enum class PushType {
|
||||
None = 0,
|
||||
Android,
|
||||
iOS
|
||||
iOS,
|
||||
iOSLegacy
|
||||
};
|
||||
}
|
||||
MSGPACK_ADD_ENUM(dht::PushType)
|
||||
@@ -273,6 +274,7 @@ private:
|
||||
restinio::router::route_params_t params);
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
PushType getTypeFromString(const std::string& type);
|
||||
/**
|
||||
* Subscribe to push notifications for an iOS or Android device.
|
||||
* Method: SUBSCRIBE "/{InfoHash: .*}"
|
||||
@@ -300,7 +302,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);
|
||||
void sendPushNotification(const std::string& key, Json::Value&& json, PushType type, bool highPriority, const std::string& topic);
|
||||
|
||||
/**
|
||||
* Send push notification with an expire timeout.
|
||||
@@ -308,9 +310,10 @@ 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);
|
||||
std::function<Json::Value()> json, PushType type, const std::string& topic);
|
||||
|
||||
/**
|
||||
* Remove a push listener between a client and a hash
|
||||
@@ -382,6 +385,7 @@ 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
|
||||
@@ -425,6 +429,7 @@ 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
|
||||
|
||||
+30
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +61,7 @@ public:
|
||||
std::string proxy_server {};
|
||||
std::string push_node_id {};
|
||||
std::string push_token {};
|
||||
std::string push_topic {};
|
||||
bool peer_discovery {false};
|
||||
bool peer_publish {false};
|
||||
std::shared_ptr<dht::crypto::Certificate> server_ca;
|
||||
@@ -257,18 +258,29 @@ public:
|
||||
}
|
||||
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
|
||||
/**
|
||||
* 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(const SockAddr& addr, DoneCallbackSimple&& cb={});
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert known nodes to the routing table, without necessarly ping them.
|
||||
* Usefull to restart a node and get things running fast without putting load on the network.
|
||||
*/
|
||||
void bootstrap(const std::vector<NodeExport>& nodes);
|
||||
void bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb={});
|
||||
void bootstrap(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);
|
||||
|
||||
/**
|
||||
* Add host:service to bootstrap nodes, and ping this node.
|
||||
@@ -303,6 +315,7 @@ public:
|
||||
* Get the public key fingerprint if an identity is used with this node, 0 otherwise.
|
||||
*/
|
||||
InfoHash getId() const;
|
||||
std::shared_ptr<crypto::PublicKey> getPublicKey() const;
|
||||
|
||||
/**
|
||||
* Get the ID of the DHT node.
|
||||
@@ -323,6 +336,7 @@ 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;
|
||||
@@ -359,8 +373,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);
|
||||
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC);
|
||||
std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC) const;
|
||||
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC) const;
|
||||
void getPublicAddress(std::function<void(std::vector<SockAddr>&&)>, sa_family_t af = AF_UNSPEC);
|
||||
|
||||
// securedht methods
|
||||
@@ -424,7 +438,6 @@ 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);
|
||||
|
||||
@@ -435,6 +448,11 @@ public:
|
||||
*/
|
||||
void setPushNotificationToken(const std::string& token);
|
||||
|
||||
/**
|
||||
* Sets the push notification topic
|
||||
*/
|
||||
void setPushNotificationTopic(const std::string& topic);
|
||||
|
||||
/**
|
||||
* Insert a push notification to process for OpenDHT
|
||||
*/
|
||||
@@ -444,8 +462,6 @@ public:
|
||||
void forwardAllMessages(bool forward);
|
||||
|
||||
private:
|
||||
static constexpr std::chrono::seconds BOOTSTRAP_PERIOD {10};
|
||||
|
||||
enum class State {
|
||||
Idle,
|
||||
Running,
|
||||
@@ -463,12 +479,9 @@ private:
|
||||
DoneCallback bindOpDoneCallback(DoneCallback&& cb);
|
||||
DoneCallbackSimple bindOpDoneCallback(DoneCallbackSimple&& cb);
|
||||
|
||||
/** Local DHT instance */
|
||||
/** 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};
|
||||
|
||||
@@ -480,17 +493,6 @@ 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 {};
|
||||
|
||||
+1
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -375,15 +375,3 @@ private:
|
||||
} // namespace http
|
||||
} // namespace dht
|
||||
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
namespace restinio
|
||||
{
|
||||
/* Custom HTTP-methods for RESTinio > 0.5.0.
|
||||
* https://github.com/Stiffstream/restinio/issues/26
|
||||
*/
|
||||
constexpr const restinio::http_method_id_t method_listen {HTTP_LISTEN, "LISTEN"};
|
||||
constexpr const restinio::http_method_id_t method_stats {HTTP_STATS, "STATS"};
|
||||
constexpr const restinio::http_method_id_t method_sign {HTTP_SIGN, "SIGN"};
|
||||
constexpr const restinio::http_method_id_t method_encrypt {HTTP_ENCRYPT, "ENCRYPT"};
|
||||
} // namespace restinio
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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>
|
||||
|
||||
+15
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
@@ -40,10 +40,12 @@ 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 {
|
||||
|
||||
@@ -65,10 +67,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
|
||||
@@ -79,7 +81,12 @@ 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(const std::string& hex);
|
||||
explicit Hash(std::string_view hex) {
|
||||
if (hex.size() < 2*N)
|
||||
data_.fill(0);
|
||||
else
|
||||
fromString(hex.data());
|
||||
}
|
||||
|
||||
Hash(const msgpack::object& o) {
|
||||
msgpack_unpack(o);
|
||||
@@ -96,13 +103,7 @@ public:
|
||||
static constexpr inline Hash zero() noexcept { return Hash{}; }
|
||||
|
||||
bool operator==(const Hash& h) const {
|
||||
auto a = reinterpret_cast<const uint32_t*>(data_.data());
|
||||
auto b = reinterpret_cast<const uint32_t*>(h.data_.data());
|
||||
constexpr unsigned n = N / sizeof(uint32_t);
|
||||
for (unsigned i=0; i < n; i++)
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
return true;
|
||||
return data_ == h.data_;
|
||||
}
|
||||
bool operator!=(const Hash& h) const { return !(*this == h); }
|
||||
|
||||
@@ -219,7 +220,7 @@ public:
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline Hash get(const std::string& data) {
|
||||
static inline Hash get(std::string_view data) {
|
||||
return get((const uint8_t*)data.data(), data.size());
|
||||
}
|
||||
|
||||
@@ -291,14 +292,6 @@ 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) {
|
||||
@@ -342,7 +335,7 @@ Hash<N>::getRandom(Rd& rdev)
|
||||
return h;
|
||||
}
|
||||
|
||||
struct HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
struct alignas(std::max_align_t) HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
HexMap() {
|
||||
for (size_t i=0; i<size(); i++) {
|
||||
auto& e = (*this)[i];
|
||||
@@ -376,7 +369,7 @@ template <size_t N>
|
||||
const char*
|
||||
Hash<N>::to_c_str() const
|
||||
{
|
||||
thread_local std::array<char, N*2+1> buf;
|
||||
alignas(std::max_align_t) thread_local std::array<char, N*2+1> buf;
|
||||
for (size_t i=0; i<N; i++) {
|
||||
auto b = buf.data()+i*2;
|
||||
const auto& m = hex_map[data_[i]];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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(Sp<Node> n, Tid socket_id, const InfoHash& hash, want_t want, const Blob& ntoken,
|
||||
void tellListener(const 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(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
|
||||
void tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& ntoken, const std::vector<Value::Id>& values, int version);
|
||||
void tellListenerRefreshed(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);
|
||||
|
||||
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(Sp<Node> n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
|
||||
sendPing(const 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(Sp<Node> n,
|
||||
Sp<Request> sendFindNode(const 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(Sp<Node> n,
|
||||
Sp<Request> sendGetValues(const 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(Sp<Node> n,
|
||||
Sp<Request> sendListen(const 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(Sp<Node> n,
|
||||
Sp<Request> sendAnnounceValue(const 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(Sp<Node> n,
|
||||
Sp<Request> sendRefreshValue(const 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(Sp<Node> n,
|
||||
Sp<Request> sendUpdateValues(const Sp<Node>& n,
|
||||
const InfoHash& infohash,
|
||||
const std::vector<Sp<Value>>& values,
|
||||
time_point created,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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 * 16;
|
||||
static const constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 64;
|
||||
static const constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(650);
|
||||
|
||||
int bindSocket(const SockAddr& addr, SockAddr& bound);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
+20
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -36,8 +36,9 @@ namespace dht {
|
||||
class Scheduler {
|
||||
public:
|
||||
struct Job {
|
||||
Job(std::function<void()>&& f) : do_(std::move(f)) {}
|
||||
Job(std::function<void()>&& f, time_point t) : do_(std::move(f)), t_(t) {}
|
||||
std::function<void()> do_;
|
||||
const time_point t_;
|
||||
void cancel() { do_ = {}; }
|
||||
};
|
||||
|
||||
@@ -50,17 +51,12 @@ 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));
|
||||
auto job = std::make_shared<Job>(std::move(job_func), t);
|
||||
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.
|
||||
*
|
||||
@@ -68,16 +64,29 @@ 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_);
|
||||
job->do_ = {};
|
||||
cancel(job);
|
||||
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 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +61,9 @@ public:
|
||||
PkId getLongId() const {
|
||||
return key_ ? key_->getPublicKey().getLongId() : PkId();
|
||||
}
|
||||
Sp<crypto::PublicKey> getPublicKey() const {
|
||||
return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey>{};
|
||||
}
|
||||
|
||||
ValueType secureType(ValueType&& type);
|
||||
|
||||
@@ -115,6 +118,10 @@ public:
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
|
||||
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false) {
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take ownership of the value and sign it using our private key.
|
||||
@@ -126,13 +133,13 @@ public:
|
||||
Value decrypt(const Value& v);
|
||||
|
||||
void findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
|
||||
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<const crypto::PublicKey>)>& cb);
|
||||
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
|
||||
|
||||
const Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
void registerCertificate(Sp<crypto::Certificate>& cert);
|
||||
|
||||
const Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
const Sp<const crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
|
||||
/**
|
||||
* Allows to set a custom callback called by the library to find a locally-stored certificate.
|
||||
@@ -166,6 +173,10 @@ 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();
|
||||
}
|
||||
@@ -354,7 +365,7 @@ private:
|
||||
|
||||
// our certificate cache
|
||||
std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
|
||||
std::map<InfoHash, Sp<const crypto::PublicKey>> nodesPubKeys_ {};
|
||||
std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
|
||||
|
||||
std::atomic_bool forward_all_ {false};
|
||||
bool enableCache_ {false};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
@@ -236,6 +236,15 @@ 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <future>
|
||||
#include <functional>
|
||||
|
||||
#include <ciso646> // fix windows compiler bug
|
||||
|
||||
namespace dht {
|
||||
|
||||
class OPENDHT_PUBLIC ThreadPool {
|
||||
@@ -63,15 +65,14 @@ public:
|
||||
void join();
|
||||
|
||||
private:
|
||||
struct ThreadState;
|
||||
std::queue<std::function<void()>> tasks_ {};
|
||||
std::vector<std::unique_ptr<ThreadState>> threads_;
|
||||
unsigned readyThreads_ {0};
|
||||
std::mutex lock_ {};
|
||||
std::condition_variable cv_ {};
|
||||
std::queue<std::function<void()>> tasks_ {};
|
||||
std::vector<std::unique_ptr<std::thread>> threads_;
|
||||
unsigned readyThreads_ {0};
|
||||
bool running_ {true};
|
||||
|
||||
const unsigned maxThreads_;
|
||||
bool running_ {true};
|
||||
};
|
||||
|
||||
class OPENDHT_PUBLIC Executor : public std::enable_shared_from_this<Executor> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
@@ -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, const std::string& key) {
|
||||
return findMapValue(map, key.c_str(), key.size());
|
||||
inline msgpack::object* findMapValue(const msgpack::object& map, std::string_view key) {
|
||||
return findMapValue(map, key.data(), key.size());
|
||||
}
|
||||
|
||||
} // namespace dht
|
||||
+41
-44
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <msgpack.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
@@ -42,8 +43,9 @@
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
using namespace std::literals;
|
||||
|
||||
static const std::string VALUE_KEY_ID("id");
|
||||
static constexpr auto 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");
|
||||
@@ -117,7 +119,7 @@ struct OPENDHT_PUBLIC ValueType {
|
||||
|
||||
Id id {0};
|
||||
std::string name {};
|
||||
duration expiration {60 * 10};
|
||||
duration expiration {std::chrono::minutes(10)};
|
||||
StorePolicy storePolicy {DEFAULT_STORE_POLICY};
|
||||
EditPolicy editPolicy {DEFAULT_EDIT_POLICY};
|
||||
};
|
||||
@@ -211,7 +213,7 @@ struct OPENDHT_PUBLIC Value
|
||||
}
|
||||
static Filter notFilter(Filter&& f) {
|
||||
if (not f) return [](const Value&) { return false; };
|
||||
return [f](const Value& v) { return not f(v); };
|
||||
return [f = std::move(f)](const Value& v) { return not f(v); };
|
||||
}
|
||||
std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
|
||||
if (not (*this))
|
||||
@@ -269,8 +271,8 @@ struct OPENDHT_PUBLIC Value
|
||||
};
|
||||
}
|
||||
|
||||
static Filter UserTypeFilter(const std::string& ut) {
|
||||
return [ut](const Value& v) {
|
||||
static Filter UserTypeFilter(std::string ut) {
|
||||
return [ut = std::move(ut)](const Value& v) {
|
||||
return v.user_type == ut;
|
||||
};
|
||||
}
|
||||
@@ -341,10 +343,10 @@ struct OPENDHT_PUBLIC Value
|
||||
return unpack<T>(*this);
|
||||
}
|
||||
|
||||
bool isEncrypted() const {
|
||||
inline bool isEncrypted() const {
|
||||
return not cypher.empty();
|
||||
}
|
||||
bool isSigned() const {
|
||||
inline bool isSigned() const {
|
||||
return owner and not signature.empty();
|
||||
}
|
||||
|
||||
@@ -353,37 +355,24 @@ 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) {
|
||||
if (isEncrypted())
|
||||
throw DhtException("Can't sign encrypted data.");
|
||||
owner = std::make_shared<const crypto::PublicKey>(key.getPublicKey());
|
||||
signature = key.sign(getToSign());
|
||||
}
|
||||
void sign(const crypto::PrivateKey& key);
|
||||
|
||||
/**
|
||||
* Check that the value is signed and that the signature matches.
|
||||
* If true, the owner field will contain the signer public key.
|
||||
*/
|
||||
bool checkSignature() const {
|
||||
inline bool checkSignature() const {
|
||||
return isSigned() and owner->checkSignature(getToSign(), signature);
|
||||
}
|
||||
|
||||
std::shared_ptr<const crypto::PublicKey> getOwner() const {
|
||||
return std::static_pointer_cast<const crypto::PublicKey>(owner);
|
||||
inline std::shared_ptr<crypto::PublicKey> getOwner() const {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the value with from and returns the encrypted version for 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 encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to);
|
||||
|
||||
Value() {}
|
||||
|
||||
@@ -451,18 +440,18 @@ struct OPENDHT_PUBLIC Value
|
||||
return id == o.id and contentEquals(o);
|
||||
}
|
||||
|
||||
void setRecipient(const InfoHash& r) {
|
||||
inline void setRecipient(const InfoHash& r) {
|
||||
recipient = r;
|
||||
}
|
||||
|
||||
void setCypher(Blob&& c) {
|
||||
inline void setCypher(Blob&& c) {
|
||||
cypher = std::move(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack part of the data to be signed (must always be done the same way)
|
||||
*/
|
||||
Blob getToSign() const {
|
||||
inline Blob getToSign() const {
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
msgpack_pack_to_sign(pk);
|
||||
@@ -472,7 +461,7 @@ struct OPENDHT_PUBLIC Value
|
||||
/**
|
||||
* Pack part of the data to be encrypted
|
||||
*/
|
||||
Blob getToEncrypt() const {
|
||||
inline Blob getToEncrypt() const {
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
msgpack_pack_to_encrypt(pk);
|
||||
@@ -482,7 +471,7 @@ struct OPENDHT_PUBLIC Value
|
||||
/** print value for debugging */
|
||||
OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Value& v);
|
||||
|
||||
std::string toString() const {
|
||||
inline std::string toString() const {
|
||||
std::stringstream ss;
|
||||
ss << *this;
|
||||
return ss.str();
|
||||
@@ -594,7 +583,7 @@ struct OPENDHT_PUBLIC Value
|
||||
/**
|
||||
* Public key of the signer.
|
||||
*/
|
||||
std::shared_ptr<const crypto::PublicKey> owner {};
|
||||
std::shared_ptr<crypto::PublicKey> owner {};
|
||||
|
||||
/**
|
||||
* Hash of the recipient (optional).
|
||||
@@ -636,8 +625,16 @@ 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 +656,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(blob_value) {}
|
||||
FieldValue(Value::Field f, Blob blob_value) : field(f), blobValue(std::move(blob_value)) {}
|
||||
|
||||
bool operator==(const FieldValue& fd) const;
|
||||
|
||||
@@ -672,9 +669,9 @@ struct OPENDHT_PUBLIC FieldValue
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& p) const {
|
||||
p.pack_map(2);
|
||||
p.pack(std::string("f")); p.pack(static_cast<uint8_t>(field));
|
||||
p.pack("f"sv); p.pack(static_cast<uint8_t>(field));
|
||||
|
||||
p.pack(std::string("v"));
|
||||
p.pack("v"sv);
|
||||
switch (field) {
|
||||
case Value::Field::Id:
|
||||
case Value::Field::ValueType:
|
||||
@@ -696,12 +693,12 @@ struct OPENDHT_PUBLIC FieldValue
|
||||
hashValue = {};
|
||||
blobValue.clear();
|
||||
|
||||
if (auto f = findMapValue(msg, "f"))
|
||||
if (auto f = findMapValue(msg, "f"sv))
|
||||
field = (Value::Field)f->as<unsigned>();
|
||||
else
|
||||
throw msgpack::type_error();
|
||||
|
||||
auto v = findMapValue(msg, "v");
|
||||
auto v = findMapValue(msg, "v"sv);
|
||||
if (not v)
|
||||
throw msgpack::type_error();
|
||||
else
|
||||
@@ -741,7 +738,7 @@ private:
|
||||
struct OPENDHT_PUBLIC Select
|
||||
{
|
||||
Select() { }
|
||||
Select(const std::string& q_str);
|
||||
Select(std::string_view q_str);
|
||||
|
||||
bool isSatisfiedBy(const Select& os) const;
|
||||
|
||||
@@ -796,7 +793,7 @@ private:
|
||||
struct OPENDHT_PUBLIC Where
|
||||
{
|
||||
Where() { }
|
||||
Where(const std::string& q_str);
|
||||
Where(std::string_view q_str);
|
||||
|
||||
bool isSatisfiedBy(const Where& where) const;
|
||||
|
||||
@@ -863,7 +860,7 @@ struct OPENDHT_PUBLIC Where
|
||||
*
|
||||
* @return the resulting Where instance.
|
||||
*/
|
||||
Where& userType(std::string user_type) {
|
||||
Where& userType(std::string_view 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));
|
||||
@@ -936,11 +933,11 @@ struct OPENDHT_PUBLIC Query
|
||||
* - $string$: a simple string WITHOUT SPACES.
|
||||
* - $integer$: a simple integer.
|
||||
*/
|
||||
Query(std::string q_str) {
|
||||
Query(std::string_view q_str) {
|
||||
auto pos_W = q_str.find("WHERE");
|
||||
auto pos_w = q_str.find("where");
|
||||
auto pos = std::min(pos_W != std::string::npos ? pos_W : q_str.size(),
|
||||
pos_w != std::string::npos ? pos_w : q_str.size());
|
||||
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());
|
||||
select = q_str.substr(0, pos);
|
||||
where = q_str.substr(pos, q_str.size()-pos);
|
||||
}
|
||||
|
||||
@@ -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' (for the C++11 standard)
|
||||
# or '14' (for the C++14 standard).
|
||||
# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for
|
||||
# the respective C++ standard version.
|
||||
#
|
||||
# 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 an extended mode.
|
||||
# preference for no added switch, and then 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,13 +35,15 @@
|
||||
# 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 11
|
||||
#serial 14
|
||||
|
||||
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||
dnl (serial version number 13).
|
||||
@@ -50,6 +52,7 @@ 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], [],
|
||||
@@ -62,6 +65,16 @@ 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
|
||||
@@ -140,7 +153,6 @@ 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],
|
||||
@@ -148,12 +160,24 @@ 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], [[
|
||||
@@ -949,3 +973,33 @@ 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
@@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
Name: OpenDHT
|
||||
Description: C++14 Distributed Hash Table library
|
||||
Description: C++17 Distributed Hash Table library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lopendht
|
||||
Libs.private: @http_parser_lib@ -pthread
|
||||
|
||||
+8
-8
@@ -1,11 +1,11 @@
|
||||
# distutils: language = c++
|
||||
# distutils: extra_compile_args = -std=c++14
|
||||
# distutils: extra_compile_args = -std=c++17
|
||||
# distutils: include_dirs = ../../include
|
||||
# distutils: library_dirs = ../../src
|
||||
# distutils: libraries = opendht gnutls
|
||||
# cython: language_level=3
|
||||
#
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-2022 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>
|
||||
@@ -329,11 +329,11 @@ cdef class PrivateKey(_WithID):
|
||||
cdef shared_ptr[cpp.PrivateKey] _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.get().getPublicKey().getId()
|
||||
h._infohash = self._key.get().getSharedPublicKey().get().getId()
|
||||
return h
|
||||
def getPublicKey(self):
|
||||
pk = PublicKey()
|
||||
pk._key = self._key.get().getPublicKey()
|
||||
pk._key = self._key.get().getSharedPublicKey()
|
||||
return pk
|
||||
def decrypt(self, bytes dat):
|
||||
cdef size_t d_len = len(dat)
|
||||
@@ -358,17 +358,17 @@ cdef class PrivateKey(_WithID):
|
||||
return k
|
||||
|
||||
cdef class PublicKey(_WithID):
|
||||
cdef cpp.PublicKey _key
|
||||
cdef cpp.shared_ptr[cpp.PublicKey] _key
|
||||
def getId(self):
|
||||
h = InfoHash()
|
||||
h._infohash = self._key.getId()
|
||||
h._infohash = self._key.get().getId()
|
||||
return h
|
||||
def encrypt(self, bytes dat):
|
||||
cdef size_t d_len = len(dat)
|
||||
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
|
||||
cdef cpp.Blob indat
|
||||
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
|
||||
cdef cpp.Blob encrypted = self._key.encrypt(indat)
|
||||
cdef cpp.Blob encrypted = self._key.get().encrypt(indat)
|
||||
cdef char* encrypted_c_str = <char *>encrypted.data()
|
||||
cdef Py_ssize_t length = encrypted.size()
|
||||
return encrypted_c_str[:length]
|
||||
@@ -440,7 +440,7 @@ cdef class Identity(object):
|
||||
property publickey:
|
||||
def __get__(self):
|
||||
k = PublicKey()
|
||||
k._key = self._id.first.get().getPublicKey()
|
||||
k._key = self._id.first.get().getSharedPublicKey()
|
||||
return k
|
||||
property certificate:
|
||||
def __get__(self):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-2022 Savoir-faire Linux Inc.
|
||||
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
# Simon Désaulniers <sim.desaulniers@gmail.com>
|
||||
#
|
||||
@@ -97,7 +97,7 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto":
|
||||
|
||||
cdef cppclass PrivateKey:
|
||||
PrivateKey()
|
||||
PublicKey getPublicKey() const
|
||||
shared_ptr[PublicKey] getSharedPublicKey() const
|
||||
Blob decrypt(Blob data) const
|
||||
@staticmethod
|
||||
PrivateKey generate()
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2022 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++14"],
|
||||
extra_link_args=["-std=c++14"],
|
||||
extra_compile_args=["-std=c++17"],
|
||||
extra_link_args=["-std=c++17"],
|
||||
libraries=["opendht"],
|
||||
library_dirs = ['@CURRENT_BINARY_DIR@', '@PROJECT_BINARY_DIR@']
|
||||
))
|
||||
|
||||
@@ -20,7 +20,7 @@ help).
|
||||
|
||||
## Python dependencies
|
||||
|
||||
- pyroute2 >=0.3.14
|
||||
- pyroute2 >=0.6.9
|
||||
- matplotlib
|
||||
- GeoIP (used by `scanner.py` for drawing map of the world)
|
||||
- ipaddress
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
# Simon Désaulniers <sim.desaulniers@gmail.com>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-2022 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.netns.process.proxy import NSPopen
|
||||
from pyroute2 import NSPopen
|
||||
import msgpack
|
||||
|
||||
from opendht import *
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2015-2019 Savoir-Faire Linux Inc.
|
||||
# Copyright (C) 2015-2022 Savoir-Faire Linux Inc.
|
||||
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
# Simon Désaulniers <sim.desaulniers@gmail.com>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-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
|
||||
@@ -15,107 +15,253 @@
|
||||
#
|
||||
# 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
|
||||
|
||||
import argparse, subprocess
|
||||
from pyroute2 import NDB, NSPopen
|
||||
|
||||
from pyroute2 import IPDB, NetNS
|
||||
from pyroute2.netns.process.proxy import NSPopen
|
||||
|
||||
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")
|
||||
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',
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
local_addr4 = '10.0.42.'
|
||||
local_addr6 = '2001:db9::'
|
||||
brige_name = 'br'+args.ifname
|
||||
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)
|
||||
|
||||
ip = None
|
||||
try:
|
||||
ip = IPDB()
|
||||
with NDB(log='debug' if args.debug else None) as ndb:
|
||||
if args.remove:
|
||||
# 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()
|
||||
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()
|
||||
# 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}')
|
||||
|
||||
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)
|
||||
# cleanup namespaces
|
||||
for nsname in namespaces:
|
||||
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())
|
||||
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)
|
||||
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,
|
||||
)
|
||||
nsp.communicate()
|
||||
nsp.wait()
|
||||
nsp.release()
|
||||
if args.verbose:
|
||||
print(
|
||||
f'netem: add {nsname}/{veth}, '
|
||||
f'{args.delay}, {args.loss}'
|
||||
)
|
||||
|
||||
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 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}')
|
||||
|
||||
except Exception as e:
|
||||
print('Error',e)
|
||||
finally:
|
||||
if ip:
|
||||
ip.release()
|
||||
# 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)
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2022 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,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2016-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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
|
||||
# Copyright (c) 2015-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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +47,7 @@ impl DhtRunnerConfig {
|
||||
proxy_server: ptr::null(),
|
||||
push_node_id: ptr::null(),
|
||||
push_token: ptr::null(),
|
||||
push_topic: ptr::null(),
|
||||
peer_discovery: false,
|
||||
peer_publish: false,
|
||||
server_ca: ptr::null_mut(),
|
||||
@@ -73,6 +74,10 @@ 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_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);
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,6 +118,7 @@ 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 peer_discovery: bool,
|
||||
pub peer_publish: bool,
|
||||
pub server_ca: *mut DhtCertificate,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+7
-31
@@ -2,7 +2,7 @@ lib_LTLIBRARIES = libopendht.la
|
||||
|
||||
libopendht_la_CPPFLAGS = @CPPFLAGS@ -I$(top_srcdir)/include/opendht @Argon2_CFLAGS@ @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@ @OpenSSL_CFLAGS@ @Fmt_CFLAGS@
|
||||
libopendht_la_LIBADD = @Argon2_LIBS@ @JsonCpp_LIBS@ @GnuTLS_LIBS@ @Nettle_LIBS@ @OpenSSL_LIBS@ @Fmt_LIBS@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ @Argon2_LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_LDFLAGS = @LDFLAGS@ -version-number @OPENDHT_MAJOR_VERSION@:@OPENDHT_MINOR_VERSION@:@OPENDHT_PATCH_VERSION@
|
||||
libopendht_la_SOURCES = \
|
||||
dht.cpp \
|
||||
storage.h \
|
||||
@@ -30,6 +30,12 @@ libopendht_la_SOURCES = \
|
||||
network_utils.cpp \
|
||||
thread_pool.cpp
|
||||
|
||||
if APPLE
|
||||
libopendht_la_SOURCES += \
|
||||
compat/apple/apple_utils.h \
|
||||
compat/apple/apple_utils.mm
|
||||
endif
|
||||
|
||||
if WIN32
|
||||
libopendht_la_SOURCES += rng.cpp
|
||||
endif
|
||||
@@ -84,33 +90,3 @@ if ENABLE_INDEXATION
|
||||
libopendht_la_SOURCES += indexation/pht.cpp
|
||||
nobase_include_HEADERS += ../include/opendht/indexation/pht.h
|
||||
endif
|
||||
|
||||
clean-local:
|
||||
rm -rf libargon2.la
|
||||
|
||||
######################
|
||||
# ARGON2 submodule #
|
||||
######################
|
||||
|
||||
if WITH_INCLUDED_ARGON2
|
||||
noinst_LTLIBRARIES = libargon2.la
|
||||
libopendht_la_DEPENDENCIES = libargon2.la
|
||||
|
||||
libargon2_la_CFLAGS = -std=c89 -fPIC -pthread -O3 -Wall -I@top_builddir@/argon2/include -I@top_builddir@/argon2/src
|
||||
libargon2_la_SOURCES = \
|
||||
@top_builddir@/argon2/src/argon2.c \
|
||||
@top_builddir@/argon2/src/core.c \
|
||||
@top_builddir@/argon2/src/blake2/blake2b.c \
|
||||
@top_builddir@/argon2/src/thread.c \
|
||||
@top_builddir@/argon2/src/ref.c \
|
||||
@top_builddir@/argon2/src/encoding.c
|
||||
|
||||
noinst_HEADERS = \
|
||||
@top_builddir@/argon2/include/argon2.h \
|
||||
@top_builddir@/argon2/src/blake2/blake2.h \
|
||||
@top_builddir@/argon2/src/blake2/blake2-impl.h \
|
||||
@top_builddir@/argon2/src/blake2/blamka-round-ref.h \
|
||||
@top_builddir@/argon2/src/core.h \
|
||||
@top_builddir@/argon2/src/encoding.h \
|
||||
@top_builddir@/argon2/src/thread.h
|
||||
endif
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2022 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
|
||||
* 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 <string>
|
||||
|
||||
namespace dht {
|
||||
namespace apple_utils {
|
||||
|
||||
std::string getPlatformVersion();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2022 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
|
||||
* 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 "apple_utils.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Foundation/Foundation.h>
|
||||
#include "TargetConditionals.h"
|
||||
#endif
|
||||
|
||||
namespace dht {
|
||||
namespace apple_utils {
|
||||
|
||||
std::string
|
||||
getPlatformVersion() {
|
||||
#ifdef __APPLE__
|
||||
#if TARGET_OS_IPHONE
|
||||
if (@available(iOS 14.5, *)) {
|
||||
return "ios";
|
||||
}
|
||||
return "apple";
|
||||
#elif TARGET_OS_MAC
|
||||
return "macos";
|
||||
#endif
|
||||
#endif
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
} /* dht */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+99
-84
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -43,18 +43,6 @@ 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 {
|
||||
@@ -69,7 +57,7 @@ constexpr gnutls_digest_algorithm_t gnutlsHashAlgo(size_t min_res) {
|
||||
GNUTLS_DIG_SHA1));
|
||||
}
|
||||
|
||||
constexpr size_t gnutlsHashSize(int algo) {
|
||||
constexpr size_t gnutlsHashSize(gnutls_digest_algorithm_t algo) {
|
||||
return (algo == GNUTLS_DIG_SHA512) ? 512/8 : (
|
||||
(algo == GNUTLS_DIG_SHA256) ? 256/8 : (
|
||||
(algo == GNUTLS_DIG_SHA1) ? 160/8 : 0 ));
|
||||
@@ -110,10 +98,6 @@ 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;
|
||||
@@ -368,13 +352,23 @@ PrivateKey::serialize(uint8_t* out, size_t* out_len, const std::string& password
|
||||
: gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, password.c_str(), GNUTLS_PKCS_PBES2_AES_256, out, out_len);
|
||||
}
|
||||
|
||||
PublicKey
|
||||
const PublicKey&
|
||||
PrivateKey::getPublicKey() const
|
||||
{
|
||||
PublicKey pk;
|
||||
if (auto err = gnutls_pubkey_import_privkey(pk.pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
|
||||
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
|
||||
return pk;
|
||||
return *getSharedPublicKey();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return publicKey_;
|
||||
}
|
||||
|
||||
PublicKey::PublicKey()
|
||||
@@ -533,41 +527,36 @@ PublicKey::encrypt(const uint8_t* data, size_t data_len) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
InfoHash
|
||||
const InfoHash&
|
||||
PublicKey::getId() const
|
||||
{
|
||||
if (not pk)
|
||||
return {};
|
||||
InfoHash id;
|
||||
size_t sz = id.size();
|
||||
#if GNUTLS_VERSION_NUMBER < 0x030401
|
||||
const int flags = 0;
|
||||
#else
|
||||
const int flags = (id.size() == 32) ? GNUTLS_KEYID_USE_SHA256 : 0;
|
||||
#endif
|
||||
if (auto err = gnutls_pubkey_get_key_id(pk, flags, id.data(), &sz))
|
||||
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;
|
||||
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_;
|
||||
}
|
||||
|
||||
PkId
|
||||
const PkId&
|
||||
PublicKey::getLongId() const
|
||||
{
|
||||
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
|
||||
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_;
|
||||
}
|
||||
|
||||
gnutls_digest_algorithm_t
|
||||
@@ -844,36 +833,36 @@ Certificate::getPublicKey() const
|
||||
return pk_ret;
|
||||
}
|
||||
|
||||
InfoHash
|
||||
const InfoHash&
|
||||
Certificate::getId() const
|
||||
{
|
||||
if (not cert)
|
||||
return {};
|
||||
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.");
|
||||
return id;
|
||||
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_;
|
||||
}
|
||||
|
||||
PkId
|
||||
const PkId&
|
||||
Certificate::getLongId() const
|
||||
{
|
||||
if (not cert)
|
||||
return {};
|
||||
#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.");
|
||||
return id;
|
||||
#endif
|
||||
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_;
|
||||
}
|
||||
|
||||
Blob
|
||||
@@ -1047,6 +1036,8 @@ 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));
|
||||
@@ -1153,14 +1144,14 @@ setRandomSerial(gnutls_x509_crt_t cert)
|
||||
}
|
||||
|
||||
Certificate
|
||||
Certificate::generate(const PrivateKey& key, const std::string& name, const Identity& ca, bool is_ca)
|
||||
Certificate::generate(const PrivateKey& key, const std::string& name, const Identity& ca, bool is_ca, int64_t validity)
|
||||
{
|
||||
gnutls_x509_crt_t cert;
|
||||
if (not key.x509_key or gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
|
||||
return {};
|
||||
Certificate ret {cert};
|
||||
|
||||
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
|
||||
setValidityPeriod(cert, validity <= 0 ? 10 * 365 * 24 * 60 * 60 : validity);
|
||||
if (int err = gnutls_x509_crt_set_key(cert, key.x509_key)) {
|
||||
throw CryptoException(std::string("Error when setting certificate key ") + gnutls_strerror(err));
|
||||
}
|
||||
@@ -1169,7 +1160,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
}
|
||||
|
||||
// TODO: compute the subject key using the recommended RFC method
|
||||
auto pk = key.getPublicKey();
|
||||
const auto& pk = key.getPublicKey();
|
||||
auto pk_id = pk.getId();
|
||||
const std::string uid_str = pk_id.toString();
|
||||
|
||||
@@ -1206,7 +1197,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
}
|
||||
|
||||
Certificate
|
||||
Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
Certificate::generate(const CertificateRequest& request, const Identity& ca, int64_t validity)
|
||||
{
|
||||
gnutls_x509_crt_t cert;
|
||||
if (auto err = gnutls_x509_crt_init(&cert))
|
||||
@@ -1219,7 +1210,7 @@ Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
throw CryptoException(std::string("Can't set certificate version: ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
|
||||
setValidityPeriod(cert, validity <= 0 ? 10 * 365 * 24 * 60 * 60 : validity);
|
||||
setRandomSerial(cert);
|
||||
|
||||
if (auto err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, ca.second->getPreferredDigest(), 0)) {
|
||||
@@ -1230,6 +1221,32 @@ Certificate::generate(const CertificateRequest& request, const Identity& ca)
|
||||
return ret.getPacked();
|
||||
}
|
||||
|
||||
void
|
||||
Certificate::setValidity(const Identity& ca, int64_t validity)
|
||||
{
|
||||
setValidityPeriod(cert, validity);
|
||||
setRandomSerial(cert);
|
||||
if (ca.first && ca.second) {
|
||||
if (not ca.second->isCA()) {
|
||||
throw CryptoException("Signing certificate must be CA");
|
||||
}
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, ca.second->getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Certificate::setValidity(const PrivateKey& key, int64_t validity)
|
||||
{
|
||||
setValidityPeriod(cert, validity);
|
||||
setRandomSerial(cert);
|
||||
const auto& pk = key.getPublicKey();
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0)) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<RevocationList>>
|
||||
Certificate::getRevocationLists() const
|
||||
{
|
||||
@@ -1437,7 +1454,7 @@ RevocationList::RevocationList(const Blob& b)
|
||||
} catch (const std::exception& e) {
|
||||
gnutls_x509_crl_deinit(crl);
|
||||
crl = nullptr;
|
||||
throw e;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1733,10 +1750,8 @@ 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
|
||||
+158
-107
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -30,16 +30,20 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace dht {
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
constexpr std::chrono::minutes Dht::MAX_STORAGE_MAINTENANCE_EXPIRE_TIME;
|
||||
constexpr std::chrono::minutes Dht::SEARCH_EXPIRE_TIME;
|
||||
constexpr std::chrono::seconds Dht::BOOTSTRAP_PERIOD;
|
||||
constexpr duration Dht::LISTEN_EXPIRE_TIME;
|
||||
constexpr duration Dht::LISTEN_EXPIRE_TIME_PUBLIC;
|
||||
constexpr duration Dht::REANNOUNCE_MARGIN;
|
||||
static constexpr size_t MAX_REQUESTS_PER_SEC {8 * 1024};
|
||||
static constexpr duration BOOTSTRAP_PERIOD_MAX {std::chrono::hours(24)};
|
||||
|
||||
NodeStatus
|
||||
Dht::updateStatus(sa_family_t af)
|
||||
@@ -49,9 +53,9 @@ Dht::updateStatus(sa_family_t af)
|
||||
d.status = d.getStatus(scheduler.time());
|
||||
if (d.status != old) {
|
||||
auto& other = dht(af == AF_INET ? AF_INET6 : AF_INET);
|
||||
if (other.status == NodeStatus::Disconnected && d.status == NodeStatus::Disconnected)
|
||||
if (other.status == NodeStatus::Disconnected && d.status == NodeStatus::Disconnected) {
|
||||
onDisconnected();
|
||||
else if (other.status == NodeStatus::Connected || d.status == NodeStatus::Connected) {
|
||||
} else if (other.status == NodeStatus::Connected || d.status == NodeStatus::Connected) {
|
||||
onConnected();
|
||||
}
|
||||
}
|
||||
@@ -284,7 +288,7 @@ Dht::searchNodeGetDone(const net::Request& req,
|
||||
if (srn->syncJob)
|
||||
scheduler.edit(srn->syncJob, syncTime);
|
||||
else
|
||||
srn->syncJob = scheduler.add(syncTime, std::bind(&Dht::searchStep, this, sr));
|
||||
srn->syncJob = scheduler.add(syncTime, std::bind(&Dht::searchStep, this, ws));
|
||||
}
|
||||
onGetValuesDone(req.node, answer, sr, query);
|
||||
}
|
||||
@@ -486,21 +490,23 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
} catch (std::out_of_range&) { }
|
||||
|
||||
auto next_refresh_time = now + getType(a.value->type).expiration;
|
||||
auto& acked = sn->acked[a.value->id];
|
||||
scheduler.cancel(acked.refresh);
|
||||
/* only put the value if the node doesn't already have it */
|
||||
if (not hasValue or seq_no < a.value->seq) {
|
||||
if (logger_)
|
||||
logger_->d(sr->id, sn->node->id, "[search %s] [node %s] sending 'put' (vid: %d)",
|
||||
logger_->d(sr->id, sn->node->id, "[search %s] [node %s] sending 'put' (vid: %016" PRIx64 ")",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
auto created = a.permanent ? time_point::max() : a.created;
|
||||
sn->acked[a.value->id] = {
|
||||
acked = {
|
||||
network_engine.sendAnnounceValue(sn->node, sr->id, a.value, created, sn->token, onDone, onExpired),
|
||||
next_refresh_time
|
||||
};
|
||||
} else if (hasValue and a.permanent) {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %d)",
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %016" PRIx64 ")",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
sn->acked[a.value->id] = {
|
||||
acked = {
|
||||
network_engine.sendRefreshValue(sn->node, sr->id, a.value->id, sn->token, onDone,
|
||||
[this, ws, node=sn->node, v=a.value,
|
||||
onDone,
|
||||
@@ -528,21 +534,17 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
};
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] already has value (vid: %d). Aborting.",
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] already has value (vid: %016" PRIx64 "). Aborting.",
|
||||
sr->id.toString().c_str(), sn->node->toString().c_str(), a.value->id);
|
||||
auto ack_req = std::make_shared<net::Request>(net::Request::State::COMPLETED);
|
||||
ack_req->reply_time = now;
|
||||
sn->acked[a.value->id] = std::make_pair(std::move(ack_req), next_refresh_time);
|
||||
acked = {std::move(ack_req), next_refresh_time};
|
||||
|
||||
/* step to clear announces */
|
||||
scheduler.edit(sr->nextSearchStep, now);
|
||||
}
|
||||
if (a.permanent) {
|
||||
scheduler.add(next_refresh_time - REANNOUNCE_MARGIN, [this,ws] {
|
||||
if (auto sr = ws.lock()) {
|
||||
searchStep(sr);
|
||||
}
|
||||
});
|
||||
acked.refresh = scheduler.add(next_refresh_time - REANNOUNCE_MARGIN, std::bind(&Dht::searchStep, this, ws));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -567,7 +569,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr) {
|
||||
sendQuery = true;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, n.node->id, "[search %s] [node %s] sending 'put' (vid: %d)",
|
||||
logger_->w(sr->id, n.node->id, "[search %s] [node %s] sending 'put' (vid: %016" PRIx64 ")",
|
||||
sr->id.toString().c_str(), n.node->toString().c_str(), a.value->id);
|
||||
n.acked[a.value->id] = {
|
||||
network_engine.sendAnnounceValue(n.node, sr->id, a.value, a.created, n.token, onDone, onExpired),
|
||||
@@ -640,8 +642,8 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
|
||||
if (auto sr = ws.lock()) {
|
||||
scheduler.edit(sr->nextSearchStep, scheduler.time());
|
||||
if (auto sn = sr->getNode(req.node)) {
|
||||
scheduler.add(sn->getListenTime(query, getListenExpiration()), std::bind(&Dht::searchStep, this, sr));
|
||||
sn->onListenSynced(query);
|
||||
auto job = scheduler.add(sn->getListenTime(query, getListenExpiration()), std::bind(&Dht::searchStep, this, ws));
|
||||
sn->onListenSynced(query, true, std::move(job));
|
||||
}
|
||||
onListenDone(req.node, answer, sr);
|
||||
}
|
||||
@@ -667,8 +669,9 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
|
||||
/* When a search is in progress, we periodically call search_step to send
|
||||
further requests. */
|
||||
void
|
||||
Dht::searchStep(Sp<Search> sr)
|
||||
Dht::searchStep(std::weak_ptr<Search> ws)
|
||||
{
|
||||
auto sr = ws.lock();
|
||||
if (not sr or sr->expired or sr->done) return;
|
||||
|
||||
const auto& now = scheduler.time();
|
||||
@@ -821,7 +824,7 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback gcb, QueryCallback q
|
||||
sr->expired = false;
|
||||
sr->nodes.clear();
|
||||
sr->nodes.reserve(SEARCH_NODES+1);
|
||||
sr->nextSearchStep = scheduler.add(time_point::max(), std::bind(&Dht::searchStep, this, sr));
|
||||
sr->nextSearchStep = scheduler.add(time_point::max(), std::bind(&Dht::searchStep, this, std::weak_ptr<Search>(sr)));
|
||||
if (logger_)
|
||||
logger_->w(id, "[search %s IPv%c] new search", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
if (search_id == 0)
|
||||
@@ -873,6 +876,11 @@ Dht::listenTo(const InfoHash& id, sa_family_t af, ValueCallback cb, Value::Filte
|
||||
size_t
|
||||
Dht::listen(const InfoHash& id, ValueCallback cb, Value::Filter f, Where where)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Listen called with invalid key");
|
||||
return 0;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
|
||||
auto token = ++listener_token;
|
||||
@@ -955,7 +963,9 @@ struct GetStatus : public OpStatus {
|
||||
void
|
||||
Dht::put(const InfoHash& id, Sp<Value> val, DoneCallback callback, time_point created, bool permanent)
|
||||
{
|
||||
if (not val) {
|
||||
if (not id or not val) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Put called with invalid key or value");
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
@@ -1025,6 +1035,13 @@ bool callbackWrapper(Cb get_cb, DoneCallback done_cb, const std::vector<Sp<T>>&
|
||||
void
|
||||
Dht::get(const InfoHash& id, GetCallback getcb, DoneCallback donecb, Value::Filter&& filter, Where&& where)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Get called with invalid key");
|
||||
if (donecb)
|
||||
donecb(false, {});
|
||||
return;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
|
||||
auto op = std::make_shared<GetStatus<std::map<Value::Id, Sp<Value>>>>();
|
||||
@@ -1065,6 +1082,13 @@ Dht::get(const InfoHash& id, GetCallback getcb, DoneCallback donecb, Value::Filt
|
||||
|
||||
void Dht::query(const InfoHash& id, QueryCallback cb, DoneCallback done_cb, Query&& q)
|
||||
{
|
||||
if (not id) {
|
||||
if (logger_)
|
||||
logger_->w(id, "Query called with invalid key");
|
||||
if (done_cb)
|
||||
done_cb(false, {});
|
||||
return;
|
||||
}
|
||||
scheduler.syncTime();
|
||||
auto op = std::make_shared<GetStatus<std::vector<Sp<FieldValueIndex>>>>();
|
||||
auto f = q.where.getFilter();
|
||||
@@ -1170,15 +1194,20 @@ Dht::cancelPut(const InfoHash& id, const Value::Id& vid)
|
||||
};
|
||||
canceled |= sr_cancel_put(dht4.searches);
|
||||
canceled |= sr_cancel_put(dht6.searches);
|
||||
if (canceled)
|
||||
storageErase(id, vid);
|
||||
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());
|
||||
}
|
||||
}
|
||||
return canceled;
|
||||
}
|
||||
|
||||
// Storage
|
||||
|
||||
void
|
||||
Dht::storageChanged(const InfoHash& id, Storage& st, ValueStorage& v, bool newValue)
|
||||
Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool newValue)
|
||||
{
|
||||
if (newValue) {
|
||||
if (not st.local_listeners.empty()) {
|
||||
@@ -1188,8 +1217,8 @@ Dht::storageChanged(const InfoHash& id, Storage& st, ValueStorage& v, bool newVa
|
||||
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.data))
|
||||
vals.push_back(v.data);
|
||||
if (not l.second.filter or l.second.filter(*v))
|
||||
vals.push_back(v);
|
||||
if (not vals.empty()) {
|
||||
if (logger_)
|
||||
logger_->d(id, "[store %s] sending update local listener with token %lu",
|
||||
@@ -1210,14 +1239,14 @@ Dht::storageChanged(const InfoHash& id, Storage& st, ValueStorage& v, bool newVa
|
||||
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.data))
|
||||
if (f and not f(*v))
|
||||
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.data);
|
||||
vals.push_back(v);
|
||||
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);
|
||||
@@ -1253,30 +1282,23 @@ 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 (not permanent) {
|
||||
scheduler.add(expiration, std::bind(&Dht::expireStorage, this, id));
|
||||
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;
|
||||
expireStore();
|
||||
storageChanged(id, st->second, value, value_diff > 0);
|
||||
} else {
|
||||
storageChanged(id, st->second, vs->data, store.second.values_diff > 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)
|
||||
{
|
||||
@@ -1308,36 +1330,8 @@ 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()) {
|
||||
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);
|
||||
}
|
||||
storageRemoved(id, st, stats.second, -stats.first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1349,6 +1343,41 @@ 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()
|
||||
{
|
||||
@@ -1374,23 +1403,23 @@ Dht::expireStore()
|
||||
break;
|
||||
}
|
||||
auto largest = store_quota.begin();
|
||||
for (auto it = ++largest; it != store_quota.end(); ++it) {
|
||||
for (auto it = std::next(largest); it != store_quota.end(); ++it) {
|
||||
if (it->second.size() > largest->second.size())
|
||||
largest = it;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1414,6 +1443,7 @@ Dht::connectivityChanged(sa_family_t af)
|
||||
reported_addr.erase(std::remove_if(reported_addr.begin(), reported_addr.end(), [&](const ReportedAddr& addr){
|
||||
return addr.second.getFamily() == af;
|
||||
}), reported_addr.end());
|
||||
startBootstrap(); // will only happen if disconnected
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1595,10 +1625,10 @@ Dht::dumpSearch(const Search& sr, std::ostream& out) const
|
||||
out << "[";
|
||||
for (const auto& a : sr.announce) {
|
||||
auto ack = n.acked.find(a.value->id);
|
||||
if (ack == n.acked.end() or not ack->second.first) {
|
||||
if (ack == n.acked.end() or not ack->second.req) {
|
||||
out << ' ';
|
||||
} else {
|
||||
out << ack->second.first->getStateChar();
|
||||
out << ack->second.req->getStateChar();
|
||||
}
|
||||
}
|
||||
out << "] ";
|
||||
@@ -1638,7 +1668,7 @@ Dht::dumpTables() const
|
||||
std::string
|
||||
Dht::getStorageLog() const
|
||||
{
|
||||
std::stringstream out;
|
||||
std::ostringstream out;
|
||||
for (const auto& s : store)
|
||||
out << printStorageLog(s);
|
||||
out << std::endl << std::endl;
|
||||
@@ -1763,7 +1793,8 @@ 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_size ? (int)config.max_store_size : MAX_HASHES),
|
||||
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_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),
|
||||
@@ -1995,11 +2026,7 @@ Dht::expire()
|
||||
void
|
||||
Dht::onConnected()
|
||||
{
|
||||
if (bootstrapJob) {
|
||||
bootstrapJob->cancel();
|
||||
bootstrapJob.reset();
|
||||
}
|
||||
bootstrap_period = std::chrono::seconds(10);
|
||||
stopBootstrap();
|
||||
auto callbacks = std::move(onConnectCallbacks_);
|
||||
while (not callbacks.empty()) {
|
||||
callbacks.front()();
|
||||
@@ -2009,6 +2036,13 @@ Dht::onConnected()
|
||||
|
||||
void
|
||||
Dht::onDisconnected()
|
||||
{
|
||||
if (not bootstrapJob)
|
||||
bootstrap();
|
||||
}
|
||||
|
||||
void
|
||||
Dht::bootstrap()
|
||||
{
|
||||
if (dht4.status != NodeStatus::Disconnected || dht6.status != NodeStatus::Disconnected)
|
||||
return;
|
||||
@@ -2027,10 +2061,23 @@ Dht::onDisconnected()
|
||||
logger_->e(myid, "Can't resolve %s:%s: %s", boootstrap.first.c_str(), boootstrap.second.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
if (bootstrapJob)
|
||||
bootstrapJob->cancel();
|
||||
bootstrapJob = scheduler.add(scheduler.time() + bootstrap_period, std::bind(&Dht::onDisconnected, this));
|
||||
bootstrap_period *= 2;
|
||||
scheduler.cancel(bootstrapJob);
|
||||
bootstrapJob = scheduler.add(scheduler.time() + bootstrap_period, std::bind(&Dht::bootstrap, this));
|
||||
bootstrap_period = std::min(bootstrap_period * 2, BOOTSTRAP_PERIOD_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
Dht::startBootstrap()
|
||||
{
|
||||
stopBootstrap();
|
||||
bootstrapJob = scheduler.add(scheduler.time(), std::bind(&Dht::bootstrap, this));
|
||||
}
|
||||
|
||||
void
|
||||
Dht::stopBootstrap()
|
||||
{
|
||||
scheduler.cancel(bootstrapJob);
|
||||
bootstrap_period = BOOTSTRAP_PERIOD;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2147,25 +2194,25 @@ Dht::exportNodes() const
|
||||
if (b4 != dht4.buckets.end()) {
|
||||
for (auto& n : b4->nodes)
|
||||
if (n->isGood(now))
|
||||
nodes.push_back(n->exportNode());
|
||||
nodes.emplace_back(n->exportNode());
|
||||
}
|
||||
const auto b6 = dht6.buckets.findBucket(myid);
|
||||
if (b6 != dht6.buckets.end()) {
|
||||
for (auto& n : b6->nodes)
|
||||
if (n->isGood(now))
|
||||
nodes.push_back(n->exportNode());
|
||||
nodes.emplace_back(n->exportNode());
|
||||
}
|
||||
for (auto b = dht4.buckets.begin(); b != dht4.buckets.end(); ++b) {
|
||||
if (b == b4) continue;
|
||||
for (auto& n : b->nodes)
|
||||
if (n->isGood(now))
|
||||
nodes.push_back(n->exportNode());
|
||||
nodes.emplace_back(n->exportNode());
|
||||
}
|
||||
for (auto b = dht6.buckets.begin(); b != dht6.buckets.end(); ++b) {
|
||||
if (b == b6) continue;
|
||||
for (auto& n : b->nodes)
|
||||
if (n->isGood(now))
|
||||
nodes.push_back(n->exportNode());
|
||||
nodes.emplace_back(n->exportNode());
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
@@ -2438,7 +2485,7 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
if (*lv == *vc) {
|
||||
storageRefresh(hash, v->id);
|
||||
if (logger_)
|
||||
logger_->d(hash, node.id, "[store %s] [node %s] refreshed value %s", hash.toString().c_str(), node.toString().c_str(), std::to_string(v->id).c_str());
|
||||
logger_->d(hash, node.id, "[store %s] [node %s] refreshed value %016" PRIx64, hash.toString().c_str(), node.toString().c_str(), v->id);
|
||||
} else {
|
||||
const auto& type = getType(lv->type);
|
||||
if (type.editPolicy(hash, lv, vc, node.id, node.getAddr())) {
|
||||
@@ -2481,7 +2528,7 @@ Dht::onRefresh(Sp<Node> node, const InfoHash& hash, const Blob& token, const Val
|
||||
}
|
||||
if (storageRefresh(hash, vid)) {
|
||||
if (logger_)
|
||||
logger_->d(hash, node->id, "[store %s] [node %s] refreshed value %s", hash.toString().c_str(), node->toString().c_str(), std::to_string(vid).c_str());
|
||||
logger_->d(hash, node->id, "[store %s] [node %s] refreshed value %016" PRIx64, hash.toString().c_str(), node->toString().c_str(), vid);
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->d(hash, node->id, "[store %s] [node %s] got refresh for unknown value",
|
||||
@@ -2516,9 +2563,13 @@ Dht::storageRefresh(const InfoHash& id, Value::Id vid)
|
||||
}
|
||||
}
|
||||
|
||||
auto expiration = s->second.refresh(now, vid, types);
|
||||
if (expiration != time_point::max())
|
||||
scheduler.add(expiration, std::bind(&Dht::expireStorage, this, id));
|
||||
auto expiration = s->second.refresh(id, now, vid, types);
|
||||
if (expiration.first) {
|
||||
scheduler.cancel(expiration.first->expiration_job);
|
||||
if (expiration.second != time_point::max()) {
|
||||
expiration.first->expiration_job = scheduler.add(expiration.second, std::bind(&Dht::expireStorage, this, id));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
+19
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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>
|
||||
@@ -22,10 +22,14 @@
|
||||
#include "dhtrunner.h"
|
||||
#include "op_cache.h"
|
||||
#include "utils.h"
|
||||
#ifdef __APPLE__
|
||||
#include "compat/apple/apple_utils.h"
|
||||
#endif
|
||||
|
||||
#include <http_parser.h>
|
||||
#include <deque>
|
||||
|
||||
|
||||
namespace dht {
|
||||
|
||||
struct DhtProxyClient::InfoState {
|
||||
@@ -41,15 +45,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 {
|
||||
@@ -720,7 +724,8 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
}
|
||||
auto newStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
if (newStatus == NodeStatus::Connected) {
|
||||
if (oldStatus == NodeStatus::Disconnected || oldStatus == NodeStatus::Connecting) {
|
||||
if (oldStatus == NodeStatus::Disconnected || oldStatus == NodeStatus::Connecting || launchConnectedCbs_) {
|
||||
launchConnectedCbs_ = false;
|
||||
listenerRestartTimer_->expires_at(std::chrono::steady_clock::now());
|
||||
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this, std::placeholders::_1));
|
||||
if (not onConnectCallbacks_.empty()) {
|
||||
@@ -813,6 +818,7 @@ 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
|
||||
@@ -825,17 +831,13 @@ 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
|
||||
method = ListenMethod::LISTEN;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
header.method(restinio::method_listen);
|
||||
header.request_target("/" + key.toString());
|
||||
#else
|
||||
header.method(restinio::http_method_get());
|
||||
header.request_target("/key/" + key.toString() + "/listen");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
method = ListenMethod::SUBSCRIBE;
|
||||
@@ -1151,13 +1153,8 @@ DhtProxyClient::restartListeners(const asio::error_code &ec)
|
||||
auto cb = listener.cb;
|
||||
// define header
|
||||
restinio::http_request_header_t header;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
header.method(restinio::method_listen);
|
||||
header.request_target("/" + search.first.toString());
|
||||
#else
|
||||
header.method(restinio::http_method_get());
|
||||
header.request_target("/key/" + search.first.toString() + "/listen");
|
||||
#endif
|
||||
sendListen(header, cb, opstate, listener, ListenMethod::LISTEN);
|
||||
}
|
||||
}
|
||||
@@ -1170,6 +1167,9 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
{
|
||||
// If a push notification is received, the proxy is up and running
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
if (oldStatus != NodeStatus::Connected)
|
||||
launchConnectedCbs_ = true;
|
||||
statusIpv4_ = NodeStatus::Connected;
|
||||
statusIpv6_ = NodeStatus::Connected;
|
||||
}
|
||||
@@ -1235,7 +1235,7 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
|
||||
ids.emplace_back(std::stoull(substr));
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard<std::mutex> lockCb(lockCallbacks_);
|
||||
callbacks_.emplace_back([this, key, token, opstate, ids, sendTime]() {
|
||||
if (opstate->stop)
|
||||
return;
|
||||
@@ -1275,11 +1275,7 @@ DhtProxyClient::resubscribe(const InfoHash& key, const size_t token, Listener& l
|
||||
logger_->d("[proxy:client] [resubscribe] [search %s]", key.to_c_str());
|
||||
|
||||
auto opstate = listener.opstate;
|
||||
opstate->stop = true;
|
||||
if (listener.request){
|
||||
listener.request.reset();
|
||||
}
|
||||
opstate->stop = false;
|
||||
listener.request.reset(); // This will update ok to false
|
||||
opstate->ok = true;
|
||||
|
||||
restinio::http_request_header_t header;
|
||||
@@ -1311,7 +1307,8 @@ DhtProxyClient::getPushRequest(Json::Value& body) const
|
||||
body["platform"] = "android";
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
body["platform"] = "apple";
|
||||
body["topic"] = notificationTopic_;
|
||||
body["platform"] = apple_utils::getPlatformVersion();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+90
-92
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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,26 +38,7 @@
|
||||
|
||||
using namespace std::placeholders;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
namespace restinio {
|
||||
struct custom_http_methods_t
|
||||
{
|
||||
static constexpr restinio::http_method_id_t from_nodejs(int m) noexcept {
|
||||
if(m == method_listen.raw_id())
|
||||
return method_listen;
|
||||
else if(m == method_stats.raw_id())
|
||||
return method_stats;
|
||||
else if(m == method_sign.raw_id())
|
||||
return method_sign;
|
||||
else if(m == method_encrypt.raw_id())
|
||||
return method_encrypt;
|
||||
else
|
||||
return restinio::default_http_methods_t::from_nodejs(m);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
using namespace std::literals;
|
||||
|
||||
namespace dht {
|
||||
constexpr char RESP_MSG_JSON_INCORRECT[] = "{\"err:\":\"Incorrect JSON\"}";
|
||||
@@ -119,7 +100,7 @@ class DhtProxyServer::ConnectionListener
|
||||
{
|
||||
public:
|
||||
ConnectionListener() {};
|
||||
ConnectionListener(std::function<void(restinio::connection_id_t)> onClosed) : onClosed_(std::move(onClosed)) {};
|
||||
explicit ConnectionListener(std::function<void(restinio::connection_id_t)> onClosed) : onClosed_(std::move(onClosed)) {};
|
||||
~ConnectionListener() {};
|
||||
|
||||
/**
|
||||
@@ -156,9 +137,6 @@ DhtProxyServer::onConnectionClosed(restinio::connection_id_t id)
|
||||
struct DhtProxyServer::RestRouterTraitsTls : public restinio::default_tls_traits_t
|
||||
{
|
||||
using timer_manager_t = restinio::asio_timer_manager_t;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
using http_methods_mapper_t = restinio::custom_http_methods_t;
|
||||
#endif
|
||||
using logger_t = opendht_logger_t;
|
||||
using request_handler_t = RestRouter;
|
||||
using connection_state_listener_t = ConnectionListener;
|
||||
@@ -166,9 +144,6 @@ struct DhtProxyServer::RestRouterTraitsTls : public restinio::default_tls_traits
|
||||
struct DhtProxyServer::RestRouterTraits : public restinio::default_traits_t
|
||||
{
|
||||
using timer_manager_t = restinio::asio_timer_manager_t;
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
using http_methods_mapper_t = restinio::custom_http_methods_t;
|
||||
#endif
|
||||
using logger_t = opendht_logger_t;
|
||||
using request_handler_t = RestRouter;
|
||||
using connection_state_listener_t = ConnectionListener;
|
||||
@@ -177,25 +152,25 @@ struct DhtProxyServer::RestRouterTraits : public restinio::default_traits_t
|
||||
void
|
||||
DhtProxyServer::PermanentPut::msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (auto cid = findMapValue(o, "cid")) {
|
||||
if (auto cid = findMapValue(o, "cid"sv)) {
|
||||
clientId = cid->as<std::string>();
|
||||
}
|
||||
if (auto exp = findMapValue(o, "exp")) {
|
||||
if (auto exp = findMapValue(o, "exp"sv)) {
|
||||
expiration = from_time_t(exp->as<time_t>());
|
||||
}
|
||||
if (auto token = findMapValue(o, "token")) {
|
||||
if (auto token = findMapValue(o, "token"sv)) {
|
||||
pushToken = token->as<std::string>();
|
||||
}
|
||||
if (auto sid = findMapValue(o, "sid")) {
|
||||
if (auto sid = findMapValue(o, "sid"sv)) {
|
||||
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")) {
|
||||
if (auto t = findMapValue(o, "t"sv)) {
|
||||
type = t->as<PushType>();
|
||||
}
|
||||
if (auto val = findMapValue(o, "value")) {
|
||||
if (auto val = findMapValue(o, "value"sv)) {
|
||||
value = std::make_shared<dht::Value>(*val);
|
||||
}
|
||||
}
|
||||
@@ -204,19 +179,19 @@ DhtProxyServer::PermanentPut::msgpack_unpack(const msgpack::object& o)
|
||||
void
|
||||
DhtProxyServer::Listener::msgpack_unpack(const msgpack::object& o)
|
||||
{
|
||||
if (auto cid = findMapValue(o, "cid")) {
|
||||
if (auto cid = findMapValue(o, "cid"sv)) {
|
||||
clientId = cid->as<std::string>();
|
||||
}
|
||||
if (auto exp = findMapValue(o, "exp")) {
|
||||
if (auto exp = findMapValue(o, "exp"sv)) {
|
||||
expiration = from_time_t(exp->as<time_t>());
|
||||
}
|
||||
if (auto sid = findMapValue(o, "sid")) {
|
||||
if (auto sid = findMapValue(o, "sid"sv)) {
|
||||
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")) {
|
||||
if (auto t = findMapValue(o, "t"sv)) {
|
||||
type = t->as<PushType>();
|
||||
}
|
||||
}
|
||||
@@ -371,7 +346,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")) {
|
||||
if (auto puts = findMapValue(oh.get(), "puts"sv)) {
|
||||
std::lock_guard<std::mutex> lock(lockSearchPuts_);
|
||||
puts_ = puts->as<decltype(puts_)>();
|
||||
if (logger_)
|
||||
@@ -397,7 +372,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));
|
||||
std::placeholders::_1, pput.second.pushToken, std::move(jsonProvider), pput.second.type, pput.second.topic));
|
||||
}
|
||||
#endif
|
||||
dht_->put(put.first, pput.second.value, DoneCallbackSimple{}, time_point::max(), true);
|
||||
@@ -408,16 +383,16 @@ DhtProxyServer::loadState(Is& is, size_t size) {
|
||||
logger_->d("No persistent puts in state");
|
||||
}
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
if (auto listeners = findMapValue(oh.get(), "pushListeners")) {
|
||||
if (auto pushListeners = findMapValue(oh.get(), "pushListeners"sv)) {
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
pushListeners_ = listeners->as<decltype(pushListeners_)>();
|
||||
pushListeners_ = pushListeners->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]
|
||||
[this, infoHash=listeners.first, pushToken=pushListener.first, type=listener.type, clientId=listener.clientId, sessionCtx = listener.sessionCtx, topic=listener.topic]
|
||||
(const std::vector<std::shared_ptr<Value>>& values, bool expired) {
|
||||
// Build message content
|
||||
Json::Value json;
|
||||
@@ -439,7 +414,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);
|
||||
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -454,7 +429,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));
|
||||
std::placeholders::_1, pushListener.first, std::move(jsonProvider), listener.type, listener.topic));
|
||||
// cancel push listen
|
||||
listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), listener.expiration);
|
||||
listener.expireTimer->async_wait(std::bind(&DhtProxyServer::handleCancelPushListen, this,
|
||||
@@ -613,11 +588,6 @@ DhtProxyServer::createRestRouter()
|
||||
// **************************** LEGACY ROUTES ****************************
|
||||
// node.info
|
||||
router->http_get("/", std::bind(&DhtProxyServer::getNodeInfo, this, _1, _2));
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// node.stats
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_stats.raw_id()),
|
||||
"/", std::bind(&DhtProxyServer::getStats, this, _1, _2));
|
||||
#endif
|
||||
// key.options
|
||||
router->add_handler(restinio::http_method_options(),
|
||||
"/:hash", std::bind(&DhtProxyServer::options, this, _1, _2));
|
||||
@@ -625,11 +595,6 @@ DhtProxyServer::createRestRouter()
|
||||
router->http_get("/:hash", std::bind(&DhtProxyServer::get, this, _1, _2));
|
||||
// key.post
|
||||
router->http_post("/:hash", std::bind(&DhtProxyServer::put, this, _1, _2));
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// key.listen
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_listen.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::listen, this, _1, _2));
|
||||
#endif
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
// key.subscribe
|
||||
router->add_handler(restinio::http_method_subscribe(),
|
||||
@@ -639,14 +604,6 @@ DhtProxyServer::createRestRouter()
|
||||
"/:hash", std::bind(&DhtProxyServer::unsubscribe, this, _1, _2));
|
||||
#endif //OPENDHT_PUSH_NOTIFICATIONS
|
||||
#ifdef OPENDHT_PROXY_SERVER_IDENTITY
|
||||
#ifdef OPENDHT_PROXY_HTTP_PARSER_FORK
|
||||
// key.sign
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_sign.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::putSigned, this, _1, _2));
|
||||
// key.encrypt
|
||||
router->add_handler(restinio::custom_http_methods_t::from_nodejs(restinio::method_encrypt.raw_id()),
|
||||
"/:hash", std::bind(&DhtProxyServer::putEncrypted, this, _1, _2));
|
||||
#endif
|
||||
#endif // OPENDHT_PROXY_SERVER_IDENTITY
|
||||
|
||||
// **************************** NEW ROUTES ****************************
|
||||
@@ -727,9 +684,9 @@ DhtProxyServer::get(restinio::request_handle_t request,
|
||||
{
|
||||
requestNum_++;
|
||||
try {
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
auto response = std::make_shared<ResponseByPartsBuilder>(
|
||||
initHttpResponse(request->create_response<ResponseByParts>()));
|
||||
response->flush();
|
||||
@@ -758,9 +715,9 @@ DhtProxyServer::listen(restinio::request_handle_t request,
|
||||
requestNum_++;
|
||||
|
||||
try {
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
auto response = std::make_shared<ResponseByPartsBuilder>(
|
||||
initHttpResponse(request->create_response<ResponseByParts>()));
|
||||
response->flush();
|
||||
@@ -788,15 +745,30 @@ DhtProxyServer::listen(restinio::request_handle_t request,
|
||||
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
PushType
|
||||
DhtProxyServer::getTypeFromString(const std::string& type) {
|
||||
if (type == "android") {
|
||||
return PushType::Android;
|
||||
}
|
||||
if (type == "apple") {
|
||||
// proxy_client is not updated or using ios < 14.5
|
||||
return PushType::iOSLegacy;
|
||||
}
|
||||
if (type == "ios") {
|
||||
return PushType::iOS;
|
||||
}
|
||||
return PushType::None;
|
||||
}
|
||||
|
||||
RequestStatus
|
||||
DhtProxyServer::subscribe(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params)
|
||||
{
|
||||
requestNum_++;
|
||||
try {
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
std::string err;
|
||||
Json::Value r;
|
||||
@@ -814,7 +786,8 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
|
||||
response.set_body(RESP_MSG_NO_TOKEN);
|
||||
return response.done();
|
||||
}
|
||||
auto type = root["platform"].asString() == "android" ? PushType::Android : PushType::iOS;
|
||||
auto type = getTypeFromString(root["platform"].asString());
|
||||
auto topic = root["topic"].asString();
|
||||
auto clientId = root["client_id"].asString();
|
||||
auto sessionId = root["session_id"].asString();
|
||||
|
||||
@@ -845,6 +818,7 @@ 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
|
||||
@@ -858,7 +832,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));
|
||||
std::placeholders::_1, pushToken, std::move(jsonProvider), listener.type, listener.topic));
|
||||
if (!listener.expireTimer)
|
||||
listener.expireTimer = std::make_unique<asio::steady_timer>(io_context(), timeout);
|
||||
else
|
||||
@@ -893,7 +867,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]
|
||||
[this, infoHash, pushToken, type, clientId, sessionCtx = listener.sessionCtx, topic]
|
||||
(const std::vector<std::shared_ptr<Value>>& values, bool expired){
|
||||
// Build message content
|
||||
Json::Value json;
|
||||
@@ -915,7 +889,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);
|
||||
sendPushNotification(pushToken, std::move(json), type, !expired and maxPrio == 0, topic);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
@@ -936,9 +910,9 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
|
||||
{
|
||||
requestNum_++;
|
||||
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
if (logger_)
|
||||
logger_->d("[proxy:server] [unsubscribe %s]", infoHash.toString().c_str());
|
||||
@@ -971,7 +945,7 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
|
||||
|
||||
void
|
||||
DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const std::string pushToken,
|
||||
std::function<Json::Value()> jsonProvider, PushType type)
|
||||
std::function<Json::Value()> jsonProvider, PushType type, const std::string& topic)
|
||||
{
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
@@ -981,7 +955,7 @@ DhtProxyServer::handleNotifyPushListenExpire(const asio::error_code &ec, const s
|
||||
}
|
||||
if (logger_)
|
||||
logger_->d("[proxy:server] [subscribe] sending put refresh to %s token", pushToken.c_str());
|
||||
sendPushNotification(pushToken, jsonProvider(), type, false);
|
||||
sendPushNotification(pushToken, jsonProvider(), type, false, topic);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1023,7 +997,7 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority)
|
||||
DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority, const std::string& topic)
|
||||
{
|
||||
if (pushServer_.empty())
|
||||
return;
|
||||
@@ -1048,7 +1022,29 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
|
||||
notification["platform"] = type == PushType::Android ? 2 : 1;
|
||||
notification["data"] = std::move(json);
|
||||
notification["priority"] = highPriority ? "high" : "normal";
|
||||
notification["time_to_live"] = 600;
|
||||
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 (type == PushType::iOS) {
|
||||
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;
|
||||
}
|
||||
} else if (type == PushType::iOSLegacy) {
|
||||
notification["push_type"] = "voip";
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value notifications(Json::arrayValue);
|
||||
notifications[0] = notification;
|
||||
@@ -1118,9 +1114,9 @@ DhtProxyServer::put(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params)
|
||||
{
|
||||
requestNum_++;
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
if (request->body().empty()){
|
||||
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
|
||||
@@ -1141,13 +1137,14 @@ 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;
|
||||
std::string pushToken, clientId, sessionId, platform, topic;
|
||||
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;
|
||||
@@ -1190,7 +1187,8 @@ DhtProxyServer::put(restinio::request_handle_t request,
|
||||
bool isAndroid = platform == "android";
|
||||
pput.pushToken = pushToken;
|
||||
pput.clientId = clientId;
|
||||
pput.type = isAndroid ? PushType::Android : PushType::iOS;
|
||||
pput.type = getTypeFromString(platform);
|
||||
pput.topic = topic;
|
||||
pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
|
||||
// notify push listen expire
|
||||
auto jsonProvider = [infoHash, clientId, vid, sessionCtx = pput.sessionCtx](){
|
||||
@@ -1209,7 +1207,7 @@ DhtProxyServer::put(restinio::request_handle_t request,
|
||||
pput.expireNotifyTimer->expires_at(timeout - proxy::OP_MARGIN);
|
||||
pput.expireNotifyTimer->async_wait(std::bind(
|
||||
&DhtProxyServer::handleNotifyPushListenExpire, this,
|
||||
std::placeholders::_1, pushToken, std::move(jsonProvider), pput.type));
|
||||
std::placeholders::_1, pushToken, std::move(jsonProvider), pput.type, pput.topic));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
@@ -1259,9 +1257,9 @@ DhtProxyServer::putSigned(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params) const
|
||||
{
|
||||
requestNum_++;
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
if (request->body().empty()){
|
||||
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
|
||||
@@ -1309,9 +1307,9 @@ DhtProxyServer::putEncrypted(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params)
|
||||
{
|
||||
requestNum_++;
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
if (request->body().empty()){
|
||||
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
|
||||
@@ -1381,10 +1379,10 @@ DhtProxyServer::getFiltered(restinio::request_handle_t request,
|
||||
restinio::router::route_params_t params)
|
||||
{
|
||||
requestNum_++;
|
||||
auto value = params["value"].to_string();
|
||||
InfoHash infoHash(params["hash"].to_string());
|
||||
auto query = params["value"];
|
||||
InfoHash infoHash(params["hash"]);
|
||||
if (!infoHash)
|
||||
infoHash = InfoHash::get(params["hash"].to_string());
|
||||
infoHash = InfoHash::get(params["hash"]);
|
||||
|
||||
try {
|
||||
auto response = std::make_shared<ResponseByPartsBuilder>(
|
||||
@@ -1399,7 +1397,7 @@ DhtProxyServer::getFiltered(restinio::request_handle_t request,
|
||||
[response] (bool /*ok*/){
|
||||
response->done();
|
||||
},
|
||||
{}, value);
|
||||
{}, query);
|
||||
return restinio::request_handling_status_t::accepted;
|
||||
} catch (const std::exception& e){
|
||||
return serverError(*request);
|
||||
|
||||
+187
-245
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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>
|
||||
@@ -36,18 +36,8 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
constexpr std::chrono::seconds DhtRunner::BOOTSTRAP_PERIOD;
|
||||
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;
|
||||
@@ -56,9 +46,6 @@ struct NodeInsertionPack {
|
||||
};
|
||||
|
||||
DhtRunner::DhtRunner() : dht_()
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
, dht_via_proxy_()
|
||||
#endif //OPENDHT_PROXY_CLIENT
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsd;
|
||||
@@ -106,91 +93,98 @@ 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.");
|
||||
context.logger->w("[runner %p] Node is already running. Call join() first before calling run() again.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
auto local4 = config.bind4;
|
||||
auto local6 = config.bind6;
|
||||
if (not local4 and not local6) {
|
||||
if (context.logger)
|
||||
context.logger->w("[runner %p] No address to bind specified in the configuration, using default addresses");
|
||||
local4.setFamily(AF_INET);
|
||||
local6.setFamily(AF_INET6);
|
||||
}
|
||||
auto state_path = config.dht_config.node_config.persist_path;
|
||||
if (not state_path.empty() && (local4.getPort() == 0 || local6.getPort() == 0)) {
|
||||
state_path += "_port.txt";
|
||||
std::ifstream inConfig(state_path);
|
||||
if (inConfig.is_open()) {
|
||||
in_port_t port;
|
||||
if (inConfig >> port) {
|
||||
if (local4.getPort() == 0) {
|
||||
if (context.logger)
|
||||
context.logger->d("[runner %p] Using IPv4 port %hu from saved configuration", this, port);
|
||||
local4.setPort(port);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 (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);
|
||||
if (context.logger) {
|
||||
logger_ = context.logger;
|
||||
logger_->d("[runner %p] state changed to Running", this);
|
||||
}
|
||||
cv.notify_all();
|
||||
return ret;
|
||||
});
|
||||
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
config_ = config;
|
||||
identityAnnouncedCb_ = context.identityAnnouncedCb;
|
||||
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 (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 (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)
|
||||
@@ -273,7 +267,8 @@ 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) {
|
||||
shutdownCallbacks_.emplace_back(std::move(cb));
|
||||
if (cb)
|
||||
shutdownCallbacks_.emplace_back(std::move(cb));
|
||||
}
|
||||
else if (cb) {
|
||||
lck.unlock();
|
||||
@@ -287,12 +282,10 @@ 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();
|
||||
}
|
||||
@@ -395,23 +388,25 @@ void
|
||||
DhtRunner::dumpTables() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
activeDht()->dumpTables();
|
||||
dht_->dumpTables();
|
||||
}
|
||||
|
||||
InfoHash
|
||||
DhtRunner::getId() const
|
||||
{
|
||||
if (auto dht = activeDht())
|
||||
return dht->getId();
|
||||
return {};
|
||||
return dht_ ? dht_->getId() : InfoHash{};
|
||||
}
|
||||
|
||||
std::shared_ptr<crypto::PublicKey>
|
||||
DhtRunner::getPublicKey() const
|
||||
{
|
||||
return dht_ ? dht_->getPublicKey() : std::shared_ptr<crypto::PublicKey>{};
|
||||
}
|
||||
|
||||
InfoHash
|
||||
DhtRunner::getNodeId() const
|
||||
{
|
||||
if (auto dht = activeDht())
|
||||
return dht->getNodeId();
|
||||
return {};
|
||||
return dht_ ? dht_->getNodeId() : InfoHash{};
|
||||
}
|
||||
|
||||
|
||||
@@ -453,10 +448,6 @@ 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
|
||||
@@ -470,16 +461,12 @@ 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);
|
||||
activeDht()->registerType(type);
|
||||
dht_->registerType(type);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -492,7 +479,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 = activeDht()->getNodesStats(af);
|
||||
const auto stats = dht_->getNodesStats(af);
|
||||
if (good_return)
|
||||
*good_return = stats.good_nodes;
|
||||
if (dubious_return)
|
||||
@@ -508,19 +495,19 @@ NodeStats
|
||||
DhtRunner::getNodesStats(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getNodesStats(af);
|
||||
return dht_->getNodesStats(af);
|
||||
}
|
||||
|
||||
NodeInfo
|
||||
DhtRunner::getNodeInfo() const {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
NodeInfo info {};
|
||||
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()) {
|
||||
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()) {
|
||||
info.bound4 = sock->getBoundRef(AF_INET).getPort();
|
||||
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
|
||||
}
|
||||
@@ -541,6 +528,7 @@ DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
|
||||
info.node_id = dht.getNodeId();
|
||||
info.ipv4 = dht.getNodesStats(AF_INET);
|
||||
info.ipv6 = dht.getNodesStats(AF_INET6);
|
||||
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();
|
||||
@@ -556,49 +544,49 @@ std::vector<unsigned>
|
||||
DhtRunner::getNodeMessageStats(bool in) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getNodeMessageStats(in);
|
||||
return dht_->getNodeMessageStats(in);
|
||||
}
|
||||
|
||||
std::string
|
||||
DhtRunner::getStorageLog() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getStorageLog();
|
||||
return dht_->getStorageLog();
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getStorageLog(const InfoHash& f) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getStorageLog(f);
|
||||
return dht_->getStorageLog(f);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getRoutingTablesLog(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getRoutingTablesLog(af);
|
||||
return dht_->getRoutingTablesLog(af);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getSearchesLog(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getSearchesLog(af);
|
||||
return dht_->getSearchesLog(af);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getSearchLog(const InfoHash& f, sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
return activeDht()->getSearchLog(f, af);
|
||||
return dht_->getSearchLog(f, af);
|
||||
}
|
||||
std::vector<SockAddr>
|
||||
DhtRunner::getPublicAddress(sa_family_t af)
|
||||
DhtRunner::getPublicAddress(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (auto dht = activeDht())
|
||||
return dht->getPublicAddress(af);
|
||||
if (dht_)
|
||||
return dht_->getPublicAddress(af);
|
||||
return {};
|
||||
}
|
||||
std::vector<std::string>
|
||||
DhtRunner::getPublicAddressStr(sa_family_t af)
|
||||
DhtRunner::getPublicAddressStr(sa_family_t af) const
|
||||
{
|
||||
auto addrs = getPublicAddress(af);
|
||||
std::vector<std::string> ret(addrs.size());
|
||||
@@ -621,15 +609,12 @@ 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);
|
||||
activeDht()->registerCertificate(cert);
|
||||
dht_->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));
|
||||
}
|
||||
@@ -637,8 +622,7 @@ DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method) {
|
||||
time_point
|
||||
DhtRunner::loop_()
|
||||
{
|
||||
auto dht = activeDht();
|
||||
if (not dht)
|
||||
if (not dht_)
|
||||
return {};
|
||||
|
||||
decltype(pending_ops) ops {};
|
||||
@@ -649,7 +633,7 @@ DhtRunner::loop_()
|
||||
std::move(pending_ops) : std::move(pending_ops_prio);
|
||||
}
|
||||
while (not ops.empty()) {
|
||||
ops.front()(*dht);
|
||||
ops.front()(*dht_);
|
||||
ops.pop();
|
||||
}
|
||||
|
||||
@@ -682,13 +666,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()) {
|
||||
@@ -697,11 +681,11 @@ DhtRunner::loop_()
|
||||
rcv_free.splice(rcv_free.end(), std::move(received_treated));
|
||||
}
|
||||
|
||||
if (dropped)
|
||||
std::cerr << "Dropped " << dropped << " packets with high delay" << std::endl;
|
||||
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;
|
||||
@@ -759,27 +743,7 @@ 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();
|
||||
@@ -795,21 +759,13 @@ void
|
||||
DhtRunner::cancelListen(InfoHash h, size_t token)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
#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
|
||||
if (running != State::Running)
|
||||
return;
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=](SecureDht& dht) {
|
||||
dht.cancelListen(h, token);
|
||||
opEnded();
|
||||
});
|
||||
#endif // OPENDHT_PROXY_CLIENT
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
@@ -817,21 +773,13 @@ void
|
||||
DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
#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) {
|
||||
if (running != State::Running)
|
||||
return;
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([this, h, ftoken = std::move(ftoken)](SecureDht& dht) {
|
||||
dht.cancelListen(h, ftoken.get());
|
||||
opEnded();
|
||||
});
|
||||
#endif // OPENDHT_PROXY_CLIENT
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
@@ -864,7 +812,7 @@ DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, tim
|
||||
return;
|
||||
}
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=, cb = std::move(cb)](SecureDht& dht) mutable {
|
||||
pending_ops.emplace([=, value = std::move(value), cb = std::move(cb)](SecureDht& dht) mutable {
|
||||
dht.put(hash, value, bindOpDoneCallback(std::move(cb)), created, permanent);
|
||||
});
|
||||
cv.notify_all();
|
||||
@@ -958,6 +906,31 @@ DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, Done
|
||||
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb) cb(false, {});
|
||||
return;
|
||||
}
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([=,
|
||||
cb = std::move(cb),
|
||||
value = std::move(value)
|
||||
] (SecureDht& dht) mutable {
|
||||
dht.putEncrypted(hash, *to, value, bindOpDoneCallback(std::move(cb)), permanent);
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::bootstrap(const std::string& host, const std::string& service)
|
||||
{
|
||||
@@ -989,7 +962,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);
|
||||
@@ -1019,7 +992,7 @@ DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple&& cb)
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb)
|
||||
DhtRunner::bootstrap(SockAddr addr, DoneCallbackSimple cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
@@ -1028,7 +1001,7 @@ DhtRunner::bootstrap(const SockAddr& addr, DoneCallbackSimple&& cb)
|
||||
return;
|
||||
}
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([addr, cb = bindOpDoneCallback(std::move(cb))](SecureDht& dht) mutable {
|
||||
pending_ops_prio.emplace([addr = std::move(addr), cb = bindOpDoneCallback(std::move(cb))](SecureDht& dht) mutable {
|
||||
dht.pingNode(std::move(addr), std::move(cb));
|
||||
});
|
||||
cv.notify_all();
|
||||
@@ -1047,12 +1020,12 @@ DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::bootstrap(const std::vector<NodeExport>& nodes)
|
||||
DhtRunner::bootstrap(std::vector<NodeExport> nodes)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
pending_ops_prio.emplace([=](SecureDht& dht) {
|
||||
pending_ops_prio.emplace([nodes = std::move(nodes)](SecureDht& dht) {
|
||||
for (auto& node : nodes)
|
||||
dht.insertNode(node);
|
||||
});
|
||||
@@ -1095,23 +1068,9 @@ 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)
|
||||
{
|
||||
@@ -1124,7 +1083,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())
|
||||
std::cerr << "DHT proxy requested but OpenDHT built without proxy support." << std::endl;
|
||||
throw std::runtime_error("DHT proxy requested but OpenDHT built without proxy support.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1132,54 +1091,35 @@ void
|
||||
DhtRunner::enableProxy(bool proxify)
|
||||
{
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
if (dht_via_proxy_) {
|
||||
dht_via_proxy_->shutdown({});
|
||||
if (dht_) {
|
||||
dht_->shutdown({});
|
||||
}
|
||||
if (proxify) {
|
||||
// Init the proxy client
|
||||
auto dht_via_proxy = std::unique_ptr<DhtInterface>(
|
||||
new DhtProxyClient(
|
||||
auto dht_via_proxy = std::make_unique<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_)
|
||||
);
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
config_.proxy_server, config_.push_node_id, logger_);
|
||||
if (not config_.push_token.empty())
|
||||
dht_via_proxy->setPushNotificationToken(config_.push_token);
|
||||
#endif
|
||||
dht_via_proxy_ = std::unique_ptr<SecureDht>(new SecureDht(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_));
|
||||
// add current listeners
|
||||
for (auto& l: listeners_)
|
||||
l.second.tokenProxyDht = dht_via_proxy_->listen(l.second.hash, l.second.gcb, l.second.f, l.second.w);
|
||||
if (not config_.push_topic.empty())
|
||||
dht_via_proxy->setPushNotificationTopic(config_.push_topic);
|
||||
dht_ = std::make_unique<SecureDht>(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_);
|
||||
// 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)
|
||||
std::cerr << "DHT proxy requested but OpenDHT built without proxy support." << std::endl;
|
||||
throw std::runtime_error("DHT proxy requested but OpenDHT built without proxy support.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1187,16 +1127,8 @@ 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
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1207,24 +1139,34 @@ 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_via_proxy_)
|
||||
dht_via_proxy_->setPushNotificationToken(token);
|
||||
if (dht_)
|
||||
dht_->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::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_via_proxy_)
|
||||
dht_via_proxy_->pushNotificationReceived(data);
|
||||
});
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht&) {
|
||||
if (dht_)
|
||||
dht_->pushNotificationReceived(data);
|
||||
});
|
||||
cv.notify_all();
|
||||
#else
|
||||
(void) data;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2022 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>
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Savoir-faire Linux Inc.
|
||||
* 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
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <sstream>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace dht {
|
||||
|
||||
const HexMap hex_map = {};
|
||||
@@ -33,9 +35,9 @@ NodeExport::msgpack_unpack(msgpack::object o)
|
||||
throw msgpack::type_error();
|
||||
if (o.via.map.size < 2)
|
||||
throw msgpack::type_error();
|
||||
if (o.via.map.ptr[0].key.as<std::string>() != "id")
|
||||
if (o.via.map.ptr[0].key.as<std::string_view>() != "id"sv)
|
||||
throw msgpack::type_error();
|
||||
if (o.via.map.ptr[1].key.as<std::string>() != "addr")
|
||||
if (o.via.map.ptr[1].key.as<std::string_view>() != "addr"sv)
|
||||
throw msgpack::type_error();
|
||||
const auto& addr = o.via.map.ptr[1].val;
|
||||
if (addr.type != msgpack::type::BIN)
|
||||
|
||||
Loaded 100 of 148 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user