Compare commits

..
32 Commits
Author SHA1 Message Date
Adrien Béraud fb38ba8a6f build/dev: cleanup launch.json 2022-04-12 15:24:17 -04:00
Adrien Béraud a1d0273514 docker: install libtool 2022-04-12 15:24:17 -04:00
Adrien Béraud a1da0af78c c: update dhtcnode 2022-04-12 15:24:17 -04:00
Adrien Béraud 6d95f7a181 c: support log to stdout/stderr 2022-04-12 15:23:45 -04:00
Adrien Béraud 76097b0da2 c: support building with autotools 2022-04-11 17:18:30 -04:00
Adrien Béraud 7dc5aa9dfd build/dev: build in build_dev 2022-04-06 12:19:11 -04:00
Adrien Béraud 808eb688b3 tests: wait for put callback before retrieving certificate 2022-04-06 12:18:42 -04:00
Adrien Béraud 12b75a612c misc: fix various clang-tidy warnings 2022-04-06 12:18:20 -04:00
Sprite ac79dc5761 cmake: fix incorrectly linking to libatomic on macOS 2022-04-03 20:44:23 -04:00
Adrien Béraud fe6676f2e6 unit tests: run on pull request 2022-04-03 20:23:37 -04:00
Adrien Béraud 7915b987ec misc: use more string_view 2022-04-02 17:14:36 -04:00
Adrien Béraud 29bdc1a46f Revert "cmake: check atomic for RISC-V architecture"
Reason for partial revert:
Adding the atomic library is meant by CheckAtomic
to be automatic through CMAKE_REQUIRED_LIBRARIES.
2022-04-01 19:35:15 -04:00
Adrien Béraud e0d32e80fb build/dev: use gdb on linux, llvm on macOS with vscode tasks 2022-04-01 19:17:44 -04:00
Sprite e753d200c6 cmake: fix incorrect variable name 2022-04-01 11:30:47 -04:00
Sprite 85fd395c52 cmake: simplify atomic checks 2022-04-01 11:30:47 -04:00
Sprite 0f146a354b cmake: check atomic for RISC-V architecture 2022-04-01 11:30:47 -04:00
Adrien Béraud 9fcaca9232 build/dev: add tests to vscode tasks 2022-04-01 11:09:01 -04:00
Adrien Béraud 1bc65bc5f5 network engine: use string_view for better performance 2022-04-01 11:04:59 -04:00
Adrien Béraud 478d28a326 dhtnode: display total count of values for get and listen 2022-03-30 17:56:39 -04:00
Adrien Béraud 4d544d53a8 ci: use scan-build with debug mode 2022-03-29 15:07:24 -04:00
Adrien Béraud 694c44bbec value: use namespace std::literals 2022-03-29 14:54:59 -04:00
Adrien Béraud 16915ff424 build/dev: add vscode devcontainer and dhtnode task 2022-03-29 14:47:42 -04:00
Adrien Béraud a22566599c proxy client: fix building Listener map 2022-03-29 14:47:42 -04:00
Adrien Béraud f9b2285593 use string view literals where relevant 2022-03-29 14:47:01 -04:00
Adrien Béraud 9c2268fa41 fix various cppcheck warnings/errors 2022-03-29 10:15:00 -04:00
Adrien Béraud d4e6fd545a search: use const for iterator comparison 2022-03-24 21:33:51 -04:00
Adrien Béraud dfd0a09361 ci/github: add Clang static analysis 2022-03-23 18:32:26 -04:00
Adrien Béraud 0afa40820a autotools: update m4 for C++17 2022-03-23 17:49:14 -04:00
Adrien Béraud f984a6a69a ci/github: update to checkout@v3 2022-03-23 17:25:23 -04:00
Adrien Béraud b4bbc6ae38 update readme 2022-03-23 15:43:31 -04:00
Adrien Béraud bc98d974cb ci: remove travis 2022-03-23 15:43:24 -04:00
Adrien Béraud 785e54838b docker: fix Bionic (Ubuntu 18.04) support 2022-03-23 15:19:29 -04:00
44 changed files with 687 additions and 325 deletions

No files matched your search

+12
View File
@@ -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],
}
+40 -5
View File
@@ -1,14 +1,13 @@
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 \
@@ -29,3 +28,39 @@ jobs:
run: make
- name: make check
run: make check
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
+35
View File
@@ -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
+1
View File
@@ -76,4 +76,5 @@ doc/Doxyfile
# build dir
build
build_dev
.DS_Store
-67
View File
@@ -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
+54
View File
@@ -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,
},
}
]
}
+44
View File
@@ -0,0 +1,44 @@
{
"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_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"
]
},
]
}
+4
View File
@@ -49,6 +49,10 @@ 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)
+4
View File
@@ -4,6 +4,10 @@ SUBDIRS =
SUBDIRS += src
if ENABLE_C
SUBDIRS += c
endif
if ENABLE_TOOLS
SUBDIRS += tools
endif
+1 -1
View File
@@ -99,7 +99,7 @@ for r in results:
- (optional) restinio used for the REST API.
- (optional) jsoncpp 1.7.4-3+, used for the REST API.
- Build tested with GCC 7+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
- Build tested with Microsoft Visual Studio 2017, 2019, 2021
- Build tested with Microsoft Visual Studio 2017, 2019, 2022
## Contact
+12
View File
@@ -0,0 +1,12 @@
lib_LTLIBRARIES = libopendht-c.la
noinst_HEADERS = opendht_c.h
AM_CPPFLAGS = -isystem @top_srcdir@/include @JsonCpp_CFLAGS@ @MsgPack_CFLAGS@
libopendht_c_la_LIBADD = $(LIBOBJS) ../src/.libs/libopendht.la
libopendht_c_la_SOURCES = \
opendht.cpp
nobase_include_HEADERS = \
opendht_c.h
+9 -2
View File
@@ -17,7 +17,9 @@
*/
#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>;
@@ -333,7 +335,12 @@ int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config
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);
dht::DhtRunner::Context context;
if (conf->log) {
context.logger = dht::log::getStdLogger();
}
runner->run(port, config, std::move(context));
} catch(...) {
return ENOTCONN;
}
+2 -1
View File
@@ -22,7 +22,7 @@
extern "C" {
#endif
#include "def.h"
#include <opendht/def.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdbool.h>
@@ -147,6 +147,7 @@ struct OPENDHT_PUBLIC dht_runner_config {
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);
+19 -22
View File
@@ -2,6 +2,7 @@
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.
@@ -12,8 +13,12 @@ function(check_working_cxx_atomics varname)
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() {
return x;
++z;
++y;
return ++x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
@@ -28,6 +33,7 @@ function(check_working_cxx_atomics64 varname)
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0;
}
" ${varname})
@@ -35,22 +41,18 @@ int main() {
endfunction(check_working_cxx_atomics64)
# This isn't necessary on MSVC, so avoid command-line switch annoyance
# by only running on GCC-like hosts.
if (LLVM_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()
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()
@@ -58,21 +60,16 @@ endif()
# Check for 64 bit atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
else()
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)
endif()
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
if(HAVE_CXX_LIBATOMICS64)
# 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()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")
endif()
endif()
+13
View File
@@ -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()
+8
View File
@@ -32,6 +32,13 @@ AS_IF([test "x$enable_logs" != "xno"], [
AC_DEFINE([OPENDHT_LOG], [false], [Define if DHT logs are enabled])
])
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
AC_ARG_ENABLE([indexation], [AS_HELP_STRING([--disable-indexation], [Disable DHT indexation])])
AM_CONDITIONAL(ENABLE_INDEXATION, test x$enable_indexation != "xno")
@@ -198,6 +205,7 @@ AC_SUBST(PROJECT_BINARY_DIR, "../src/.libs")
AC_CONFIG_FILES([Makefile
src/Makefile
c/Makefile
tools/Makefile
python/Makefile
python/setup.py
+1 -1
View File
@@ -9,7 +9,7 @@ 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 \
+4 -3
View File
@@ -6,6 +6,7 @@ RUN echo "APT::Acquire::Retries \"3\";" > /etc/apt/apt.conf.d/80-retries
RUN apt-get update && apt-get install -y \
apt-transport-https build-essential pkg-config git wget libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
libargon2-0-dev \
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libssl-dev python3-pip \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
@@ -21,9 +22,9 @@ RUN echo "** Building a recent version of asio ***" \
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
&& ls -l && tar -xzf e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
&& cd restinio-e0a261dd8488246a3cb8bbb3ea781ea5139c3c94/dev \
&& wget https://github.com/aberaud/restinio/archive/8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59.tar.gz \
&& ls -l && tar -xzf 8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59.tar.gz \
&& cd restinio-8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59/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 . \
+2 -1
View File
@@ -8,7 +8,8 @@ RUN apt-get update && apt-get install -y \
&& 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 \
+2 -2
View File
@@ -273,13 +273,13 @@ public:
* 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 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(const std::vector<NodeExport>& nodes);
void bootstrap(std::vector<NodeExport> nodes);
/**
* Add host:service to bootstrap nodes, and ping this node.
+10 -10
View File
@@ -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,
+2 -2
View File
@@ -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
+10 -9
View File
@@ -43,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");
@@ -270,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;
};
}
@@ -660,7 +661,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;
@@ -673,9 +674,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:
@@ -697,12 +698,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
@@ -864,7 +865,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));
+59 -5
View File
@@ -10,13 +10,13 @@
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (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
]])
+3 -1
View File
@@ -1057,6 +1057,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));
@@ -1473,7 +1475,7 @@ RevocationList::RevocationList(const Blob& b)
} catch (const std::exception& e) {
gnutls_x509_crl_deinit(crl);
crl = nullptr;
throw e;
throw;
}
}
+6 -4
View File
@@ -41,15 +41,15 @@ struct DhtProxyClient::OperationState {
struct DhtProxyClient::Listener
{
Listener(OpValueCache&& c):
cache(std::move(c))
{}
cache(std::move(c)) {}
unsigned callbackId;
OpValueCache cache;
CacheValueCallback cb;
Sp<OperationState> opstate;
std::shared_ptr<http::Request> request;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
std::unique_ptr<asio::steady_timer> refreshSubscriberTimer;
#endif
};
struct PermanentPut {
@@ -814,6 +814,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
@@ -826,6 +827,7 @@ 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
@@ -1229,7 +1231,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;
+15 -14
View File
@@ -38,6 +38,7 @@
using namespace std::placeholders;
using namespace std::chrono_literals;
using namespace std::literals;
namespace dht {
constexpr char RESP_MSG_JSON_INCORRECT[] = "{\"err:\":\"Incorrect JSON\"}";
@@ -99,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() {};
/**
@@ -151,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);
}
}
@@ -178,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>();
}
}
@@ -345,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_)
@@ -382,9 +383,9 @@ 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_) {
+19 -9
View File
@@ -181,8 +181,8 @@ DhtRunner::run(const Config& config, Context&& context)
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));
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);
enableProxy(not config.proxy_server.empty());
} catch(const std::exception& e) {
config_ = {};
@@ -817,6 +817,9 @@ void
DhtRunner::cancelListen(InfoHash h, size_t token)
{
std::lock_guard<std::mutex> lck(storage_mtx);
if (running != State::Running)
return;
ongoing_ops++;
#ifdef OPENDHT_PROXY_CLIENT
pending_ops.emplace([=](SecureDht&) {
auto it = listeners_.find(token);
@@ -826,10 +829,12 @@ DhtRunner::cancelListen(InfoHash h, size_t token)
if (it->second.tokenProxyDht and dht_via_proxy_)
dht_via_proxy_->cancelListen(h, it->second.tokenProxyDht);
listeners_.erase(it);
opEnded();
});
#else
pending_ops.emplace([=](SecureDht& dht) {
dht.cancelListen(h, token);
opEnded();
});
#endif // OPENDHT_PROXY_CLIENT
cv.notify_all();
@@ -839,8 +844,11 @@ void
DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
{
std::lock_guard<std::mutex> lck(storage_mtx);
if (running != State::Running)
return;
ongoing_ops++;
#ifdef OPENDHT_PROXY_CLIENT
pending_ops.emplace([=](SecureDht&) {
pending_ops.emplace([this, h, ftoken = std::move(ftoken)](SecureDht&) {
auto it = listeners_.find(ftoken.get());
if (it == listeners_.end()) return;
if (it->second.tokenClassicDht)
@@ -848,10 +856,12 @@ DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
if (it->second.tokenProxyDht and dht_via_proxy_)
dht_via_proxy_->cancelListen(h, it->second.tokenProxyDht);
listeners_.erase(it);
opEnded();
});
#else
pending_ops.emplace([=](SecureDht& dht) {
pending_ops.emplace([this, h, ftoken = std::move(ftoken)](SecureDht& dht) {
dht.cancelListen(h, ftoken.get());
opEnded();
});
#endif // OPENDHT_PROXY_CLIENT
cv.notify_all();
@@ -886,7 +896,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();
@@ -1066,7 +1076,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) {
@@ -1075,7 +1085,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();
@@ -1094,12 +1104,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);
});
+4 -2
View File
@@ -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)
+2 -2
View File
@@ -38,7 +38,7 @@ printLog(std::ostream& s, char const *m, va_list args) {
// print log to buffer
std::array<char, 8192> buffer;
int ret = vsnprintf(buffer.data(), buffer.size(), m, args);
if (ret < 0)
if (ret <= 0)
return;
// write timestamp
@@ -89,7 +89,7 @@ std::shared_ptr<Logger>
getSyslogLogger(const char* name) {
#ifndef _WIN32
struct Syslog {
Syslog(const char* n) {
explicit Syslog(const char* n) {
openlog(n, LOG_NDELAY, LOG_USER);
}
~Syslog() {
+20 -20
View File
@@ -116,7 +116,7 @@ NetworkEngine::~NetworkEngine() {
}
void
NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash, want_t want,
NetworkEngine::tellListener(const Sp<Node>& node, Tid socket_id, const InfoHash& hash, want_t want,
const Blob& ntoken, std::vector<Sp<Node>>&& nodes,
std::vector<Sp<Node>>&& nodes6, std::vector<Sp<Value>>&& values,
const Query& query, int version)
@@ -135,7 +135,7 @@ NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash,
}
void
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
NetworkEngine::tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
@@ -186,7 +186,7 @@ NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&,
}
void
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
NetworkEngine::tellListenerExpired(const Sp<Node>& n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values, int version)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
@@ -219,7 +219,7 @@ NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, c
Tid tid (n->getNewTid());
pk.pack(KEY_Q); pk.pack(QUERY_UPDATE);
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_TID); pk.pack(tid);
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
Blob(buffer.data(), buffer.data() + buffer.size()),
@@ -460,9 +460,9 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
// process the full message
process(std::move(pmsg_it->second.msg), from);
partial_messages.erase(pmsg_it);
} catch (...) {
} catch (...) {
return;
}
}
} else
scheduler.add(now + RX_TIMEOUT, std::bind(&NetworkEngine::maintainRxBuffer, this, msg->tid));
}
@@ -485,11 +485,11 @@ NetworkEngine::processMessage(const uint8_t *buf, size_t buflen, SockAddr f)
}
if (msg->value_parts.empty()) {
try {
try {
process(std::move(msg), from);
} catch(...) {
} catch(...) {
return;
}
}
} else {
// starting partial message session
auto k = msg->tid;
@@ -699,7 +699,7 @@ NetworkEngine::send(const SockAddr& addr, const char *buf, size_t len, bool conf
}
Sp<Request>
NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
NetworkEngine::sendPing(const Sp<Node>& node, RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (node->getNewTid());
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
@@ -757,7 +757,7 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
}
Sp<Request>
NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
NetworkEngine::sendFindNode(const Sp<Node>& n, const InfoHash& target, want_t want,
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (n->getNewTid());
msgpack::sbuffer buffer;
@@ -802,7 +802,7 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
Sp<Request>
NetworkEngine::sendGetValues(Sp<Node> n, const InfoHash& info_hash, const Query& query, want_t want,
NetworkEngine::sendGetValues(const Sp<Node>& n, const InfoHash& info_hash, const Query& query, want_t want,
RequestCb&& on_done, RequestExpiredCb&& on_expired) {
Tid tid (n->getNewTid());
msgpack::sbuffer buffer;
@@ -955,8 +955,8 @@ NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const Soc
pk.pack(KEY_TID); pk.pack(tid);
pk.pack(KEY_V); pk.pack_map(1);
pk.pack(i); pk.pack_map(2);
pk.pack(std::string("o")); pk.pack(start);
pk.pack(std::string("d")); pk.pack_bin(end-start);
pk.pack("o"sv); pk.pack(start);
pk.pack("d"sv); pk.pack_bin(end-start);
pk.pack_bin_body((const char*)v.data()+start, end-start);
send(addr, buffer.data(), buffer.size());
start = end;
@@ -998,8 +998,8 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
auto fields = query.select.getSelection();
pk.pack(KEY_REQ_FIELDS);
pk.pack_map(2);
pk.pack(std::string("f")); pk.pack(fields);
pk.pack(std::string("v")); pk.pack_array(st.size()*fields.size());
pk.pack("f"sv); pk.pack(fields);
pk.pack("v"sv); pk.pack_array(st.size()*fields.size());
for (const auto& v : st)
v->msgpack_pack_fields(fields, pk);
//DHT_LOG_DBG("sending closest nodes (%d+%d nodes.), %u value headers containing %u fields",
@@ -1073,7 +1073,7 @@ NetworkEngine::bufferNodes(sa_family_t af, const InfoHash& id, want_t want,
}
Sp<Request>
NetworkEngine::sendListen(Sp<Node> n,
NetworkEngine::sendListen(const Sp<Node>& n,
const InfoHash& hash,
const Query& query,
const Blob& token,
@@ -1142,7 +1142,7 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
}
Sp<Request>
NetworkEngine::sendAnnounceValue(Sp<Node> n,
NetworkEngine::sendAnnounceValue(const Sp<Node>& n,
const InfoHash& infohash,
const Sp<Value>& value,
time_point created,
@@ -1200,7 +1200,7 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
}
Sp<Request>
NetworkEngine::sendUpdateValues(Sp<Node> n,
NetworkEngine::sendUpdateValues(const Sp<Node>& n,
const InfoHash& infohash,
const std::vector<Sp<Value>>& values,
time_point created,
@@ -1246,7 +1246,7 @@ NetworkEngine::sendUpdateValues(Sp<Node> n,
}
Sp<Request>
NetworkEngine::sendRefreshValue(Sp<Node> n,
NetworkEngine::sendRefreshValue(const Sp<Node>& n,
const InfoHash& infohash,
const Value::Id& vid,
const Blob& token,
+1 -4
View File
@@ -137,10 +137,7 @@ Node::openSocket(SocketCb&& cb)
if (++transaction_id == 0)
transaction_id = 1;
auto sock = std::make_shared<Socket>(std::move(cb));
auto s = sockets_.emplace(transaction_id, std::move(sock));
if (not s.second)
s.first->second = std::move(sock);
sockets_[transaction_id] = std::make_shared<Socket>(std::move(cb));
return transaction_id;
}
+1 -1
View File
@@ -175,7 +175,7 @@ SearchCache::listen(const ValueCallback& get_cb, const Sp<Query>& q, const Value
auto op = getOp(q);
if (op == ops.end()) {
// New query
op = ops.emplace(q, std::unique_ptr<OpCache>(new OpCache)).first;
op = ops.emplace(q, std::make_unique<OpCache>()).first;
auto& cache = *op->second;
cache.searchToken = onListen(q, [&](const std::vector<Sp<Value>>& values, bool expired){
return cache.onValue(values, expired);
+3 -3
View File
@@ -28,13 +28,13 @@ struct OpCacheValueStorage
Sp<Value> data {};
unsigned refCount {1};
system_clock::time_point updated {system_clock::time_point::min()};
OpCacheValueStorage(Sp<Value> val) : data(val) {}
explicit OpCacheValueStorage(Sp<Value> val) : data(std::move(val)) {}
};
class OpValueCache {
public:
OpValueCache(ValueCallback&& cb) noexcept : callback(std::forward<ValueCallback>(cb)) {}
OpValueCache(OpValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)) {
explicit OpValueCache(OpValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)) {
o.callback = {};
}
@@ -150,7 +150,7 @@ public:
return cache.size();
}
size_t searchToken;
size_t searchToken {0};
private:
constexpr static const std::chrono::seconds EXPIRATION {60};
OpCache(const OpCache&) = delete;
+47 -44
View File
@@ -22,47 +22,50 @@
#include "net.h"
#include <map>
#include <string_view>
using namespace std::literals;
namespace dht {
namespace net {
static const std::string KEY_Y {"y"};
static const std::string KEY_R {"r"};
static const std::string KEY_U {"u"};
static const std::string KEY_E {"e"};
static const std::string KEY_V {"p"};
static const std::string KEY_TID {"t"};
static const std::string KEY_UA {"v"};
static const std::string KEY_NETID {"n"};
static const std::string KEY_ISCLIENT {"s"};
static const std::string KEY_Q {"q"};
static const std::string KEY_A {"a"};
static constexpr auto KEY_Y = "y"sv;
static constexpr auto KEY_R = "r"sv;
static constexpr auto KEY_U = "u"sv;
static constexpr auto KEY_E = "e"sv;
static constexpr auto KEY_V = "p"sv;
static constexpr auto KEY_TID = "t"sv;
static constexpr auto KEY_UA = "v"sv;
static constexpr auto KEY_NETID = "n"sv;
static constexpr auto KEY_ISCLIENT = "s"sv;
static constexpr auto KEY_Q = "q"sv;
static constexpr auto KEY_A = "a"sv;
static const std::string KEY_REQ_SID {"sid"};
static const std::string KEY_REQ_ID {"id"};
static const std::string KEY_REQ_H {"h"};
static const std::string KEY_REQ_TARGET {"target"};
static const std::string KEY_REQ_QUERY {"q"};
static const std::string KEY_REQ_TOKEN {"token"};
static const std::string KEY_REQ_VALUE_ID {"vid"};
static const std::string KEY_REQ_NODES4 {"n4"};
static const std::string KEY_REQ_NODES6 {"n6"};
static const std::string KEY_REQ_CREATION {"c"};
static const std::string KEY_REQ_ADDRESS {"sa"};
static const std::string KEY_REQ_VALUES {"values"};
static const std::string KEY_REQ_EXPIRED {"exp"};
static const std::string KEY_REQ_REFRESHED {"re"};
static const std::string KEY_REQ_FIELDS {"fileds"};
static const std::string KEY_REQ_WANT {"w"};
static const std::string KEY_VERSION {"ve"};
static constexpr auto KEY_REQ_SID = "sid"sv;
static constexpr auto KEY_REQ_ID = "id"sv;
static constexpr auto KEY_REQ_H = "h"sv;
static constexpr auto KEY_REQ_TARGET = "target"sv;
static constexpr auto KEY_REQ_QUERY = "q"sv;
static constexpr auto KEY_REQ_TOKEN = "token"sv;
static constexpr auto KEY_REQ_VALUE_ID = "vid"sv;
static constexpr auto KEY_REQ_NODES4 = "n4"sv;
static constexpr auto KEY_REQ_NODES6 = "n6"sv;
static constexpr auto KEY_REQ_CREATION = "c"sv;
static constexpr auto KEY_REQ_ADDRESS = "sa"sv;
static constexpr auto KEY_REQ_VALUES = "values"sv;
static constexpr auto KEY_REQ_EXPIRED = "exp"sv;
static constexpr auto KEY_REQ_REFRESHED = "re"sv;
static constexpr auto KEY_REQ_FIELDS = "fileds"sv;
static constexpr auto KEY_REQ_WANT = "w"sv;
static constexpr auto KEY_VERSION = "ve"sv;
static const std::string QUERY_PING {"ping"};
static const std::string QUERY_FIND {"find"};
static const std::string QUERY_GET {"get"};
static const std::string QUERY_UPDATE {"update"};
static const std::string QUERY_PUT {"put"};
static const std::string QUERY_LISTEN {"listen"};
static const std::string QUERY_REFRESH {"refresh"};
static constexpr auto QUERY_PING = "ping"sv;
static constexpr auto QUERY_FIND = "find"sv;
static constexpr auto QUERY_GET = "get"sv;
static constexpr auto QUERY_UPDATE = "update"sv;
static constexpr auto QUERY_PUT = "put"sv;
static constexpr auto QUERY_LISTEN = "listen"sv;
static constexpr auto QUERY_REFRESH = "refresh"sv;
Tid unpackTid(const msgpack::object& o) {
switch (o.type) {
@@ -173,14 +176,14 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
msgpack::object* e;
msgpack::object* v;
msgpack::object* a;
std::string q;
std::string_view q;
} parsed {};
for (unsigned i = 0; i < msg.via.map.size; i++) {
auto& o = msg.via.map.ptr[i];
if (o.key.type != msgpack::type::STR)
continue;
auto key = o.key.as<std::string>();
auto key = o.key.as<std::string_view>();
if (key == KEY_Y)
parsed.y = &o.val;
else if (key == KEY_R)
@@ -200,7 +203,7 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
else if (key == KEY_ISCLIENT)
is_client = o.val.as<bool>();
else if (key == KEY_Q)
parsed.q = o.val.as<std::string>();
parsed.q = o.val.as<std::string_view>();
else if (key == KEY_A)
parsed.a = &o.val;
}
@@ -213,7 +216,7 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
type = MessageType::ValueData;
else if (parsed.u)
type = MessageType::ValueUpdate;
else if (parsed.y and parsed.y->as<std::string>() != "q")
else if (parsed.y and parsed.y->as<std::string_view>() != "q"sv)
throw msgpack::type_error();
else if (parsed.q == QUERY_PING)
type = MessageType::Ping;
@@ -237,8 +240,8 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
throw msgpack::type_error();
for (size_t i = 0; i < parsed.v->via.map.size; ++i) {
auto& vdat = parsed.v->via.map.ptr[i];
auto o = findMapValue(vdat.val, "o");
auto d = findMapValue(vdat.val, "d");
auto o = findMapValue(vdat.val, "o"sv);
auto d = findMapValue(vdat.val, "d"sv);
if (not o or not d)
continue;
value_parts.emplace(vdat.key.as<unsigned>(), std::pair<size_t, Blob>(o->as<size_t>(), unpackBlob(*d)));
@@ -267,7 +270,7 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
auto& o = req.via.map.ptr[i];
if (o.key.type != msgpack::type::STR)
continue;
auto key = o.key.as<std::string>();
auto key = o.key.as<std::string_view>();
if (key == KEY_REQ_SID)
socket_id = unpackTid(o.val);
else if (key == KEY_REQ_ID)
@@ -341,9 +344,9 @@ ParsedMessage::msgpack_unpack(const msgpack::object& msg)
}
}
} else if (parsedReq.fields) {
if (auto rfields = findMapValue(*parsedReq.fields, "f")) {
if (auto rfields = findMapValue(*parsedReq.fields, "f"sv)) {
auto vfields = rfields->as<std::set<Value::Field>>();
if (auto rvalues = findMapValue(*parsedReq.fields, "v")) {
if (auto rvalues = findMapValue(*parsedReq.fields, "v"sv)) {
if (rvalues->type != msgpack::type::ARRAY)
throw msgpack::type_error();
size_t val_num = rvalues->via.array.size / vfields.size();
+5 -4
View File
@@ -24,6 +24,8 @@
#include <asio.hpp>
using namespace std::literals;
namespace dht {
// Organization-local Scope multicast
@@ -61,7 +63,7 @@ private:
msgpack::sbuffer sbuf_;
std::map<std::string, msgpack::sbuffer> messages_;
std::map<std::string, ServiceDiscoveredCallback> callbackmap_;
std::map<std::string, ServiceDiscoveredCallback, std::less<>> callbackmap_;
bool lrunning_ {false};
bool drunning_ {false};
@@ -133,19 +135,18 @@ PeerDiscovery::DomainPeerDiscovery::loopListener()
msgpack::object obj = rcv.get();
if (obj.type == msgpack::type::STR) {
if (lrunning_ and obj.as<std::string>() == "q")
if (lrunning_ and obj.as<std::string_view>() == "q"sv)
publish(receiveFrom_);
} else if (obj.type == msgpack::type::MAP) {
for (unsigned i = 0; i < obj.via.map.size; i++) {
auto& o = obj.via.map.ptr[i];
if (o.key.type != msgpack::type::STR)
continue;
auto key = o.key.as<std::string>();
ServiceDiscoveredCallback cb;
{
std::lock_guard<std::mutex> lck(dmtx_);
if (drunning_) {
auto callback = callbackmap_.find(key);
auto callback = callbackmap_.find(o.key.as<std::string_view>());
if (callback != callbackmap_.end())
cb = callback->second;
} else
+2 -2
View File
@@ -74,14 +74,14 @@ struct Request {
Blob&& msg,
std::function<void(const Request&, ParsedMessage&&)> on_done,
std::function<void(const Request&, bool)> on_expired) :
node(node), tid(tid), type(type), on_done(on_done), on_expired(on_expired), msg(std::move(msg)) { }
node(std::move(node)), tid(tid), type(type), on_done(std::move(on_done)), on_expired(std::move(on_expired)), msg(std::move(msg)) { }
Request(MessageType type, Tid tid,
Sp<Node> node,
Blob&& msg,
std::function<void(const Request&, ParsedMessage&&)> on_done,
std::function<bool(const Request&, DhtProtocolException&&)> on_error,
std::function<void(const Request&, bool)> on_expired) :
node(node), tid(tid), type(type), on_done(on_done), on_error(on_error), on_expired(on_expired), msg(std::move(msg)) { }
node(std::move(node)), tid(tid), type(type), on_done(std::move(on_done)), on_error(std::move(on_error)), on_expired(std::move(on_expired)), msg(std::move(msg)) { }
Tid getTid() const { return tid; }
MessageType getType() const { return type; }
+14 -15
View File
@@ -164,12 +164,12 @@ struct Dht::SearchNode {
if (node->isExpired())
return false;
bool pending {false},
bool is_pending {false},
completed_sq_status {false},
pending_sq_status {false};
for (const auto& s : getStatus) {
if (s.second and s.second->pending())
pending = true;
is_pending = true;
if (s.first and q and q->isSatisfiedBy(*s.first) and s.second) {
if (s.second->pending())
pending_sq_status = true;
@@ -180,7 +180,7 @@ struct Dht::SearchNode {
}
}
return (not pending and now > last_get_reply + Node::NODE_EXPIRE_TIME) or
return (not is_pending and now > last_get_reply + Node::NODE_EXPIRE_TIME) or
not (completed_sq_status or pending_sq_status or hasStartedPagination(q));
}
@@ -292,7 +292,7 @@ struct Dht::SearchNode {
return std::find_if(status.cbegin(), status.cend(),
[](const SyncStatus::value_type& r){
return r.second and r.second->pending();
}) != status.end();
}) != status.cend();
}
static bool pending(const NodeListenerStatus& status) {
return std::find_if(status.begin(), status.end(),
@@ -437,13 +437,13 @@ struct Dht::Search {
~Search() {
if (opExpirationJob)
opExpirationJob->cancel();
for (auto& get : callbacks) {
get.second.done_cb(false, {});
get.second.done_cb = {};
for (auto& g : callbacks) {
g.second.done_cb(false, {});
g.second.done_cb = {};
}
for (auto& put : announce) {
put.callback(false, {});
put.callback = {};
for (auto& a : announce) {
a.callback(false, {});
a.callback = {};
}
}
@@ -465,7 +465,7 @@ struct Dht::Search {
bool insertNode(const Sp<Node>& n, time_point now, const Blob& token={});
SearchNode* getNode(const Sp<Node>& n) {
auto srn = std::find_if(nodes.begin(), nodes.end(), [&](std::unique_ptr<SearchNode>& sn) {
auto srn = std::find_if(nodes.begin(), nodes.end(), [&](const std::unique_ptr<SearchNode>& sn) {
return n == sn->node;
});
return (srn == nodes.end()) ? nullptr : (*srn).get();
@@ -665,12 +665,11 @@ struct Dht::Search {
}
unsigned getNumberOfConsecutiveBadNodes() const {
unsigned count = 0;
std::find_if(nodes.begin(), nodes.end(), [&count](const std::unique_ptr<SearchNode>& sn) {
for (const auto& sn : nodes) {
if (not sn->node->isExpired())
return true;
break;
++count;
return false;
});
}
return count;
}
+2 -2
View File
@@ -482,13 +482,13 @@ Query::msgpack_unpack(const msgpack::object& o)
if (o.type != msgpack::type::MAP)
throw msgpack::type_error();
auto rfilters = findMapValue(o, "w"); /* unpacking filters */
auto rfilters = findMapValue(o, "w"sv); /* unpacking filters */
if (rfilters)
where.msgpack_unpack(*rfilters);
else
throw msgpack::type_error();
auto rfield_selector = findMapValue(o, "s"); /* unpacking field selectors */
auto rfield_selector = findMapValue(o, "s"sv); /* unpacking field selectors */
if (rfield_selector)
select.msgpack_unpack(*rfield_selector);
else
+2 -2
View File
@@ -28,7 +28,7 @@ using CallbackQueue = std::list<std::function<void()>>;
class ValueCache {
public:
ValueCache(ValueStateCallback&& cb, SyncCallback&& scb = {})
explicit ValueCache(ValueStateCallback&& cb, SyncCallback&& scb = {})
: callback(std::forward<ValueStateCallback>(cb)), syncCallback(std::move(scb))
{
if (syncCallback)
@@ -53,7 +53,7 @@ public:
CallbackQueue clear() {
std::vector<Sp<Value>> expired_values;
expired_values.reserve(values.size());
for (const auto& v : values)
for (auto& v : values)
expired_values.emplace_back(std::move(v.second.data));
values.clear();
CallbackQueue ret;
+5
View File
@@ -199,6 +199,11 @@ DhtRunnerTester::testIdOps() {
node2.run(42232, config2, std::move(context2));
node2.bootstrap(node1.getBound());
{
std::unique_lock<std::mutex> lk(mutex);
CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]{ return valueCount == 1; }));
}
node1.findCertificate(node2.getId(), [&](const std::shared_ptr<dht::crypto::Certificate>& crt){
CPPUNIT_ASSERT(crt);
std::lock_guard<std::mutex> lk(mutex);
+7
View File
@@ -11,3 +11,10 @@ dhtchat_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIBS@
dhtscanner_SOURCES = dhtscanner.cpp
dhtscanner_LDFLAGS = -lopendht -lreadline -L@top_builddir@/src/.libs @GnuTLS_LIBS@
if ENABLE_C
bin_PROGRAMS += dhtcnode
dhtcnode_CFLAGS = -std=c11 -isystem @top_srcdir@/c -isystem @top_srcdir@/include
dhtcnode_SOURCES = dhtcnode.c
dhtcnode_LDFLAGS = -lopendht-c -lreadline -L@top_builddir@/c/.libs
endif
+168 -59
View File
@@ -1,14 +1,23 @@
#include <opendht_c.h>
#include <getopt.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <stdatomic.h>
struct op_context {
dht_runner* runner;
int d;
atomic_bool stop;
};
struct listen_context {
dht_runner* runner;
dht_op_token* token;
};
bool dht_value_callback(const dht_value* value, bool expired, void* user_data)
@@ -26,16 +35,30 @@ bool dht_get_callback(const dht_value* value, void* user_data)
return true;
}
void dht_done_callback(bool ok, void* user_data)
void dht_get_done_callback(bool ok, void* user_data)
{
dht_runner* runner = (dht_runner*)user_data;
printf("Done callback. %s\n", ok ? "Success !" : "Failure :-(");
printf("Get completed: %s\n", ok ? "success !" : "failure :-(");
}
void op_context_free(void* user_data)
void dht_put_done_callback(bool ok, void* user_data)
{
dht_runner* runner = (dht_runner*)user_data;
printf("Put completed: %s\n", ok ? "success !" : "failure :-(");
}
void dht_shutdown_callback(void* user_data)
{
printf("Stopped.\n");
struct op_context* ctx = (struct op_context*)user_data;
printf("op_context_free %d.\n", ctx->d);
atomic_store(&ctx->stop, true);
}
void listen_context_free(void* user_data)
{
printf("listen_context_free.\n");
struct listen_context* ctx = (struct listen_context*)user_data;
dht_op_token_delete(ctx->token);
free(ctx);
}
@@ -60,66 +83,152 @@ char* print_addr(const struct sockaddr* addr) {
return s;
}
int main()
struct dht_params {
bool help;
bool version;
bool generate_identity;
bool service;
bool peer_discovery;
bool log;
const char* bootstrap;
unsigned network;
in_port_t port;
};
static const struct option long_options[] = {
{"help", no_argument , NULL, 'h'},
{"port", required_argument, NULL, 'p'},
{"net", required_argument, NULL, 'n'},
{"bootstrap", required_argument, NULL, 'b'},
{"identity", no_argument , NULL, 'i'},
{"verbose", no_argument , NULL, 'v'},
{"service", no_argument , NULL, 's'},
{"peer-discovery", no_argument , NULL, 'D'},
{"no-rate-limit", no_argument , NULL, 'U'},
{"persist", required_argument, NULL, 'f'},
{"logfile", required_argument, NULL, 'l'},
{"syslog", no_argument , NULL, 'L'},
{NULL, 0 , NULL, 0}
};
struct dht_params
parse_args(int argc, char **argv) {
struct dht_params params;
int opt;
while ((opt = getopt_long(argc, argv, "hisvDp:n:b:f:l:", long_options, NULL)) != -1) {
switch (opt) {
case 'p': {
int port_arg = atoi(optarg);
if (port_arg >= 0 && port_arg < 0x10000)
params.port = port_arg;
}
break;
case 'D':
params.peer_discovery = true;
break;
case 'n':
params.network = strtoul(optarg, NULL, 0);
break;
case 'b':
params.bootstrap = (optarg[0] == '=') ? optarg+1 : optarg;
break;
case 'h':
params.help = true;
break;
case 'v':
params.log = true;
break;
case 'i':
params.generate_identity = true;
break;
case 's':
params.service = true;
break;
default:
break;
}
}
return params;
}
int main(int argc, char **argv)
{
dht_identity id = dht_identity_generate("testNode", NULL);
dht_infohash cert_id = dht_certificate_get_id(id.certificate);
printf("Cert ID: %s\n", dht_infohash_print(&cert_id));
dht_publickey* pk = dht_certificate_get_publickey(id.certificate);
dht_infohash pk_id = dht_publickey_get_id(pk);
printf("PK ID: %s\n", dht_infohash_print(&pk_id));
dht_publickey_delete(pk);
pk = dht_privatekey_get_publickey(id.privatekey);
pk_id = dht_publickey_get_id(pk);
printf("Key ID: %s\n", dht_infohash_print(&pk_id));
dht_publickey_delete(pk);
dht_identity_delete(&id);
struct dht_params params = parse_args(argc, argv);
dht_runner* runner = dht_runner_new();
dht_runner_run(runner, 4040);
dht_runner_config dht_config;
dht_runner_config_default(&dht_config);
dht_config.peer_discovery = params.peer_discovery; // Look for other peers on the network
dht_config.peer_publish = params.peer_discovery; // Publish our own peer info
dht_config.dht_config.node_config.network = params.network;
dht_config.log = params.log;
dht_runner_run_config(runner, params.port, &dht_config);
dht_infohash h;
dht_infohash_random(&h);
printf("random hash: %s\n", dht_infohash_print(&h));
// Put data
const char* data_str = "yo, this is some data";
dht_value* val = dht_value_new_from_string(data_str);
dht_runner_put(runner, &h, val, dht_done_callback, runner, false);
dht_value_unref(val);
// Get data
dht_runner_get(runner, &h, dht_get_callback, dht_done_callback, runner);
// Listen for data
struct op_context* ctx = malloc(sizeof(struct op_context));
ctx->runner = runner;
ctx->d = 42;
dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, op_context_free, ctx);
sleep(1);
dht_runner_bootstrap(runner, "bootstrap.jami.net", NULL);
sleep(2);
struct sockaddr** addrs = dht_runner_get_public_address(runner);
for (struct sockaddr** addrIt = addrs; *addrIt; addrIt++) {
struct sockaddr* addr = *addrIt;
char* addr_str = print_addr(addr);
free(addr);
printf("Found public address: %s\n", addr_str);
free(addr_str);
if (params.bootstrap) {
printf("Bootstrap using %s\n", params.bootstrap);
dht_runner_bootstrap(runner, params.bootstrap, NULL);
}
free(addrs);
dht_runner_cancel_listen(runner, &h, token);
dht_op_token_delete(token);
char cmd[64];
char arg[64];
char value[256];
while (true) {
const char* line_read = readline("> ");
if (line_read && *line_read)
add_history(line_read);
if (!line_read)
break;
if (!strcmp(line_read, "\0"))
continue;
bzero(cmd, sizeof cmd);
bzero(arg, sizeof arg);
bzero(value, sizeof value);
sscanf(line_read, "%64s %64s %256s", cmd, arg, value);
//printf("%s -> %s\n", cmd, arg);
if (!strcmp(cmd, "la")) {
struct sockaddr** addrs = dht_runner_get_public_address(runner);
if (addrs) {
for (struct sockaddr** addrIt = addrs; *addrIt; addrIt++) {
struct sockaddr* addr = *addrIt;
char* addr_str = print_addr(addr);
free(addr);
printf("Found public address: %s\n", addr_str);
free(addr_str);
}
free(addrs);
}
continue;
}
dht_infohash key;
dht_infohash_from_hex(&key, arg);
if (dht_infohash_is_zero(&key)) {
dht_infohash_get_from_string(&key, arg);
printf("Using h(%s) = %s\n", arg, dht_infohash_print(&key));
}
if (!strcmp(cmd, "g")) {
dht_runner_get(runner, &key, dht_get_callback, dht_get_done_callback, runner);
} else if (!strcmp(cmd, "l")) {
struct listen_context* ctx = malloc(sizeof(struct listen_context));
ctx->runner = runner;
ctx->token = dht_runner_listen(runner, &key, dht_value_callback, listen_context_free, ctx);
} else if (!strcmp(cmd, "p")) {
dht_value* val = dht_value_new_from_string(value);
dht_runner_put(runner, &key, val, dht_put_done_callback, runner, true);
dht_value_unref(val);
}
}
printf("Stopping..\n");
struct op_context ctx;
ctx.runner = runner;
atomic_init(&ctx.stop, false);
dht_runner_shutdown(runner, dht_shutdown_callback, &ctx);
while (!atomic_load(&ctx.stop)) {
usleep(250);
}
dht_runner_delete(runner);
return 0;
}
+13 -6
View File
@@ -327,15 +327,17 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
if (op == "g") {
std::string rem;
std::getline(iss, rem);
node->get(id, [start](const std::vector<std::shared_ptr<Value>>& values) {
auto total = std::make_shared<size_t>();
node->get(id, [start, total](const std::vector<std::shared_ptr<Value>>& values) {
auto now = std::chrono::high_resolution_clock::now();
std::cout << "Get: found " << values.size() << " value(s) after " << print_duration(now-start) << std::endl;
(*total) += values.size();
std::cout << "Get: found " << values.size() << " value(s) after " << print_duration(now-start) << " (total " << *total << ')' << std::endl;
for (const auto& value : values)
std::cout << "\t" << *value << std::endl;
return true;
}, [start](bool ok) {
}, [start, total](bool ok) {
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Get: " << (ok ? "completed" : "failure") << ", took " << print_duration(end-start) << std::endl;
std::cout << "Get: " << (ok ? "completed" : "failure") << ", took " << print_duration(end-start) << " (total " << *total << ')' << std::endl;
}, {}, dht::Where {rem});
}
else if (op == "q") {
@@ -356,8 +358,13 @@ void cmd_loop(std::shared_ptr<DhtRunner>& node, dht_params& params
else if (op == "l") {
std::string rem;
std::getline(iss, rem);
auto token = node->listen(id, [](const std::vector<std::shared_ptr<Value>>& values, bool expired) {
std::cout << "Listen: found " << values.size() << " values" << (expired ? " expired" : "") << std::endl;
auto total = std::make_shared<size_t>();
auto token = node->listen(id, [total](const std::vector<std::shared_ptr<Value>>& values, bool expired) {
if (expired)
(*total) -= values.size();
else
(*total) += values.size();
std::cout << "Listen: found " << values.size() << " values" << (expired ? " expired" : "") << " (total " << *total << ')' << std::endl;
for (const auto& value : values)
std::cout << "\t" << *value << std::endl;
return true;