mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-10 05:17:13 +00:00
Compare commits
101
Commits
llhttp
...
cert_pk_id
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4622f5e49 | ||
|
|
1d86ab8b16 | ||
|
|
c5edca7508 | ||
|
|
767a3721bd | ||
|
|
e368292546 | ||
|
|
acae4bc4ff | ||
|
|
68dc6a64be | ||
|
|
54a8fef0ee | ||
|
|
a722726196 | ||
|
|
b9bd954dfd | ||
|
|
aeb0b163cf | ||
|
|
c4e75ae66c | ||
|
|
d9afd2631b | ||
|
|
405220795b | ||
|
|
3e407e65fa | ||
|
|
a2dff6a123 | ||
|
|
8d030f75f6 | ||
|
|
13af7a6002 | ||
|
|
2bc46e9657 | ||
|
|
b3b050ca26 | ||
|
|
38b0b2248f | ||
|
|
5cfb1c6c9c | ||
|
|
7aad21b7ed | ||
|
|
c3669cfd36 | ||
|
|
45f04a7b6f | ||
|
|
33f9570ecb | ||
|
|
c2d8b19380 | ||
|
|
9bd957da48 | ||
|
|
352e36500c | ||
|
|
7397bd615f | ||
|
|
6a264d6f73 | ||
|
|
b0fa19d6f8 | ||
|
|
b2860e1731 | ||
|
|
ad65ce872b | ||
|
|
0cdc828953 | ||
|
|
65e13fff4e | ||
|
|
748247d660 | ||
|
|
456f266be3 | ||
|
|
2c26030108 | ||
|
|
efc26245ae | ||
|
|
b9e00c7a0f | ||
|
|
5bf19c875c | ||
|
|
5c18c980aa | ||
|
|
b8d6fdc8eb | ||
|
|
27bfd547c5 | ||
|
|
5237f0a3b3 | ||
|
|
23af860532 | ||
|
|
4c98f7c8f4 | ||
|
|
2a4b357420 | ||
|
|
a26ac441ba | ||
|
|
80cfed38a1 | ||
|
|
83ae498008 | ||
|
|
7c184e1c8c | ||
|
|
4aa417802f | ||
|
|
cdba5b33cc | ||
|
|
81bd05fe84 | ||
|
|
cf135d18b4 | ||
|
|
c7ba7f6703 | ||
|
|
c73c8c77f2 | ||
|
|
c3bb16e92f | ||
|
|
3f27cd7069 | ||
|
|
b222efe638 | ||
|
|
3c62026b5c | ||
|
|
7cf43f53ac | ||
|
|
df189e3e12 | ||
|
|
7e0e7d5483 | ||
|
|
1aeb596b04 | ||
|
|
950194f68e | ||
|
|
5dc3d3cfd7 | ||
|
|
5397f80b87 | ||
|
|
88d0af9e3d | ||
|
|
792b851d77 | ||
|
|
9da832c1d1 | ||
|
|
44f6d21c83 | ||
|
|
38454eaf6e | ||
|
|
76a2bd234a | ||
|
|
972d4d28a1 | ||
|
|
72e0a4fb6b | ||
|
|
3e2fd5e8fa | ||
|
|
8b3f7f2480 | ||
|
|
57c855e1cb | ||
|
|
56e7cd94a5 | ||
|
|
074e05cc32 | ||
|
|
251f66dfce | ||
|
|
227a7aa0d9 | ||
|
|
e12e344a79 | ||
|
|
d4fc4fd658 | ||
|
|
08d67cc8d8 | ||
|
|
208afd22f2 | ||
|
|
9eea01202a | ||
|
|
304a9992fe | ||
|
|
ae62216bf4 | ||
|
|
cd92eeaae5 | ||
|
|
9dad7c69fd | ||
|
|
5cc5b98aeb | ||
|
|
c03ce419ca | ||
|
|
ceef3f048c | ||
|
|
8dd926182c | ||
|
|
c8b528b3f4 | ||
|
|
a65148cd08 | ||
|
|
5a2a20a32f |
No files matched your search
+129
-69
@@ -1,5 +1,13 @@
|
||||
name: C/C++ CI
|
||||
|
||||
env:
|
||||
LLHTTP_VERSION: "v9.2.1"
|
||||
RESTINIO_VERSION: "0.7.6"
|
||||
EXPECTED_LITE_URL: "https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp"
|
||||
UBUNTU_FULL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev autotools-dev autoconf libfmt-dev libmsgpack-dev libargon2-dev"
|
||||
UBUNTU_MESON_DEPS: "ninja-build libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-dev python3-setuptools python3-pip libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
|
||||
UBUNTU_MINIMAL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libfmt-dev libgnutls28-dev libcppunit-dev libmsgpack-dev libargon2-dev"
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
@@ -7,90 +15,142 @@ jobs:
|
||||
name: Ubuntu/GCC Autotools build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Dependencies
|
||||
run: |
|
||||
sudo apt install libncurses5-dev libreadline-dev nettle-dev libasio-dev \
|
||||
libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev
|
||||
- name: Cython
|
||||
run: sudo pip3 install Cython
|
||||
- name: Configure
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure
|
||||
- name: Build
|
||||
run: make
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
echo "Installing Ubuntu full dependencies:"
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y $UBUNTU_FULL_DEPS
|
||||
|
||||
- name: Install Cython
|
||||
run: sudo pip3 install Cython
|
||||
|
||||
- name: Build llhttp dependency
|
||||
run: |
|
||||
mkdir llhttp
|
||||
wget "https://github.com/nodejs/llhttp/archive/refs/tags/release/${LLHTTP_VERSION}.tar.gz" -O llhttp.tar.gz
|
||||
tar -xzf llhttp.tar.gz -C llhttp --strip-components=1
|
||||
cd llhttp && cmake -DCMAKE_INSTALL_PREFIX=/usr . && make -j2 && sudo make install
|
||||
cd ../ && rm -rf llhttp*
|
||||
|
||||
- name: Install expected-lite header
|
||||
run: |
|
||||
sudo mkdir -p /usr/local/include/nonstd
|
||||
sudo wget "${EXPECTED_LITE_URL}" -O /usr/local/include/nonstd/expected.hpp
|
||||
|
||||
- name: Build restinio dependency
|
||||
run: |
|
||||
mkdir restinio && cd restinio
|
||||
wget "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2"
|
||||
tar -xjf restinio-${RESTINIO_VERSION}.tar.bz2
|
||||
cd restinio-${RESTINIO_VERSION}/dev
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off \
|
||||
-DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
|
||||
sudo make install
|
||||
cd ../../ && rm -rf restinio*
|
||||
|
||||
- name: Configure project
|
||||
run: |
|
||||
./autogen.sh
|
||||
./configure --enable-proxy-client
|
||||
|
||||
- name: Build
|
||||
run: make
|
||||
|
||||
build-ubuntu-meson:
|
||||
name: Ubuntu/GCC Meson build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Dependencies
|
||||
run: |
|
||||
sudo apt install ninja-build libncurses5-dev libreadline-dev nettle-dev libasio-dev \
|
||||
libgnutls28-dev libuv1-dev python3-dev python3-setuptools python3-pip \
|
||||
libcppunit-dev libjsoncpp-dev libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev
|
||||
- name: Python dependencies
|
||||
run: sudo pip3 install meson Cython
|
||||
- name: Configure
|
||||
run: meson setup build .
|
||||
- name: Build
|
||||
run: cd build && ninja
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
echo "Installing Ubuntu meson dependencies:"
|
||||
sudo apt update
|
||||
sudo apt install -y $UBUNTU_MESON_DEPS
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: sudo pip3 install meson Cython
|
||||
|
||||
- name: Configure with Meson
|
||||
run: meson setup build .
|
||||
|
||||
- name: Build with Ninja
|
||||
run: cd build && ninja
|
||||
|
||||
build-ubuntu-minimal:
|
||||
name: Ubuntu/GCC minimal build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Dependencies
|
||||
run: |
|
||||
sudo apt install libncurses5-dev libreadline-dev nettle-dev libfmt-dev \
|
||||
libgnutls28-dev libcppunit-dev libmsgpack-dev libargon2-0-dev
|
||||
- name: Configure
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Debug \
|
||||
-DOPENDHT_C=Off -DBUILD_TESTING=On -DOPENDHT_PEER_DISCOVERY=Off -DOPENDHT_PYTHON=Off \
|
||||
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=Off -DOPENDHT_PROXY_CLIENT=Off
|
||||
- name: Build
|
||||
run: cd build && make
|
||||
- name: Unit tests
|
||||
run: cd build && ./opendht_unit_tests
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Minimal Dependencies
|
||||
run: |
|
||||
echo "Installing Ubuntu minimal dependencies:"
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y $UBUNTU_MINIMAL_DEPS
|
||||
|
||||
- name: Configure project with CMake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DOPENDHT_C=Off -DBUILD_TESTING=On \
|
||||
-DOPENDHT_PEER_DISCOVERY=Off -DOPENDHT_PYTHON=Off \
|
||||
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=Off -DOPENDHT_PROXY_CLIENT=Off
|
||||
|
||||
- name: Build
|
||||
run: cd build && make
|
||||
|
||||
- name: Run Unit tests
|
||||
run: cd build && ./opendht_unit_tests
|
||||
|
||||
build-macos:
|
||||
name: macOS/Clang build
|
||||
runs-on: macos-12
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Dependencies
|
||||
run: |
|
||||
brew install msgpack-cxx asio gnutls nettle readline fmt jsoncpp argon2 openssl http-parser cppunit
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: restinio
|
||||
run: |
|
||||
mkdir restinio && cd restinio
|
||||
wget https://github.com/aberaud/restinio/archive/6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz
|
||||
ls -l && tar -xzf 6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz
|
||||
cd restinio-6fd08b65f6f15899dd0de3c801f6a5462b811c64/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: Install Homebrew Dependencies
|
||||
run: brew install msgpack-cxx asio gnutls nettle readline fmt jsoncpp argon2 openssl cppunit
|
||||
|
||||
- name: Configure
|
||||
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 -DBUILD_TESTING=On -DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off \
|
||||
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
|
||||
- name: Install expected-lite header
|
||||
run: |
|
||||
sudo mkdir -p /usr/local/include/nonstd
|
||||
sudo wget "${EXPECTED_LITE_URL}" -O /usr/local/include/nonstd/expected.hpp
|
||||
|
||||
- name: Build
|
||||
run: cd build && make
|
||||
- name: Build restinio dependency
|
||||
run: |
|
||||
mkdir restinio && cd restinio
|
||||
wget "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2"
|
||||
tar -xjf restinio-${RESTINIO_VERSION}.tar.bz2
|
||||
cd restinio-${RESTINIO_VERSION}/dev
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off \
|
||||
-DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
|
||||
make -j2 && sudo make install
|
||||
cd ../../ && rm -rf restinio*
|
||||
|
||||
- name: Configure project with CMake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
# Set Homebrew OpenSSL paths
|
||||
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 -DBUILD_TESTING=On \
|
||||
-DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off \
|
||||
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On \
|
||||
-DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
|
||||
|
||||
- name: Build
|
||||
run: cd build && make
|
||||
@@ -6,26 +6,33 @@ jobs:
|
||||
name: Clang Static Analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: deps
|
||||
run: |
|
||||
sudo apt update && \
|
||||
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
|
||||
libgnutls28-dev libuv1-dev python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
|
||||
autotools-dev autoconf libfmt-dev libhttp-parser-dev libmsgpack-dev libargon2-0-dev libasio-dev \
|
||||
autotools-dev autoconf libfmt-dev libmsgpack-dev libargon2-dev libasio-dev \
|
||||
llvm llvm-dev clang clang-tools && \
|
||||
sudo apt remove gcc g++
|
||||
|
||||
- name: expected-lite
|
||||
run: |
|
||||
sudo mkdir /usr/include/nonstd && \
|
||||
sudo wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
- name: restinio
|
||||
run: |
|
||||
mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& ls -l && tar -xzf 6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& cd restinio-6fd08b65f6f15899dd0de3c801f6a5462b811c64/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
|
||||
mkdir restinio && cd restinio
|
||||
wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2
|
||||
ls -l && tar -xjf restinio-0.7.3.tar.bz2
|
||||
cd restinio-0.7.3/dev
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
|
||||
make -j2 && sudo make install
|
||||
cd ../../ && rm -rf restinio*
|
||||
|
||||
- name: cmake
|
||||
run: |
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
@@ -25,10 +25,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -36,12 +36,12 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDeps
|
||||
@@ -58,10 +58,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -69,13 +69,13 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
@@ -92,10 +92,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -103,12 +103,12 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS_LLVM }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDepsLlvm
|
||||
@@ -125,10 +125,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -136,13 +136,13 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LLVM }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileLlvm
|
||||
@@ -159,10 +159,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -170,13 +170,13 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DHTNODE }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDhtnode
|
||||
@@ -193,10 +193,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -204,13 +204,13 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE_DEPS }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDepsAlpine
|
||||
@@ -227,10 +227,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -238,13 +238,13 @@ jobs:
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileAlpine
|
||||
@@ -262,7 +262,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: cmake
|
||||
run: |
|
||||
@@ -280,14 +280,14 @@ jobs:
|
||||
- name: build
|
||||
run: cd build && make dist
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: opendht-wheels-linux
|
||||
path: build/python/dist/*.whl
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
draft: true
|
||||
files: build/python/dist/*.whl
|
||||
@@ -52,6 +52,10 @@ Makefile.in
|
||||
# VSCode
|
||||
.vscode/*
|
||||
|
||||
# Visual Studio
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
|
||||
# Eclipse CDT
|
||||
.cproject
|
||||
.project
|
||||
@@ -78,3 +82,5 @@ doc/Doxyfile
|
||||
build
|
||||
build_dev
|
||||
.DS_Store
|
||||
build-*/
|
||||
install/
|
||||
+63
-13
@@ -1,4 +1,7 @@
|
||||
cmake_minimum_required (VERSION 3.16..3.28)
|
||||
cmake_minimum_required (VERSION 3.16..3.31)
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
project (opendht)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
@@ -7,9 +10,10 @@ include(CheckIncludeFileCXX)
|
||||
include(FindPkgConfig)
|
||||
include(cmake/CheckAtomic.cmake)
|
||||
include(CTest)
|
||||
include(FetchContent)
|
||||
|
||||
set (opendht_VERSION_MAJOR 3)
|
||||
set (opendht_VERSION_MINOR 1.11)
|
||||
set (opendht_VERSION_MINOR 4.0)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -29,6 +33,7 @@ option (OPENDHT_PROXY_CLIENT "Enable DHT proxy client, use Restinio and jsoncpp"
|
||||
option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
|
||||
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_IO_URING "Use io_uring if available on the system (Linux only)" OFF)
|
||||
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
|
||||
option (OPENDHT_TESTS_NETWORK "Enable unit tests that require network access" ON)
|
||||
option (OPENDHT_C "Build C bindings" OFF)
|
||||
@@ -81,15 +86,50 @@ if (NOT MSVC)
|
||||
|
||||
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
find_path(ASIO_INCLUDE_DIR asio.hpp REQUIRED)
|
||||
message(STATUS "Found ASIO ${ASIO_INCLUDE_DIR}")
|
||||
else()
|
||||
message(STATUS "ASIO not required")
|
||||
endif ()
|
||||
|
||||
find_package(fmt)
|
||||
|
||||
if (OPENDHT_HTTP)
|
||||
find_package(Restinio REQUIRED)
|
||||
find_library(HTTP_PARSER_LIBRARY http_parser)
|
||||
add_library(http_parser SHARED IMPORTED)
|
||||
set(http_parser_lib "-lhttp_parser")
|
||||
|
||||
# llhttp
|
||||
pkg_search_module(LLHTTP IMPORTED_TARGET llhttp libllhttp)
|
||||
if (LLHTTP_FOUND)
|
||||
message(STATUS "Found llhttp ${LLHTTP_INCLUDE_DIRS}")
|
||||
set(llhttp_target PkgConfig::LLHTTP)
|
||||
else()
|
||||
find_path(LLHTTP_INCLUDE_DIR llhttp.h)
|
||||
find_library(LLHTTP_LIBRARY NAMES llhttp libllhttp)
|
||||
if (LLHTTP_INCLUDE_DIR AND LLHTTP_LIBRARY)
|
||||
message(STATUS "Found llhttp ${LLHTTP_INCLUDE_DIR} ${LLHTTP_LIBRARY}")
|
||||
add_library(llhttp_static STATIC IMPORTED)
|
||||
set_target_properties(llhttp_static PROPERTIES
|
||||
IMPORTED_LOCATION ${LLHTTP_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${LLHTTP_INCLUDE_DIR}
|
||||
)
|
||||
set(llhttp_target llhttp_static)
|
||||
else()
|
||||
FetchContent_Declare(llhttp-local URL "https://github.com/nodejs/llhttp/archive/refs/tags/release/v9.2.1.tar.gz")
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON CACHE INTERNAL "")
|
||||
else()
|
||||
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
|
||||
set(BUILD_STATIC_LIBS ON CACHE INTERNAL "")
|
||||
endif()
|
||||
FetchContent_MakeAvailable(llhttp-local)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(llhttp_target llhttp_shared)
|
||||
else()
|
||||
set(llhttp_target llhttp_static)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
set(http_lib "-lllhttp")
|
||||
|
||||
if (NOT Jsoncpp_FOUND)
|
||||
message(SEND_ERROR "Jsoncpp is required for DHT proxy support")
|
||||
endif()
|
||||
@@ -123,17 +163,20 @@ else ()
|
||||
${WIN32_DEP_DIR}/openssl/include
|
||||
${WIN32_DEP_DIR}/restinio/dev
|
||||
${WIN32_DEP_DIR}/fmt/include
|
||||
${WIN32_DEP_DIR}/http_parser
|
||||
${WIN32_DEP_DIR}/llhttp/include
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (OPENDHT_HTTP OR OPENDHT_PEER_DISCOVERY)
|
||||
add_definitions(-DASIO_STANDALONE)
|
||||
if (OPENDHT_IO_URING AND UNIX AND NOT APPLE)
|
||||
pkg_search_module(liburing IMPORTED_TARGET liburing)
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
if (NOT MSVC)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wno-deprecated -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
|
||||
if (OPENDHT_SANITIZE)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fstack-protector-strong")
|
||||
@@ -142,8 +185,7 @@ else ()
|
||||
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
-DWIN32_LEAN_AND_MEAN
|
||||
-DSTATIC_GETOPT
|
||||
-DGNUTLS_INTERNAL_BUILD)
|
||||
-DSTATIC_GETOPT)
|
||||
set(DISABLE_MSC_WARNINGS "/wd4101 /wd4244 /wd4267 /wd4273 /wd4804 /wd4834 /wd4996")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DISABLE_MSC_WARNINGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
@@ -204,6 +246,7 @@ list (APPEND opendht_SOURCES
|
||||
)
|
||||
|
||||
list (APPEND opendht_HEADERS
|
||||
include/opendht.h
|
||||
include/opendht/def.h
|
||||
include/opendht/utils.h
|
||||
include/opendht/sockaddr.h
|
||||
@@ -306,12 +349,12 @@ if (MSVC)
|
||||
)
|
||||
if (OPENDHT_HTTP)
|
||||
add_obj_lib (win32_fmt ${WIN32_DEP_DIR}/fmt/msvc/Release/fmt.lib)
|
||||
add_obj_lib (win32_http_parser ${WIN32_DEP_DIR}/http_parser/x64/Release/http-parser.lib)
|
||||
add_obj_lib (win32_llhttp ${WIN32_DEP_DIR}/llhttp/build/Release/llhttp.lib)
|
||||
add_obj_lib (win32_ssl ${WIN32_DEP_DIR}/openssl/libssl_static.lib)
|
||||
add_obj_lib (win32_crypto ${WIN32_DEP_DIR}/openssl/libcrypto_static.lib)
|
||||
list (APPEND obj_libs
|
||||
$<TARGET_OBJECTS:win32_fmt>
|
||||
$<TARGET_OBJECTS:win32_http_parser>
|
||||
$<TARGET_OBJECTS:win32_llhttp>
|
||||
$<TARGET_OBJECTS:win32_ssl>
|
||||
$<TARGET_OBJECTS:win32_crypto>
|
||||
)
|
||||
@@ -324,7 +367,7 @@ if (MSVC)
|
||||
)
|
||||
list (APPEND win32_Libs
|
||||
${PROJECT_SOURCE_DIR}/../fmt/msvc/Release/fmt.lib
|
||||
${PROJECT_SOURCE_DIR}/../http_parser/x64/Release/http-parser.lib
|
||||
${PROJECT_SOURCE_DIR}/../llhttp/build/Release/llhttp.lib
|
||||
${PROJECT_SOURCE_DIR}/../openssl/libssl.lib
|
||||
${PROJECT_SOURCE_DIR}/../openssl/libcrypto.lib
|
||||
)
|
||||
@@ -356,18 +399,25 @@ else()
|
||||
PRIVATE
|
||||
PkgConfig::argon2
|
||||
PkgConfig::Nettle
|
||||
${HTTP_PARSER_LIBRARY}
|
||||
PUBLIC
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
PkgConfig::GnuTLS
|
||||
fmt::fmt
|
||||
)
|
||||
if (OPENDHT_HTTP)
|
||||
target_link_libraries(opendht PUBLIC ${llhttp_target})
|
||||
endif()
|
||||
if (Jsoncpp_FOUND)
|
||||
target_link_libraries(opendht PUBLIC PkgConfig::Jsoncpp)
|
||||
endif()
|
||||
if (OPENDHT_PROXY_OPENSSL)
|
||||
target_link_libraries(opendht PUBLIC PkgConfig::OPENSSL)
|
||||
endif()
|
||||
if (OPENDHT_IO_URING AND liburing_FOUND)
|
||||
set(iouring_lib ", liburing")
|
||||
target_link_libraries(opendht PUBLIC PkgConfig::liburing)
|
||||
target_compile_definitions(opendht PUBLIC ASIO_HAS_IO_URING ASIO_DISABLE_EPOLL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
|
||||
@@ -98,6 +98,7 @@ for r in results:
|
||||
- Nettle 2.4+, a GnuTLS dependency for crypto.
|
||||
- {fmt} 9.0+, for log formatting.
|
||||
- (optional) restinio used for the REST API.
|
||||
- (optional) llhttp 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 2019, 2022
|
||||
@@ -107,7 +108,7 @@ for r in results:
|
||||
IRC: join us on Libera.chat at [`#opendht`](https://web.libera.chat/#opendht).
|
||||
|
||||
## License
|
||||
Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
Copyright (C) 2014-2025 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.
|
||||
|
||||
@@ -117,4 +118,4 @@ See COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html for the full GPLv3 l
|
||||
|
||||
## Acknowledgements
|
||||
This project was originally based on https://github.com/jech/dht by Juliusz Chroboczek.
|
||||
It is independent from another project called OpenDHT (Sean Rhea. Ph.D. Thesis, 2005), now extinct.
|
||||
It is independent from another (now extinct) project called OpenDHT (Sean Rhea. Ph.D. Thesis, 2005).
|
||||
+24
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -132,8 +132,12 @@ 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_with_id_new(const uint8_t* data, size_t size, uint64_t value_id) {
|
||||
return reinterpret_cast<dht_value*>(new ValueSp(std::make_shared<dht::Value>(dht::ValueType::USER_DATA.id, data, size, value_id)));
|
||||
}
|
||||
|
||||
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)));
|
||||
return dht_value_with_id_new(data, size, 0);
|
||||
}
|
||||
|
||||
dht_value* dht_value_new_from_string(const char* str) {
|
||||
@@ -325,12 +329,13 @@ int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
try {
|
||||
dht::DhtRunner::Config config;
|
||||
config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
|
||||
config.dht_config.node_config.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{};
|
||||
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);
|
||||
@@ -338,14 +343,18 @@ int dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config
|
||||
if (conf->dht_config.id.certificate)
|
||||
config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
|
||||
|
||||
config.threaded = conf->threaded;
|
||||
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
|
||||
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
|
||||
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
|
||||
config.push_topic = conf->push_topic ? std::string(conf->push_topic) : std::string{};
|
||||
config.push_platform = conf->push_platform ? std::string(conf->push_platform) : std::string{};
|
||||
config.peer_discovery = conf->peer_discovery;
|
||||
config.peer_publish = conf->peer_publish;
|
||||
config.threaded = conf->threaded;
|
||||
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
|
||||
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
|
||||
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
|
||||
config.push_topic = conf->push_topic ? std::string(conf->push_topic) : std::string{};
|
||||
config.push_platform = conf->push_platform ? std::string(conf->push_platform) : std::string{};
|
||||
config.proxy_user_agent = conf->proxy_user_agent ? std::string(conf->proxy_user_agent) : std::string{};
|
||||
config.peer_discovery = conf->peer_discovery;
|
||||
config.peer_publish = conf->peer_publish;
|
||||
if (conf->server_ca)
|
||||
config.server_ca = *reinterpret_cast<const CertSp*>(conf->server_ca);
|
||||
config.client_identity = dht_identity_from_c(&conf->client_identity);
|
||||
|
||||
dht::DhtRunner::Context context;
|
||||
if (conf->log) {
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -91,7 +91,7 @@ OPENDHT_C_PUBLIC dht_pkid dht_certificate_get_long_id(const dht_certificate*);
|
||||
OPENDHT_C_PUBLIC dht_publickey* dht_certificate_get_publickey(const dht_certificate*);
|
||||
OPENDHT_C_PUBLIC void dht_certificate_delete(dht_certificate*);
|
||||
|
||||
struct OPENDHT_PUBLIC dht_identity {
|
||||
struct OPENDHT_C_PUBLIC dht_identity {
|
||||
dht_privatekey* privatekey;
|
||||
dht_certificate* certificate;
|
||||
};
|
||||
@@ -104,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_with_id_new(const uint8_t* data, size_t size, uint64_t value_id);
|
||||
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*);
|
||||
@@ -148,6 +149,7 @@ struct OPENDHT_PUBLIC dht_runner_config {
|
||||
const char* push_token;
|
||||
const char* push_topic;
|
||||
const char* push_platform;
|
||||
const char* proxy_user_agent;
|
||||
bool peer_discovery;
|
||||
bool peer_publish;
|
||||
dht_certificate* server_ca;
|
||||
|
||||
+31
-8
@@ -49,10 +49,15 @@ elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if(HAVE_LIBATOMIC)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
#message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -65,14 +70,32 @@ elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
|
||||
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!")
|
||||
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
|
||||
if(HAVE_CXX_LIBATOMICS64)
|
||||
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()
|
||||
endif()
|
||||
|
||||
# Set variable LLVM_ATOMIC_LIB specifying flags for linking against libatomic.
|
||||
if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB)
|
||||
# Use options --push-state, --as-needed and --pop-state if linker is known to support them.
|
||||
# Use single option -Wl of compiler driver to avoid incorrect re-ordering of options by CMake.
|
||||
if(LLVM_LINKER_IS_GNULD OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD OR LLVM_LINKER_IS_MOLD)
|
||||
set(LLVM_ATOMIC_LIB "-Wl,--push-state,--as-needed,-latomic,--pop-state")
|
||||
else()
|
||||
set(LLVM_ATOMIC_LIB "-latomic")
|
||||
endif()
|
||||
else()
|
||||
set(LLVM_ATOMIC_LIB)
|
||||
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.
|
||||
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 3)
|
||||
m4_define([opendht_minor_version], 1)
|
||||
m4_define([opendht_patch_version], 11)
|
||||
m4_define([opendht_minor_version], 4)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
|
||||
@@ -175,11 +175,11 @@ AS_IF([test "x$have_fmt" = "xyes"], [
|
||||
AM_COND_IF([PROXY_CLIENT_OR_SERVER], [
|
||||
AC_CHECK_HEADERS([asio.hpp],, AC_MSG_ERROR([Missing Asio headers files]))
|
||||
CXXFLAGS="${CXXFLAGS} -DASIO_STANDALONE"
|
||||
# http_parser has no pkgconfig, instead we check with:
|
||||
AC_CHECK_LIB(http_parser, exit,, AC_MSG_ERROR([Missing HttpParser library files]))
|
||||
AC_CHECK_HEADERS([http_parser.h], [http_parser_headers=yes; break;])
|
||||
AC_SUBST(http_parser_lib, ["-lhttp_parser"])
|
||||
AS_IF([test "x$http_parser_headers" != "xyes"], AC_MSG_ERROR([Missing HttpParser headers files]))
|
||||
# llhttp has no pkgconfig, instead we check with:
|
||||
AC_CHECK_LIB(llhttp, exit,, AC_MSG_ERROR([Missing llhttp library files]))
|
||||
AC_CHECK_HEADERS([llhttp.h], [llhttp_headers=yes; break;])
|
||||
AC_SUBST(http_lib, ["-lllhttp"])
|
||||
AS_IF([test "x$llhttp_headers" != "xyes"], AC_MSG_ERROR([Missing llhttp headers files]))
|
||||
])
|
||||
|
||||
CXXFLAGS="${CXXFLAGS} -DMSGPACK_NO_BOOST -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
|
||||
|
||||
@@ -19,7 +19,7 @@ RUN cd opendht && mkdir build && cd build \
|
||||
-DOPENDHT_SYSTEMD=On \
|
||||
&& make -j8 && make install
|
||||
|
||||
FROM alpine:3.18 AS install
|
||||
FROM alpine:3.19 AS install
|
||||
COPY --from=build /install /
|
||||
RUN apk add --no-cache \
|
||||
libstdc++ \
|
||||
@@ -28,8 +28,8 @@ RUN apk add --no-cache \
|
||||
openssl \
|
||||
argon2-dev \
|
||||
jsoncpp \
|
||||
llhttp \
|
||||
fmt \
|
||||
http-parser \
|
||||
readline \
|
||||
ncurses
|
||||
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
|
||||
|
||||
+13
-9
@@ -13,18 +13,22 @@ RUN apt-get update && apt-get install -y \
|
||||
python3-pip python3-dev python3-setuptools python3-build python3-virtualenv \
|
||||
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 \
|
||||
libssl-dev libfmt-dev libasio-dev libmsgpack-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
RUN pip3 install meson Cython
|
||||
|
||||
RUN mkdir /usr/include/nonstd \
|
||||
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& ls -l && tar -xzf 6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& cd restinio-6fd08b65f6f15899dd0de3c801f6a5462b811c64/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../../.. && rm -rf restinio
|
||||
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
|
||||
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
|
||||
&& cd restinio-0.7.3/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
|
||||
&& make -j2 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
+14
-10
@@ -1,4 +1,4 @@
|
||||
FROM alpine:3.18
|
||||
FROM alpine:3.19
|
||||
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
|
||||
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
|
||||
|
||||
@@ -8,16 +8,20 @@ RUN apk add --no-cache \
|
||||
ncurses-dev readline-dev nettle-dev \
|
||||
cppunit-dev gnutls-dev jsoncpp-dev \
|
||||
argon2-dev openssl-dev fmt-dev \
|
||||
http-parser-dev asio-dev msgpack-cxx-dev \
|
||||
llhttp-dev asio-dev msgpack-cxx-dev \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN mkdir /usr/include/nonstd \
|
||||
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& tar -xzf 6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& cd restinio-6fd08b65f6f15899dd0de3c801f6a5462b811c64/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../../.. && rm -rf restinio
|
||||
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
|
||||
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
|
||||
&& cd restinio-0.7.3/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
|
||||
&& make -j2 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
@@ -7,7 +7,7 @@ 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 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 \
|
||||
autotools-dev autoconf libfmt-dev libmsgpack-dev libssl-dev python3-pip \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
RUN pip3 install --upgrade cmake meson Cython
|
||||
@@ -20,13 +20,17 @@ RUN echo "** Building a recent version of asio ***" \
|
||||
&& make install \
|
||||
&& cd ../../ && rm -rf asio*
|
||||
|
||||
RUN mkdir /usr/include/nonstd \
|
||||
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& 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 . \
|
||||
&& make -j8 && make install \
|
||||
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
|
||||
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
|
||||
&& cd restinio-0.7.3/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
|
||||
&& make -j2 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
@@ -13,18 +13,22 @@ RUN apt-get update && apt-get install -y \
|
||||
python3-dev python3-setuptools python3-pip \
|
||||
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 \
|
||||
libssl-dev libfmt-dev libasio-dev libmsgpack-dev \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
RUN pip3 install meson Cython
|
||||
|
||||
RUN mkdir /usr/include/nonstd \
|
||||
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
|
||||
&& ls -l && tar -xzf e0a261dd8488246a3cb8bbb3ea781ea5139c3c94.tar.gz \
|
||||
&& cd restinio-e0a261dd8488246a3cb8bbb3ea781ea5139c3c94/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& cd ../../.. && rm -rf restinio
|
||||
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
|
||||
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
|
||||
&& cd restinio-0.7.3/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
|
||||
&& make -j2 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
+15
-11
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:22.04
|
||||
FROM ubuntu:24.04
|
||||
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
|
||||
LABEL org.opencontainers.image.source https://github.com/savoirfairelinux/opendht
|
||||
|
||||
@@ -8,27 +8,31 @@ 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 lldb clang gdb make cmake pkg-config \
|
||||
&& apt-get install -y llvm llvm-dev lldb clang gdb make cmake meson pkg-config \
|
||||
libtool git wget libncurses5-dev libreadline-dev \
|
||||
nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev python3-dev \
|
||||
python3-setuptools libcppunit-dev python3-pip python3-build python3-virtualenv \
|
||||
autotools-dev autoconf libssl-dev libargon2-dev \
|
||||
libfmt-dev libhttp-parser-dev libasio-dev \
|
||||
libfmt-dev libasio-dev \
|
||||
&& apt-get remove -y gcc g++ && apt-get autoremove -y \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
|
||||
|
||||
RUN pip3 install meson Cython
|
||||
RUN pip3 install Cython --break-system-packages
|
||||
|
||||
ENV CC cc
|
||||
ENV CXX c++
|
||||
|
||||
RUN mkdir /usr/include/nonstd \
|
||||
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
|
||||
-O /usr/include/nonstd/expected.hpp
|
||||
|
||||
RUN echo "*** Downloading RESTinio ***" \
|
||||
&& mkdir restinio && cd restinio \
|
||||
&& wget https://github.com/aberaud/restinio/archive/6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& ls -l && tar -xzf 6fd08b65f6f15899dd0de3c801f6a5462b811c64.tar.gz \
|
||||
&& cd restinio-6fd08b65f6f15899dd0de3c801f6a5462b811c64/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
|
||||
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
|
||||
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
|
||||
&& make -j8 && make install \
|
||||
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
|
||||
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
|
||||
&& cd restinio-0.7.3/dev \
|
||||
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
|
||||
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
|
||||
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
|
||||
&& make -j2 && make install \
|
||||
&& cd ../../ && rm -rf restinio*
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -143,6 +143,9 @@ struct OPENDHT_PUBLIC Config {
|
||||
* - Larger listen refresh time
|
||||
*/
|
||||
bool public_stable {false};
|
||||
|
||||
/* Client mode, node will not be used by other nodes to store data. */
|
||||
bool client_mode {false};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -160,6 +163,20 @@ struct OPENDHT_PUBLIC SecureDhtConfig
|
||||
bool cert_cache_all {false};
|
||||
};
|
||||
|
||||
enum class OPENDHT_PUBLIC PushNotificationResult: uint8_t {
|
||||
/* success codes */
|
||||
PutRefresh,
|
||||
ListenRefresh,
|
||||
Values,
|
||||
ValuesExpired,
|
||||
/* ignored/error codes */
|
||||
IgnoredWrongSession = 0x80,
|
||||
IgnoredNoOp,
|
||||
IgnoredStopped,
|
||||
IgnoredDisabled,
|
||||
Error
|
||||
};
|
||||
|
||||
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
|
||||
|
||||
using ValuesExport = std::pair<InfoHash, Blob>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -512,12 +512,18 @@ struct OPENDHT_PUBLIC Certificate {
|
||||
|
||||
Blob getSerialNumber() const;
|
||||
|
||||
/** Read certificate full DN as described in RFC4514 */
|
||||
std::string getDN() const;
|
||||
|
||||
/** Read certificate Common Name (CN) */
|
||||
std::string getName() const;
|
||||
|
||||
/** Read certificate User ID (UID) */
|
||||
std::string getUID() const;
|
||||
|
||||
/** Read certificate issuer DN as described in RFC4514 */
|
||||
std::string getIssuerDN() const;
|
||||
|
||||
/** Read certificate issuer Common Name (CN) */
|
||||
std::string getIssuerName() const;
|
||||
|
||||
@@ -748,7 +754,7 @@ OPENDHT_PUBLIC Blob aesGetSalt(const uint8_t* data, size_t data_length);
|
||||
OPENDHT_PUBLIC Blob inline aesGetSalt(const Blob& data) {
|
||||
return aesGetSalt(data.data(), data.size());
|
||||
}
|
||||
/** Get the encrypted data part of data password-encrypted with `aesEncrypt(data, password)` */
|
||||
/** Get the encrypted data (ciphertext) part of data password-encrypted with `aesEncrypt(data, password)` */
|
||||
OPENDHT_PUBLIC std::string_view aesGetEncrypted(const uint8_t* data, size_t data_length);
|
||||
OPENDHT_PUBLIC std::string_view inline aesGetEncrypted(const Blob& data) {
|
||||
return aesGetEncrypted(data.data(), data.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -315,7 +315,9 @@ public:
|
||||
|
||||
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override;
|
||||
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>&) override {}
|
||||
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>&) override {
|
||||
return PushNotificationResult::IgnoredDisabled;
|
||||
}
|
||||
void resubscribe(unsigned) {}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -262,7 +262,7 @@ public:
|
||||
* Call linked callback with a push notification
|
||||
* @param notification to process
|
||||
*/
|
||||
virtual void pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
|
||||
virtual PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Logger> logger_ {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -53,19 +53,21 @@ public:
|
||||
DhtProxyClient();
|
||||
|
||||
explicit DhtProxyClient(
|
||||
std::shared_ptr<crypto::Certificate> serverCA, crypto::Identity clientIdentity,
|
||||
std::function<void()> loopSignal, const std::string& serverHost,
|
||||
const std::string& pushClientId = "", std::shared_ptr<Logger> logger = {});
|
||||
std::shared_ptr<crypto::Certificate> serverCA,
|
||||
crypto::Identity clientIdentity,
|
||||
std::function<void()> loopSignal,
|
||||
const std::string& serverHost,
|
||||
const std::string& userAgent = "",
|
||||
const std::string& pushClientId = "",
|
||||
const std::string& pushToken = "",
|
||||
const std::string& pushTopic = "",
|
||||
const std::string& pushPlatform = "",
|
||||
std::shared_ptr<Logger> logger = {}
|
||||
);
|
||||
|
||||
void setHeaderFields(http::Request& request);
|
||||
|
||||
virtual void setPushNotificationToken(const std::string& token) override {
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
deviceKey_ = token;
|
||||
#else
|
||||
(void) token;
|
||||
#endif
|
||||
}
|
||||
virtual void setPushNotificationToken(const std::string& token) override;
|
||||
|
||||
virtual void setPushNotificationTopic(const std::string& topic) override {
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
@@ -214,7 +216,7 @@ public:
|
||||
* Call linked callback with a push notification
|
||||
* @param notification to process
|
||||
*/
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>& notification) override;
|
||||
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& notification) override;
|
||||
|
||||
time_point periodic(const uint8_t*, size_t, SockAddr, const time_point& now) override;
|
||||
time_point periodic(const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override {
|
||||
@@ -351,7 +353,7 @@ private:
|
||||
std::string proxyUrl_;
|
||||
dht::crypto::Identity clientIdentity_;
|
||||
std::shared_ptr<dht::crypto::Certificate> serverCertificate_;
|
||||
//std::pair<std::string, std::string> serverHostService_;
|
||||
std::string userAgent_ {"OpenDHT"};
|
||||
std::string pushClientId_;
|
||||
std::string pushSessionId_;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -46,17 +46,17 @@ enum class PushType {
|
||||
}
|
||||
MSGPACK_ADD_ENUM(dht::PushType)
|
||||
|
||||
namespace http {
|
||||
class Request;
|
||||
struct ListenerSession;
|
||||
}
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
}
|
||||
|
||||
namespace dht {
|
||||
|
||||
namespace http {
|
||||
class Request;
|
||||
struct ListenerSession;
|
||||
}
|
||||
|
||||
class DhtRunner;
|
||||
|
||||
using RestRouter = restinio::router::express_router_t<>;
|
||||
@@ -98,6 +98,32 @@ public:
|
||||
|
||||
asio::io_context& io_context() const;
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
|
||||
struct PushStats {
|
||||
uint64_t highPriorityCount {0};
|
||||
uint64_t normalPriorityCount {0};
|
||||
|
||||
void increment(bool highPriority) {
|
||||
if (highPriority)
|
||||
highPriorityCount++;
|
||||
else
|
||||
normalPriorityCount++;
|
||||
}
|
||||
|
||||
Json::Value toJson() const {
|
||||
Json::Value val;
|
||||
val["highPriorityCount"] = static_cast<Json::UInt64>(highPriorityCount);
|
||||
val["normalPriorityCount"] = static_cast<Json::UInt64>(normalPriorityCount);
|
||||
return val;
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
return fmt::format("{} high priority, {} normal priority", highPriorityCount, normalPriorityCount);
|
||||
}
|
||||
};
|
||||
|
||||
struct ServerStats {
|
||||
/** Current number of listen operations */
|
||||
size_t listenCount {0};
|
||||
@@ -107,24 +133,39 @@ public:
|
||||
size_t totalPermanentPuts {0};
|
||||
/** Current number of push tokens with at least one listen operation */
|
||||
size_t pushListenersCount {0};
|
||||
|
||||
/** Time at which the server was started */
|
||||
time_point serverStartTime;
|
||||
/** Last time at which the stats were updated */
|
||||
time_point lastUpdated;
|
||||
/** Total number of push notification requests that the server attempted to
|
||||
* send since being started, broken down by type and priority level */
|
||||
PushStats androidPush;
|
||||
PushStats iosPush;
|
||||
PushStats unifiedPush;
|
||||
|
||||
/** Average requests per second */
|
||||
double requestRate {0};
|
||||
/** Node Info **/
|
||||
std::shared_ptr<NodeInfo> nodeInfo {};
|
||||
|
||||
std::string toString() const {
|
||||
std::ostringstream ss;
|
||||
ss << "Listens: " << listenCount << " Puts: " << putCount << " PushListeners: " << pushListenersCount << std::endl;
|
||||
ss << "Requests: " << requestRate << " per second." << std::endl;
|
||||
auto ret = fmt::format("Listens: {}, Puts: {}, PushListeners: {}\n"
|
||||
"Push requests in the last {}: [Android: {}], [iOS: {}], [Unified: {}]\n"
|
||||
"Requests: {} per second.",
|
||||
listenCount, putCount, pushListenersCount,
|
||||
print_duration(lastUpdated - serverStartTime),
|
||||
androidPush.toString(), iosPush.toString(), unifiedPush.toString(),
|
||||
requestRate);
|
||||
if (nodeInfo) {
|
||||
auto& ipv4 = nodeInfo->ipv4;
|
||||
if (ipv4.table_depth > 1)
|
||||
ss << "IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
|
||||
ret += fmt::format("IPv4 Network estimation: {}\n", ipv4.getNetworkSizeEstimation());
|
||||
auto& ipv6 = nodeInfo->ipv6;
|
||||
if (ipv6.table_depth > 1)
|
||||
ss << "IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
|
||||
ret += fmt::format("IPv6 Network estimation: {}\n", ipv6.getNetworkSizeEstimation());
|
||||
}
|
||||
return ss.str();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,6 +177,11 @@ public:
|
||||
result["putCount"] = static_cast<Json::UInt64>(putCount);
|
||||
result["totalPermanentPuts"] = static_cast<Json::UInt64>(totalPermanentPuts);
|
||||
result["pushListenersCount"] = static_cast<Json::UInt64>(pushListenersCount);
|
||||
result["serverStartTime"] = static_cast<Json::LargestInt>(to_time_t(serverStartTime));
|
||||
result["lastUpdated"] = static_cast<Json::LargestInt>(to_time_t(lastUpdated));
|
||||
result["androidPush"] = androidPush.toJson();
|
||||
result["iosPush"] = iosPush.toJson();
|
||||
result["unifiedPush"] = unifiedPush.toJson();
|
||||
result["requestRate"] = requestRate;
|
||||
if (nodeInfo)
|
||||
result["nodeInfo"] = nodeInfo->toJson();
|
||||
@@ -366,9 +412,6 @@ private:
|
||||
template <typename Is>
|
||||
void loadState(Is& is, size_t size);
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using time_point = clock::time_point;
|
||||
|
||||
std::shared_ptr<asio::io_context> ioContext_;
|
||||
std::shared_ptr<DhtRunner> dht_;
|
||||
Json::StreamWriterBuilder jsonBuilder_;
|
||||
@@ -393,6 +436,11 @@ private:
|
||||
std::shared_ptr<ServerStats> stats_;
|
||||
std::shared_ptr<NodeInfo> nodeInfo_ {};
|
||||
std::unique_ptr<asio::steady_timer> printStatsTimer_;
|
||||
const time_point serverStartTime_;
|
||||
mutable std::mutex pushStatsMutex_;
|
||||
PushStats androidPush_;
|
||||
PushStats iosPush_;
|
||||
PushStats unifiedPush_;
|
||||
|
||||
// Thread-safe access to listeners map.
|
||||
std::mutex lockListener_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
std::string push_token {};
|
||||
std::string push_topic {};
|
||||
std::string push_platform {};
|
||||
std::string proxy_user_agent {};
|
||||
bool peer_discovery {false};
|
||||
bool peer_publish {false};
|
||||
std::shared_ptr<dht::crypto::Certificate> server_ca;
|
||||
@@ -267,11 +268,17 @@ public:
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
[[deprecated("Use the shared_ptr version instead")]]
|
||||
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb={}, bool permanent = false);
|
||||
[[deprecated("Use the shared_ptr version instead")]]
|
||||
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);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert known nodes to the routing table, without necessarly ping them.
|
||||
@@ -383,7 +390,9 @@ public:
|
||||
// securedht methods
|
||||
|
||||
void findCertificate(InfoHash hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
|
||||
void registerCertificate(std::shared_ptr<crypto::Certificate> cert);
|
||||
void findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
|
||||
|
||||
void registerCertificate(const std::shared_ptr<crypto::Certificate>& cert);
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
|
||||
|
||||
/**
|
||||
@@ -409,7 +418,8 @@ public:
|
||||
void run(const Config& config, Context&& context);
|
||||
|
||||
void setOnStatusChanged(StatusCallback&& cb) {
|
||||
statusCb = std::move(cb);
|
||||
if (cb)
|
||||
statusCbs.emplace_back(std::move(cb));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,7 +474,7 @@ public:
|
||||
/**
|
||||
* Insert a push notification to process for OpenDHT
|
||||
*/
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>& data);
|
||||
std::future<PushNotificationResult> pushNotificationReceived(const std::map<std::string, std::string>& data);
|
||||
|
||||
/* Proxy server mothods */
|
||||
void forwardAllMessages(bool forward);
|
||||
@@ -519,7 +529,8 @@ private:
|
||||
|
||||
NodeStatus status4 {NodeStatus::Disconnected},
|
||||
status6 {NodeStatus::Disconnected};
|
||||
StatusCallback statusCb {nullptr};
|
||||
|
||||
std::vector<StatusCallback> statusCbs {};
|
||||
|
||||
/** PeerDiscovery Parameters */
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery_;
|
||||
|
||||
+8
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -29,23 +29,20 @@
|
||||
# define snprintf snprintf
|
||||
#endif
|
||||
|
||||
#include <asio/ip/tcp.hpp>
|
||||
#include <asio/streambuf.hpp>
|
||||
#include <asio/ssl/context.hpp>
|
||||
#include <restinio/http_headers.hpp>
|
||||
#include <restinio/message_builders.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <future>
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct http_parser;
|
||||
struct http_parser_settings;
|
||||
}
|
||||
|
||||
namespace restinio {
|
||||
namespace impl {
|
||||
class tls_socket_t;
|
||||
@@ -75,7 +72,7 @@ class OPENDHT_PUBLIC Url
|
||||
{
|
||||
public:
|
||||
Url() = default;
|
||||
Url(const std::string& url);
|
||||
Url(std::string_view url);
|
||||
std::string url;
|
||||
std::string protocol {"http"};
|
||||
std::string host;
|
||||
@@ -156,17 +153,6 @@ private:
|
||||
bool checkOcsp_ {false};
|
||||
};
|
||||
|
||||
/**
|
||||
* Session value associated with a connection_id_t key.
|
||||
*/
|
||||
struct ListenerSession
|
||||
{
|
||||
ListenerSession() = default;
|
||||
dht::InfoHash hash;
|
||||
std::future<size_t> token;
|
||||
std::shared_ptr<restinio::response_builder_t<restinio::chunked_output_t>> response;
|
||||
};
|
||||
|
||||
/* @class Resolver
|
||||
* @brief The purpose is to only resolve once to avoid mutliple dns requests per operation.
|
||||
*/
|
||||
@@ -338,7 +324,7 @@ private:
|
||||
|
||||
void init_default_headers();
|
||||
/**
|
||||
* Initialized and wraps the http_parser callbacks with our user defined callbacks.
|
||||
* Initialized and wraps the llhttp callbacks with our user defined callbacks.
|
||||
*/
|
||||
void init_parser();
|
||||
|
||||
@@ -380,8 +366,8 @@ private:
|
||||
Response response_ {};
|
||||
std::string request_;
|
||||
std::atomic<bool> finishing_ {false};
|
||||
std::unique_ptr<http_parser> parser_;
|
||||
std::unique_ptr<http_parser_settings> parser_s_;
|
||||
std::unique_ptr<llhttp_t> parser_;
|
||||
std::unique_ptr<llhttp_settings_t> parser_s_;
|
||||
|
||||
// Next request in case of redirect following
|
||||
std::shared_ptr<Request> next_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -409,7 +409,7 @@ private:
|
||||
|
||||
/**
|
||||
* This mutlimap contains all prefix insert in the tree in time order
|
||||
* We could then delete the last one if there is too much node
|
||||
* We could then delete the last one if there are too many nodes
|
||||
* The tree will self destroy is branch ( thanks to share_ptr )
|
||||
*/
|
||||
std::multimap<time_point, std::shared_ptr<Node>> leaves_;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
bool operator!=(const Hash& h) const { return !(*this == h); }
|
||||
|
||||
bool operator<(const Hash& o) const {
|
||||
for(unsigned i = 0; i < N; i++) {
|
||||
for (unsigned i = 0; i < N; i++) {
|
||||
if(data_[i] != o.data_[i])
|
||||
return data_[i] < o.data_[i];
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
|
||||
Hash operator^(const Hash& o) const {
|
||||
Hash result;
|
||||
for(auto i = 0u; i < N; i++) {
|
||||
for (auto i = 0u; i < N; i++) {
|
||||
result[i] = data_[i] ^ o.data_[i];
|
||||
}
|
||||
return result;
|
||||
@@ -345,8 +345,8 @@ Hash<N>::getRandom(Rd& rdev)
|
||||
}
|
||||
|
||||
struct alignas(std::max_align_t) HexMap : public std::array<std::array<char, 2>, 256> {
|
||||
HexMap() {
|
||||
for (size_t i=0; i<size(); i++) {
|
||||
constexpr HexMap() : std::array<std::array<char, 2>, 256>() {
|
||||
for (size_t i = 0; i < size(); i++) {
|
||||
auto& e = (*this)[i];
|
||||
e[0] = hex_digits[(i >> 4) & 0x0F];
|
||||
e[1] = hex_digits[i & 0x0F];
|
||||
@@ -356,7 +356,7 @@ private:
|
||||
static constexpr const char* hex_digits = "0123456789abcdef";
|
||||
};
|
||||
|
||||
OPENDHT_PUBLIC extern const HexMap hex_map;
|
||||
OPENDHT_PUBLIC constexpr HexMap hex_map = {};
|
||||
|
||||
inline std::string
|
||||
toHex(const uint8_t* data, size_t size) {
|
||||
@@ -380,10 +380,11 @@ Hash<N>::to_c_str() const
|
||||
{
|
||||
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;
|
||||
auto b = buf.data() + i*2;
|
||||
const auto& m = hex_map[data_[i]];
|
||||
*((uint16_t*)b) = *((uint16_t*)&m);
|
||||
}
|
||||
buf[N*2] = '\0';
|
||||
return buf.data();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -52,6 +52,7 @@ struct NetworkConfig {
|
||||
NetId network {0};
|
||||
ssize_t max_req_per_sec {0};
|
||||
ssize_t max_peer_req_per_sec {0};
|
||||
bool is_client {false};
|
||||
};
|
||||
|
||||
class DhtProtocolException : public DhtException {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -23,7 +23,9 @@
|
||||
#include "sockaddr.h"
|
||||
#include "infohash.h"
|
||||
#include "logger.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <asio/steady_timer.hpp>
|
||||
#include <thread>
|
||||
|
||||
namespace asio {
|
||||
@@ -36,31 +38,34 @@ class OPENDHT_PUBLIC PeerDiscovery
|
||||
{
|
||||
public:
|
||||
static constexpr in_port_t DEFAULT_PORT = 8888;
|
||||
using ServiceDiscoveredCallback = std::function<void(msgpack::object&&, SockAddr&&)>;
|
||||
using ServiceDiscoveredCallback = std::function<void(msgpack::object &&, SockAddr &&)>;
|
||||
|
||||
PeerDiscovery(in_port_t port = DEFAULT_PORT, std::shared_ptr<asio::io_context> ioContext = {}, std::shared_ptr<Logger> logger = {});
|
||||
PeerDiscovery(in_port_t port = DEFAULT_PORT,
|
||||
std::shared_ptr<asio::io_context> ioContext = {},
|
||||
std::shared_ptr<Logger> logger = {});
|
||||
~PeerDiscovery();
|
||||
|
||||
/**
|
||||
* startDiscovery - Keep Listening data from the sender until node is joinned or stop is called
|
||||
*/
|
||||
void startDiscovery(const std::string &type, ServiceDiscoveredCallback callback);
|
||||
* startDiscovery - Keep Listening data from the sender until node is joinned
|
||||
* or stop is called
|
||||
*/
|
||||
void startDiscovery(std::string_view type, ServiceDiscoveredCallback callback);
|
||||
|
||||
template<typename T>
|
||||
void startDiscovery(const std::string &type, std::function<void(T&&, SockAddr&&)> cb) {
|
||||
startDiscovery(type, [cb](msgpack::object&& ob, SockAddr&& addr) {
|
||||
template <typename T>
|
||||
void startDiscovery(std::string_view type, std::function<void(T &&, SockAddr &&)> cb) {
|
||||
startDiscovery(type, [cb](msgpack::object &&ob, SockAddr &&addr) {
|
||||
cb(ob.as<T>(), std::move(addr));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* startPublish - Keeping sending data until node is joinned or stop is called
|
||||
*/
|
||||
void startPublish(const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
void startPublish(sa_family_t domain, const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
*/
|
||||
void startPublish(std::string_view type, const msgpack::sbuffer &pack_buf);
|
||||
void startPublish(sa_family_t domain, std::string_view type, const msgpack::sbuffer &pack_buf);
|
||||
|
||||
template<typename T>
|
||||
void startPublish(const std::string &type, const T& object) {
|
||||
template <typename T>
|
||||
void startPublish(std::string_view type, const T &object) {
|
||||
msgpack::sbuffer buf;
|
||||
msgpack::pack(buf, object);
|
||||
startPublish(type, buf);
|
||||
@@ -68,22 +73,24 @@ public:
|
||||
|
||||
/**
|
||||
* Thread Stopper
|
||||
*/
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Remove possible callBack to discovery
|
||||
*/
|
||||
bool stopDiscovery(const std::string &type);
|
||||
*/
|
||||
bool stopDiscovery(std::string_view type);
|
||||
|
||||
/**
|
||||
* Remove different serivce message to send
|
||||
*/
|
||||
bool stopPublish(const std::string &type);
|
||||
bool stopPublish(sa_family_t domain, const std::string &type);
|
||||
*/
|
||||
bool stopPublish(std::string_view type);
|
||||
bool stopPublish(sa_family_t domain, std::string_view type);
|
||||
|
||||
void connectivityChanged();
|
||||
|
||||
void stopConnectivityChanged();
|
||||
|
||||
private:
|
||||
class DomainPeerDiscovery;
|
||||
std::unique_ptr<DomainPeerDiscovery> peerDiscovery4_;
|
||||
@@ -92,4 +99,4 @@ private:
|
||||
std::thread ioRunnner_;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace dht
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -24,7 +24,7 @@ namespace proxy {
|
||||
|
||||
constexpr const std::chrono::hours OP_TIMEOUT {24}; // one day
|
||||
constexpr const std::chrono::hours OP_MARGIN {2}; // two hours
|
||||
constexpr const char* const HTTP_PROTO {"http://"};
|
||||
|
||||
using ListenToken = uint64_t;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -115,14 +115,20 @@ public:
|
||||
* The operation will be immediate if the recipient' public key is known (otherwise it will be retrived first).
|
||||
*/
|
||||
void putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
|
||||
|
||||
[[deprecated("Use the shared_ptr version instead")]]
|
||||
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);
|
||||
|
||||
[[deprecated("Use the shared_ptr version instead")]]
|
||||
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);
|
||||
}
|
||||
|
||||
void putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
|
||||
|
||||
/**
|
||||
* Take ownership of the value and sign it using our private key.
|
||||
*/
|
||||
@@ -135,12 +141,17 @@ public:
|
||||
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<crypto::PublicKey>)>& cb);
|
||||
|
||||
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
void registerCertificate(Sp<crypto::Certificate>& cert);
|
||||
void findCertificate(const PkId& id, const std::function<void(const Sp<crypto::Certificate>)>& cb);
|
||||
void findPublicKey(const PkId& id, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
|
||||
|
||||
void registerCertificate(const Sp<crypto::Certificate>& cert);
|
||||
|
||||
Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
|
||||
Sp<crypto::Certificate> getCertificate(const PkId& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const PkId& node) const;
|
||||
|
||||
/**
|
||||
* Allows to set a custom callback called by the library to find a locally-stored certificate.
|
||||
* The search key used is the public key ID, so there may be multiple certificates retured, signed with
|
||||
@@ -328,8 +339,8 @@ public:
|
||||
* Call linked callback with push_notification
|
||||
* @param notification to process
|
||||
*/
|
||||
void pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
|
||||
dht_->pushNotificationReceived(notification);
|
||||
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
|
||||
return dht_->pushNotificationReceived(notification);
|
||||
}
|
||||
|
||||
void setLogger(const Logger& logger) override {
|
||||
@@ -360,6 +371,9 @@ private:
|
||||
ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
|
||||
GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
|
||||
|
||||
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
|
||||
Sp<crypto::Certificate> registerCertificate(const PkId& node, const Blob& cert);
|
||||
|
||||
Sp<crypto::PrivateKey> key_ {};
|
||||
Sp<crypto::Certificate> certificate_ {};
|
||||
|
||||
@@ -369,6 +383,8 @@ private:
|
||||
// our certificate cache
|
||||
std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
|
||||
std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
|
||||
std::map<PkId, Sp<crypto::Certificate>> nodesCertificatesLong_ {};
|
||||
std::map<PkId, Sp<crypto::PublicKey>> nodesPubKeysLong_ {};
|
||||
|
||||
std::atomic_bool forward_all_ {false};
|
||||
bool enableCache_ {false};
|
||||
@@ -387,7 +403,7 @@ const ValueType CERTIFICATE_TYPE = {
|
||||
},
|
||||
[](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
|
||||
try {
|
||||
return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
|
||||
return crypto::Certificate(o->data).getPublicKey().getLongId() == crypto::Certificate(n->data).getPublicKey().getLongId();
|
||||
} catch (const std::exception& e) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
+10
-23
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "def.h"
|
||||
|
||||
#include <msgpack.hpp>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
@@ -60,7 +61,7 @@ void erase_if(std::map<Key, Item>& map, const Condition& condition)
|
||||
* Split "[host]:port" or "host:port" to pair<"host", "port">.
|
||||
*/
|
||||
OPENDHT_PUBLIC std::pair<std::string, std::string>
|
||||
splitPort(const std::string& s);
|
||||
splitPort(std::string_view s);
|
||||
|
||||
class OPENDHT_PUBLIC DhtException : public std::runtime_error {
|
||||
public:
|
||||
@@ -84,37 +85,23 @@ using duration = clock::duration;
|
||||
time_point from_time_t(std::time_t t);
|
||||
std::time_t to_time_t(time_point t);
|
||||
|
||||
inline std::string
|
||||
to_str(double d) {
|
||||
char buf[16];
|
||||
auto ret = snprintf(buf, sizeof(buf), "%.3g", d);
|
||||
return (ret < 0) ? std::to_string(d) : std::string(buf, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts std::chrono::duration to floating-point seconds.
|
||||
*/
|
||||
template <class DT>
|
||||
static double
|
||||
print_dt(DT d) {
|
||||
return std::chrono::duration_cast<std::chrono::duration<double>>(d).count();
|
||||
}
|
||||
|
||||
template <class DT>
|
||||
static std::string
|
||||
print_duration(DT d) {
|
||||
if (d < std::chrono::seconds(0)) {
|
||||
return "-" + print_duration(-d);
|
||||
} else if (d < std::chrono::milliseconds(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count()) + " us";
|
||||
return fmt::format("{:.3g} us", std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count());
|
||||
} else if (d < std::chrono::seconds(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count()) + " ms";
|
||||
return fmt::format("{:.3g} ms", std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count());
|
||||
} else if (d < std::chrono::minutes(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double>>(d).count()) + " s";
|
||||
return fmt::format("{:.3g} s", std::chrono::duration_cast<std::chrono::duration<double>>(d).count());
|
||||
} else if (d < std::chrono::hours(1)) {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<60>>>(d).count()) + " min";
|
||||
return fmt::format("{:.3g} min", std::chrono::duration_cast<std::chrono::duration<double, std::ratio<60>>>(d).count());
|
||||
} else if (d < std::chrono::hours(72)) {
|
||||
return fmt::format("{:.3g} h", std::chrono::duration_cast<std::chrono::duration<double, std::ratio<3600>>>(d).count());
|
||||
} else {
|
||||
return to_str(std::chrono::duration_cast<std::chrono::duration<double, std::ratio<3600>>>(d).count()) + " h";
|
||||
return fmt::format("{:.3g} days", std::chrono::duration_cast<std::chrono::duration<double, std::ratio<86400>>>(d).count());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -137,8 +137,6 @@ private:
|
||||
std::map<ValueType::Id, ValueType> types {};
|
||||
};
|
||||
|
||||
struct CryptoValueCache;
|
||||
|
||||
/**
|
||||
* A "value" is data potentially stored on the Dht, with some metadata.
|
||||
*
|
||||
|
||||
+13
-15
@@ -1,5 +1,5 @@
|
||||
project('opendht', 'c', 'cpp', 'cython',
|
||||
version: '3.1.11',
|
||||
version: '3.4.0',
|
||||
default_options: [
|
||||
'cpp_std=c++17',
|
||||
'warning_level=3'
|
||||
@@ -12,17 +12,17 @@ argon2 = dependency('libargon2')
|
||||
openssl = dependency('openssl', required: get_option('proxy_client'))
|
||||
jsoncpp = dependency('jsoncpp', required: get_option('proxy_client'))
|
||||
fmt = dependency('fmt')
|
||||
llhttp = dependency('llhttp', 'libllhttp', required: get_option('proxy_client'))
|
||||
io_uring = dependency('liburing', required: false)
|
||||
|
||||
dirs=[]
|
||||
if host_machine.system() == 'freebsd'
|
||||
dirs+='/usr/local/lib'
|
||||
elif host_machine.system() == 'darwin'
|
||||
dirs+='/opt/homebrew/lib'
|
||||
deps = [fmt, gnutls, nettle, msgpack, argon2, openssl, jsoncpp, llhttp, io_uring]
|
||||
conf_data = configuration_data()
|
||||
|
||||
add_project_arguments('-DMSGPACK_NO_BOOST', '-DASIO_STANDALONE', language : 'cpp')
|
||||
if io_uring.found()
|
||||
add_project_arguments('-DASIO_HAS_IO_URING', '-DASIO_DISABLE_EPOLL', language : 'cpp')
|
||||
conf_data.set('iouring_lib', ', liburing')
|
||||
endif
|
||||
http_parser = meson.get_compiler('c').find_library('http_parser', dirs: dirs, required: get_option('proxy_client'))
|
||||
deps = [fmt, gnutls, nettle, msgpack, argon2, openssl, jsoncpp, http_parser]
|
||||
|
||||
add_project_arguments('-DMSGPACK_NO_BOOST', language : 'cpp')
|
||||
add_project_arguments(['-Wno-return-type','-Wno-deprecated','-Wnon-virtual-dtor','-pedantic-errors','-fvisibility=hidden'], language : 'cpp')
|
||||
|
||||
opendht_inc = include_directories('include/opendht')
|
||||
@@ -46,8 +46,6 @@ opendht_src = [
|
||||
'src/thread_pool.cpp',
|
||||
]
|
||||
|
||||
conf_data = configuration_data()
|
||||
|
||||
if get_option('indexation').enabled()
|
||||
opendht_src += 'src/indexation/pht.cpp'
|
||||
add_project_arguments('-DOPENDHT_INDEXATION', language : 'cpp')
|
||||
@@ -57,12 +55,12 @@ if jsoncpp.found()
|
||||
add_project_arguments('-DOPENDHT_JSONCPP', language : 'cpp')
|
||||
conf_data.set('jsoncpp_lib', ', jsoncpp')
|
||||
endif
|
||||
if http_parser.found()
|
||||
if llhttp.found()
|
||||
opendht_src += ['src/http.cpp', 'src/compat/os_cert.cpp']
|
||||
if host_machine.system() == 'darwin'
|
||||
deps+=dependency('appleframeworks', modules : ['CoreFoundation', 'Security'])
|
||||
endif
|
||||
conf_data.set('http_lib', '-lhttp_parser')
|
||||
conf_data.set('http_lib', '-lllhttp')
|
||||
endif
|
||||
if openssl.found()
|
||||
conf_data.set('openssl_lib', ', openssl')
|
||||
@@ -158,7 +156,7 @@ if get_option('tools').enabled()
|
||||
link_with : opendht,
|
||||
dependencies : [readline, jsoncpp, msgpack, fmt, openssl],
|
||||
install : true)
|
||||
if http_parser.found()
|
||||
if llhttp.found()
|
||||
durl = executable('durl', 'tools/durl.cpp',
|
||||
include_directories : opendht_interface_inc,
|
||||
link_with : opendht,
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ Name: OpenDHT
|
||||
Description: C++17 Distributed Hash Table library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lopendht
|
||||
Libs.private: @http_parser_lib@ -pthread
|
||||
Libs.private: @http_lib@ -pthread
|
||||
Requires: gnutls >= 3.3@jsoncpp_lib@@openssl_lib@
|
||||
Requires.private: nettle >= 2.4@argon2_lib@
|
||||
Requires.private: nettle >= 2.4@argon2_lib@@iouring_lib@
|
||||
Cflags: -I${includedir}
|
||||
+2
-1
@@ -500,12 +500,13 @@ cdef class DhtConfig(object):
|
||||
def setRateLimit(self, ssize_t max_req_per_sec, ssize_t max_peer_req_per_sec):
|
||||
self._config.dht_config.node_config.max_req_per_sec = max_req_per_sec
|
||||
self._config.dht_config.node_config.max_peer_req_per_sec = max_peer_req_per_sec
|
||||
def setProxyInfo(self, str proxy_server, str push_node_id="", str push_token="", str push_topic="", str push_platform="", Certificate server_ca = Certificate()):
|
||||
def setProxyInfo(self, str proxy_server, str push_node_id="", str push_token="", str push_topic="", str push_platform="", str user_agent="", Certificate server_ca = Certificate()):
|
||||
self._config.proxy_server = proxy_server.encode()
|
||||
self._config.push_node_id = push_node_id.encode()
|
||||
self._config.push_token = push_token.encode()
|
||||
self._config.push_topic = push_topic.encode()
|
||||
self._config.push_platform = push_platform.encode()
|
||||
self._config.proxy_user_agent = user_agent.encode()
|
||||
self._config.server_ca = server_ca._cert
|
||||
def setPeerDiscovery(self, bool peer_discovery, bool peer_publish):
|
||||
self._config.peer_discovery = peer_discovery
|
||||
|
||||
@@ -246,6 +246,7 @@ cdef extern from "opendht/dhtrunner.h" namespace "dht":
|
||||
string push_token
|
||||
string push_topic
|
||||
string push_platform
|
||||
string proxy_user_agent
|
||||
bool peer_discovery
|
||||
bool peer_publish
|
||||
shared_ptr[Certificate] server_ca
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
|
||||
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2025 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) 2014-2023 Savoir-faire Linux Inc.
|
||||
# Copyright (C) 2014-2025 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
|
||||
|
||||
+5
-5
@@ -2,10 +2,10 @@
|
||||
name = "opendht"
|
||||
version = "0.1.0"
|
||||
authors = ["Sébastien Blin <sebastien.blin@savoirfairelinux.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
libc="0.2.0"
|
||||
os_socketaddr="0.2.3"
|
||||
libc="0.2"
|
||||
os_socketaddr="0.2.3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+15
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -49,6 +49,7 @@ impl DhtRunnerConfig {
|
||||
push_token: ptr::null(),
|
||||
push_topic: ptr::null(),
|
||||
push_platform: ptr::null(),
|
||||
proxy_user_agent: ptr::null(),
|
||||
peer_discovery: false,
|
||||
peer_publish: false,
|
||||
server_ca: ptr::null_mut(),
|
||||
@@ -56,6 +57,7 @@ impl DhtRunnerConfig {
|
||||
privatekey: ptr::null_mut(),
|
||||
certificate: ptr::null_mut(),
|
||||
},
|
||||
log: true,
|
||||
});
|
||||
unsafe {
|
||||
dht_runner_config_default(&mut *config);
|
||||
@@ -64,23 +66,27 @@ impl DhtRunnerConfig {
|
||||
}
|
||||
|
||||
pub fn set_proxy_server(&mut self, proxy_server: &str) {
|
||||
self.proxy_server = CString::new(proxy_server).unwrap().as_ptr();
|
||||
self.proxy_server = CString::new(proxy_server).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_push_node_id(&mut self, push_node_id: &str) {
|
||||
self.push_node_id = CString::new(push_node_id).unwrap().as_ptr();
|
||||
self.push_node_id = CString::new(push_node_id).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_push_token(&mut self, push_token: &str) {
|
||||
self.push_token = CString::new(push_token).unwrap().as_ptr();
|
||||
self.push_token = CString::new(push_token).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_push_topic(&mut self, push_topic: &str) {
|
||||
self.push_topic = CString::new(push_topic).unwrap().as_ptr();
|
||||
self.push_topic = CString::new(push_topic).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_push_platform(&mut self, push_platform: &str) {
|
||||
self.push_platform = CString::new(push_platform).unwrap().as_ptr();
|
||||
self.push_platform = CString::new(push_platform).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_proxy_user_agent(&mut self, proxy_user_agent: &str) {
|
||||
self.proxy_user_agent = CString::new(proxy_user_agent).unwrap().into_raw();
|
||||
}
|
||||
|
||||
pub fn set_identity(&mut self, certificate: Box<DhtCertificate>, privatekey: Box<PrivateKey>) {
|
||||
@@ -93,7 +99,7 @@ impl DhtRunnerConfig {
|
||||
impl DhtNodeConfig
|
||||
{
|
||||
pub fn set_persist_path(&mut self, persist_path: &str) {
|
||||
self.persist_path = CString::new(persist_path).unwrap().as_ptr();
|
||||
self.persist_path = CString::new(persist_path).unwrap().into_raw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,8 +203,8 @@ impl DhtRunner {
|
||||
pub fn bootstrap(&mut self, host: &str, service: u16) {
|
||||
unsafe {
|
||||
dht_runner_bootstrap(&mut *self,
|
||||
CString::new(host).unwrap().as_ptr(),
|
||||
CString::new(service.to_string()).unwrap().as_ptr())
|
||||
CString::new(host).unwrap().into_raw(),
|
||||
CString::new(service.to_string()).unwrap().into_raw())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -120,13 +120,14 @@ pub struct DhtRunnerConfig
|
||||
pub push_token: *const c_char,
|
||||
pub push_topic: *const c_char,
|
||||
pub push_platform: *const c_char,
|
||||
pub proxy_user_agent: *const c_char,
|
||||
pub peer_discovery: bool,
|
||||
pub peer_publish: bool,
|
||||
pub server_ca: *mut DhtCertificate,
|
||||
pub client_identity: DhtIdentity,
|
||||
pub log: bool,
|
||||
}
|
||||
|
||||
|
||||
#[link(name = "opendht-c")]
|
||||
extern {
|
||||
// dht::Value
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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,39 @@
|
||||
//Code from getifaddrs.3 man
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <net/if.h>
|
||||
#include <asio.hpp>
|
||||
#include <stdexcept>
|
||||
namespace dht{
|
||||
namespace workaround{
|
||||
|
||||
asio::ip::address_v4
|
||||
get_interface(){
|
||||
struct ifaddrs *ifaddr;
|
||||
if(getifaddrs(&ifaddr) == -1){
|
||||
throw std::runtime_error("Can't getifaddrs");
|
||||
}
|
||||
for (struct ifaddrs *if1 = ifaddr; if1 != NULL; if1 = if1->ifa_next){
|
||||
if (if1->ifa_addr == NULL)
|
||||
continue;
|
||||
if (if1->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
if((if1->ifa_flags & IFF_MULTICAST) == IFF_MULTICAST){
|
||||
auto sa_data = reinterpret_cast<uint8_t*>(if1->ifa_addr->sa_data);
|
||||
uint32_t value = sa_data[2] << 24
|
||||
| sa_data[3] << 16
|
||||
| sa_data[4] << 8
|
||||
| sa_data[5];
|
||||
freeifaddrs(ifaddr);
|
||||
return asio::ip::address_v4(value);
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddr);
|
||||
throw std::runtime_error("Can't find a interface which supports multicast");
|
||||
}
|
||||
|
||||
} /* namespace workaround */
|
||||
} /* namespace dht */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
File renamed without changes.
File renamed without changes.
+149
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
@@ -93,11 +93,27 @@ Blob aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
std::random_device rdev;
|
||||
std::generate_n(ret.begin(), GCM_IV_SIZE, std::bind(rand_byte, std::ref(rdev)));
|
||||
}
|
||||
struct gcm_aes_ctx aes;
|
||||
gcm_aes_set_key(&aes, key.size(), key.data());
|
||||
gcm_aes_set_iv(&aes, GCM_IV_SIZE, ret.data());
|
||||
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);
|
||||
|
||||
if (key.size() == AES_LENGTHS[0]) {
|
||||
struct gcm_aes128_ctx aes;
|
||||
gcm_aes128_set_key(&aes, key.data());
|
||||
gcm_aes128_set_iv(&aes, GCM_IV_SIZE, ret.data());
|
||||
gcm_aes128_encrypt(&aes, data_length, ret.data() + GCM_IV_SIZE, data);
|
||||
gcm_aes128_digest(&aes, GCM_DIGEST_SIZE, ret.data() + GCM_IV_SIZE + data_length);
|
||||
} else if (key.size() == AES_LENGTHS[1]) {
|
||||
struct gcm_aes192_ctx aes;
|
||||
gcm_aes192_set_key(&aes, key.data());
|
||||
gcm_aes192_set_iv(&aes, GCM_IV_SIZE, ret.data());
|
||||
gcm_aes192_encrypt(&aes, data_length, ret.data() + GCM_IV_SIZE, data);
|
||||
gcm_aes192_digest(&aes, GCM_DIGEST_SIZE, ret.data() + GCM_IV_SIZE + data_length);
|
||||
} else if (key.size() == AES_LENGTHS[2]) {
|
||||
struct gcm_aes256_ctx aes;
|
||||
gcm_aes256_set_key(&aes, key.data());
|
||||
gcm_aes256_set_iv(&aes, GCM_IV_SIZE, ret.data());
|
||||
gcm_aes256_encrypt(&aes, data_length, ret.data() + GCM_IV_SIZE, data);
|
||||
gcm_aes256_digest(&aes, GCM_DIGEST_SIZE, ret.data() + GCM_IV_SIZE + data_length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,14 +134,28 @@ Blob aesDecrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
|
||||
std::array<uint8_t, GCM_DIGEST_SIZE> digest;
|
||||
|
||||
struct gcm_aes_ctx aes;
|
||||
gcm_aes_set_key(&aes, key.size(), key.data());
|
||||
gcm_aes_set_iv(&aes, GCM_IV_SIZE, data);
|
||||
|
||||
size_t data_sz = data_length - GCM_IV_SIZE - GCM_DIGEST_SIZE;
|
||||
Blob ret(data_sz);
|
||||
gcm_aes_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
|
||||
if (key.size() == AES_LENGTHS[0]) {
|
||||
struct gcm_aes128_ctx aes;
|
||||
gcm_aes128_set_key(&aes, key.data());
|
||||
gcm_aes128_set_iv(&aes, GCM_IV_SIZE, data);
|
||||
gcm_aes128_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
gcm_aes128_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
} else if (key.size() == AES_LENGTHS[1]) {
|
||||
struct gcm_aes192_ctx aes;
|
||||
gcm_aes192_set_key(&aes, key.data());
|
||||
gcm_aes192_set_iv(&aes, GCM_IV_SIZE, data);
|
||||
gcm_aes192_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
gcm_aes192_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
} else if (key.size() == AES_LENGTHS[2]) {
|
||||
struct gcm_aes256_ctx aes;
|
||||
gcm_aes256_set_key(&aes, key.data());
|
||||
gcm_aes256_set_iv(&aes, GCM_IV_SIZE, data);
|
||||
gcm_aes256_decrypt(&aes, data_sz, ret.data(), data + GCM_IV_SIZE);
|
||||
gcm_aes256_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
}
|
||||
|
||||
if (not std::equal(digest.begin(), digest.end(), data + data_length - GCM_DIGEST_SIZE)) {
|
||||
throw DecryptError("Can't decrypt data");
|
||||
@@ -227,7 +257,7 @@ PrivateKey::PrivateKey(const uint8_t* src, size_t src_size, const char* password
|
||||
throw CryptoException("Can't initialize private key !");
|
||||
|
||||
const gnutls_datum_t dt {(uint8_t*)src, static_cast<unsigned>(src_size)};
|
||||
int flags = password_ptr ? GNUTLS_PKCS_PLAIN
|
||||
int flags = (password_ptr == NULL || strlen(password_ptr)==0) ? GNUTLS_PKCS_PLAIN
|
||||
: ( GNUTLS_PKCS_PBES2_AES_128 | GNUTLS_PKCS_PBES2_AES_192 | GNUTLS_PKCS_PBES2_AES_256
|
||||
| GNUTLS_PKCS_PKCS12_3DES | GNUTLS_PKCS_PKCS12_ARCFOUR | GNUTLS_PKCS_PKCS12_RC2_40);
|
||||
|
||||
@@ -616,7 +646,7 @@ GnuTLSFromType(NameType type)
|
||||
}
|
||||
|
||||
static std::string
|
||||
getDN(gnutls_x509_crq_t request, const char* oid)
|
||||
readDN(gnutls_x509_crq_t request, const char* oid)
|
||||
{
|
||||
std::string dn;
|
||||
dn.resize(512);
|
||||
@@ -674,13 +704,13 @@ CertificateRequest::setName(const std::string& name)
|
||||
std::string
|
||||
CertificateRequest::getName() const
|
||||
{
|
||||
return getDN(request, GNUTLS_OID_X520_COMMON_NAME);
|
||||
return readDN(request, GNUTLS_OID_X520_COMMON_NAME);
|
||||
}
|
||||
|
||||
std::string
|
||||
CertificateRequest::getUID() const
|
||||
{
|
||||
return getDN(request, GNUTLS_OID_LDAP_UID);
|
||||
return readDN(request, GNUTLS_OID_LDAP_UID);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -739,7 +769,21 @@ CertificateRequest::toString() const
|
||||
// Certificate
|
||||
|
||||
static std::string
|
||||
getDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false)
|
||||
readDN(gnutls_x509_crt_t cert, bool issuer = false)
|
||||
{
|
||||
gnutls_datum_t dn;
|
||||
int err = issuer
|
||||
? gnutls_x509_crt_get_issuer_dn3(cert, &dn, 0)
|
||||
: gnutls_x509_crt_get_dn3( cert, &dn, 0);
|
||||
if (err != GNUTLS_E_SUCCESS)
|
||||
return {};
|
||||
std::string ret((const char*)dn.data, dn.size);
|
||||
gnutls_free(dn.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string
|
||||
readDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false)
|
||||
{
|
||||
std::string dn;
|
||||
dn.resize(512);
|
||||
@@ -897,28 +941,40 @@ Certificate::getSerialNumber() const
|
||||
return {serial, serial + size};
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getDN() const
|
||||
{
|
||||
return readDN(cert);
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getName() const
|
||||
{
|
||||
return getDN(cert, GNUTLS_OID_X520_COMMON_NAME);
|
||||
return readDN(cert, GNUTLS_OID_X520_COMMON_NAME);
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getUID() const
|
||||
{
|
||||
return getDN(cert, GNUTLS_OID_LDAP_UID);
|
||||
return readDN(cert, GNUTLS_OID_LDAP_UID);
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getIssuerDN() const
|
||||
{
|
||||
return readDN(cert, true);
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getIssuerName() const
|
||||
{
|
||||
return getDN(cert, GNUTLS_OID_X520_COMMON_NAME, true);
|
||||
return readDN(cert, GNUTLS_OID_X520_COMMON_NAME, true);
|
||||
}
|
||||
|
||||
std::string
|
||||
Certificate::getIssuerUID() const
|
||||
{
|
||||
return getDN(cert, GNUTLS_OID_LDAP_UID, true);
|
||||
return readDN(cert, GNUTLS_OID_LDAP_UID, true);
|
||||
}
|
||||
|
||||
std::vector<std::pair<NameType, std::string>>
|
||||
@@ -1134,11 +1190,17 @@ saveIdentity(const Identity& id, const std::string& path, const std::string& pri
|
||||
auto ca_key_data = id.first->serialize(privkey_password);
|
||||
std::ofstream key_file(path + ".pem");
|
||||
key_file.write((char*)ca_key_data.data(), ca_key_data.size());
|
||||
// Throw error if the file is not written
|
||||
if (!key_file)
|
||||
throw CryptoException("Could not write private key file");
|
||||
}
|
||||
{
|
||||
auto ca_key_data = id.second->getPacked();
|
||||
std::ofstream crt_file(path + ".crt");
|
||||
crt_file.write((char*)ca_key_data.data(), ca_key_data.size());
|
||||
// Throw error if the file is not written
|
||||
if (!crt_file)
|
||||
throw CryptoException("Could not write certificate file");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1152,12 +1214,19 @@ loadIdentity(const std::string &path,const std::string &privkey_password)
|
||||
pkStream.close();
|
||||
// Create a certificate
|
||||
gnutls_x509_crt_t gnuCert;
|
||||
if (gnutls_x509_crt_init(&gnuCert) != GNUTLS_E_SUCCESS)
|
||||
if (gnutls_x509_crt_init(&gnuCert))
|
||||
throw std::runtime_error("Failed to initialize gnutls certificate struct");
|
||||
gnutls_datum_t crtContent {nullptr, 0};
|
||||
|
||||
// Read the certificate file
|
||||
gnutls_load_file((path + ".crt").c_str(), &crtContent);
|
||||
gnutls_x509_crt_import(gnuCert, &crtContent, GNUTLS_X509_FMT_PEM);
|
||||
int err = gnutls_load_file((path + ".crt").c_str(), &crtContent);
|
||||
if (err)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
|
||||
err = gnutls_x509_crt_import(gnuCert, &crtContent, GNUTLS_X509_FMT_PEM);
|
||||
if (err)
|
||||
throw CryptoException(gnutls_strerror(err));
|
||||
|
||||
auto cert = std::make_shared<Certificate>(gnuCert);
|
||||
return {std::move(key), std::move(cert)};
|
||||
}
|
||||
@@ -1204,31 +1273,49 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden
|
||||
auto pk_id = pk.getId();
|
||||
const std::string uid_str = pk_id.toString();
|
||||
|
||||
gnutls_x509_crt_set_subject_key_id(cert, &pk_id, sizeof(pk_id));
|
||||
gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, name.data(), name.length());
|
||||
gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_LDAP_UID, 0, uid_str.data(), uid_str.length());
|
||||
int err = gnutls_x509_crt_set_subject_key_id(cert, &pk_id, sizeof(pk_id));
|
||||
if(err) {
|
||||
throw CryptoException(std::string("Error when setting subject key id ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
err = gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, name.data(), name.length());
|
||||
if(err) {
|
||||
throw CryptoException(std::string("Error when setting subject key id ") + gnutls_strerror(err));
|
||||
}
|
||||
err = gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_LDAP_UID, 0, uid_str.data(), uid_str.length());
|
||||
if(err) {
|
||||
throw CryptoException(std::string("Error when setting dn by oid ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
setRandomSerial(cert);
|
||||
|
||||
unsigned key_usage = 0;
|
||||
if (is_ca) {
|
||||
gnutls_x509_crt_set_ca_status(cert, 1);
|
||||
err = gnutls_x509_crt_set_ca_status(cert, 1);
|
||||
if(err) {
|
||||
throw CryptoException(std::string("Error when setting ca status ") + gnutls_strerror(err));
|
||||
}
|
||||
key_usage |= GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN;
|
||||
} else {
|
||||
key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_DATA_ENCIPHERMENT;
|
||||
}
|
||||
gnutls_x509_crt_set_key_usage(cert, key_usage);
|
||||
err = gnutls_x509_crt_set_key_usage(cert, key_usage);
|
||||
if(err) {
|
||||
throw CryptoException(std::string("Error when setting ca status ") + gnutls_strerror(err));
|
||||
}
|
||||
|
||||
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, pk.getPreferredDigest(), 0)) {
|
||||
err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, pk.getPreferredDigest(), 0);
|
||||
if (err) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
ret.issuer = ca.second;
|
||||
} else {
|
||||
if (int err = gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0)) {
|
||||
err = gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0);
|
||||
if (err) {
|
||||
throw CryptoException(std::string("Error when signing certificate ") + gnutls_strerror(err));
|
||||
}
|
||||
}
|
||||
@@ -1414,7 +1501,22 @@ OcspResponse::getCertificateStatus() const
|
||||
{
|
||||
int ret;
|
||||
unsigned int status;
|
||||
// MSVC/vcpkg GnuTLS cast workaround
|
||||
#if _WIN32 && (GNUTLS_VERSION_NUMBER >= 0x030807)
|
||||
ret = gnutls_ocsp_resp_get_single(response,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
reinterpret_cast<gnutls_ocsp_cert_status_t*>(& status),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
#else
|
||||
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status, NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return (gnutls_ocsp_cert_status_t) status;
|
||||
@@ -1472,8 +1574,23 @@ OcspResponse::verifyDirect(const Certificate& crt, const Blob& nonce)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
|
||||
// Check certificate revocation status
|
||||
unsigned status_ocsp;
|
||||
unsigned int status_ocsp;
|
||||
// MSVC/vcpkg GnuTLS cast workaround
|
||||
#if _WIN32 && (GNUTLS_VERSION_NUMBER >= 0x030807)
|
||||
ret = gnutls_ocsp_resp_get_single(response,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
reinterpret_cast<gnutls_ocsp_cert_status_t*>(& status_ocsp),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
#else
|
||||
ret = gnutls_ocsp_resp_get_single(response, 0, NULL, NULL, NULL, NULL, &status_ocsp, NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
throw CryptoException(gnutls_strerror(ret));
|
||||
return (gnutls_ocsp_cert_status_t)status_ocsp;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+70
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -93,7 +93,7 @@ Dht::shutdown(ShutdownCallback cb, bool stop)
|
||||
r.second.done_cb(false, {});
|
||||
sr.second->callbacks.clear();
|
||||
for (const auto& a : sr.second->announce) {
|
||||
if (a.callback) a.callback(false, {});
|
||||
for (auto& cb : a.callbacks) cb(false, {});
|
||||
}
|
||||
sr.second->announce.clear();
|
||||
sr.second->listeners.clear();
|
||||
@@ -113,7 +113,7 @@ Dht::shutdown(ShutdownCallback cb, bool stop)
|
||||
auto str_donecb = [=](bool, const std::vector<Sp<Node>>&) {
|
||||
--*remaining;
|
||||
if (logger_)
|
||||
logger_->w("shuting down node: %u ops remaining", *remaining);
|
||||
logger_->w("Shutting down node: %u ops remaining", *remaining);
|
||||
if (!*remaining && cb) { cb(); }
|
||||
};
|
||||
|
||||
@@ -121,7 +121,7 @@ Dht::shutdown(ShutdownCallback cb, bool stop)
|
||||
*remaining += maintainStorage(str, true, str_donecb);
|
||||
|
||||
if (logger_)
|
||||
logger_->w("shuting down node: after storage, %u ops", *remaining);
|
||||
logger_->w("Shutting down node: after storage, %u ops", *remaining);
|
||||
|
||||
if (!*remaining) {
|
||||
if (cb) cb();
|
||||
@@ -147,7 +147,7 @@ Dht::sendCachedPing(Bucket& b)
|
||||
{
|
||||
if (b.cached)
|
||||
if (logger_)
|
||||
logger_->d(b.cached->id, "[node %s] sending ping to cached node", b.cached->toString().c_str());
|
||||
logger_->d(b.cached->id, "[node %s] Sending ping to cached node", b.cached->toString().c_str());
|
||||
b.sendCachedPing(network_engine);
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ Dht::expireSearches()
|
||||
auto b = sr.callbacks.empty() && sr.announce.empty() && sr.listeners.empty() && sr.step_time < t;
|
||||
if (b) {
|
||||
if (logger_)
|
||||
logger_->d(srp.first, "[search %s] removing search", srp.first.toString().c_str());
|
||||
logger_->d(srp.first, "[search %s] Removing search", srp.first.toString().c_str());
|
||||
sr.clear();
|
||||
return b;
|
||||
} else { return false; }
|
||||
@@ -360,7 +360,7 @@ void Dht::paginate(std::weak_ptr<Search> ws, Sp<Query> query, SearchNode* n) {
|
||||
auto query_for_vid = std::make_shared<Query>(Select {}, Where {}.id(vid));
|
||||
sn->pagination_queries[query].push_back(query_for_vid);
|
||||
if (logger_)
|
||||
logger_->d(id, sn->node->id, "[search %s] [node %s] sending %s",
|
||||
logger_->d(id, sn->node->id, "[search %s] [node %s] Sending %s",
|
||||
id.toString().c_str(), sn->node->toString().c_str(), query_for_vid->toString().c_str());
|
||||
sn->getStatus[query_for_vid] = network_engine.sendGetValues(status.node,
|
||||
id,
|
||||
@@ -371,8 +371,8 @@ void Dht::paginate(std::weak_ptr<Search> ws, Sp<Query> query, SearchNode* n) {
|
||||
);
|
||||
} catch (const std::out_of_range&) {
|
||||
if (logger_)
|
||||
logger_->e(id, sn->node->id, "[search %s] [node %s] received non-id field in response to "\
|
||||
"'SELECT id' request...",
|
||||
logger_->e(id, sn->node->id, "[search %s] [node %s] Received non-id field in response to "\
|
||||
"'SELECT id' request…",
|
||||
id.toString().c_str(), sn->node->toString().c_str());
|
||||
}
|
||||
}
|
||||
@@ -381,7 +381,7 @@ void Dht::paginate(std::weak_ptr<Search> ws, Sp<Query> query, SearchNode* n) {
|
||||
n->pagination_queries[query].push_back(select_q);
|
||||
|
||||
if (logger_)
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] sending %s",
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] Sending %s",
|
||||
sr->id.toString().c_str(), n->node->toString().c_str(), select_q->toString().c_str());
|
||||
n->getStatus[select_q] = network_engine.sendGetValues(n->node,
|
||||
sr->id,
|
||||
@@ -426,7 +426,7 @@ Dht::searchSendGetValues(Sp<Search> sr, SearchNode* pn, bool update)
|
||||
return nullptr;
|
||||
|
||||
/* if (logger_)
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] sending 'find_node'",
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] Sending 'find_node'",
|
||||
sr->id.toString().c_str(), n->node->toString().c_str());*/
|
||||
n->getStatus[query] = network_engine.sendFindNode(n->node,
|
||||
sr->id,
|
||||
@@ -439,9 +439,9 @@ Dht::searchSendGetValues(Sp<Search> sr, SearchNode* pn, bool update)
|
||||
continue;
|
||||
|
||||
if (query and not query->select.empty()) {
|
||||
/* The request contains a select. No need to paginate... */
|
||||
/* The request contains a select. No need to paginate… */
|
||||
/* if (logger_)
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] sending 'get'",
|
||||
logger_->d(sr->id, n->node->id, "[search %s] [node %s] Sending 'get'",
|
||||
sr->id.toString().c_str(), n->node->toString().c_str());*/
|
||||
n->getStatus[query] = network_engine.sendGetValues(n->node,
|
||||
sr->id,
|
||||
@@ -453,7 +453,7 @@ Dht::searchSendGetValues(Sp<Search> sr, SearchNode* pn, bool update)
|
||||
paginate(ws, query, n);
|
||||
}
|
||||
|
||||
/* We only try to send one request. return. */
|
||||
/* We only attempt to send one request. Return. */
|
||||
return n;
|
||||
|
||||
} while (++cb != sr->callbacks.end());
|
||||
@@ -519,7 +519,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
/* 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: %016" PRIx64 ")",
|
||||
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;
|
||||
acked = {
|
||||
@@ -528,7 +528,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
};
|
||||
} else if (hasValue and a.permanent) {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] sending 'refresh' (vid: %016" PRIx64 ")",
|
||||
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);
|
||||
acked = {
|
||||
network_engine.sendRefreshValue(sn->node, sr->id, a.value->id, sn->token, onDone,
|
||||
@@ -540,7 +540,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
](const net::Request& /*req*/, net::DhtProtocolException&& e){
|
||||
if (e.getCode() == net::DhtProtocolException::NOT_FOUND) {
|
||||
if (logger_)
|
||||
logger_->e(node->id, "[node %s] returned error 404: storage not found", node->toString().c_str());
|
||||
logger_->e(node->id, "[node %s] Returned error 404: storage not found", node->toString().c_str());
|
||||
if (auto sr = ws.lock()) {
|
||||
if (auto sn = sr->getNode(node)) {
|
||||
sn->acked[v->id] = {
|
||||
@@ -558,7 +558,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
};
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, sn->node->id, "[search %s] [node %s] already has value (vid: %016" PRIx64 "). 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;
|
||||
@@ -594,7 +594,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
sendQuery = true;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, n.node->id, "[search %s] [node %s] sending 'put' (vid: %016" PRIx64 ")",
|
||||
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),
|
||||
@@ -607,7 +607,7 @@ void Dht::searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel) {
|
||||
if (sendQuery) {
|
||||
n.probe_query = PROBE_QUERY;
|
||||
if (logger_)
|
||||
logger_->d(sr->id, n.node->id, "[search %s] [node %s] sending %s",
|
||||
logger_->d(sr->id, n.node->id, "[search %s] [node %s] Sending %s",
|
||||
sr->id.toString().c_str(), n.node->toString().c_str(), n.probe_query->toString().c_str());
|
||||
auto req = network_engine.sendGetValues(n.node,
|
||||
sr->id,
|
||||
@@ -634,7 +634,7 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
|
||||
if (n.getListenTime(r, listenExp) > scheduler.time())
|
||||
continue;
|
||||
// if (logger_)
|
||||
// logger_->d(sr->id, n.node->id, "[search %s] [node %s] sending 'listen'",
|
||||
// logger_->d(sr->id, n.node->id, "[search %s] [node %s] Sending 'listen'",
|
||||
// sr->id.toString().c_str(), n.node->toString().c_str());
|
||||
|
||||
if (r == n.listenStatus.end()) {
|
||||
@@ -706,7 +706,7 @@ Dht::searchStep(std::weak_ptr<Search> ws)
|
||||
auto syncLevel = preSynced ? level - MARGIN : 0;
|
||||
/*if (auto req_count = sr->currentlySolicitedNodeCount())
|
||||
if (logger_)
|
||||
logger_->d(sr->id, "[search %s IPv%c] step (%d requests)",
|
||||
logger_->d(sr->id, "[search %s IPv%c] Step (%d requests)",
|
||||
sr->id.toString().c_str(), sr->af == AF_INET ? '4' : '6', req_count);*/
|
||||
sr->step_time = now;
|
||||
|
||||
@@ -787,7 +787,7 @@ Dht::searchStep(std::weak_ptr<Search> ws)
|
||||
if (sr->getNumberOfConsecutiveBadNodes() >= std::min<size_t>(sr->nodes.size(), SEARCH_MAX_BAD_NODES))
|
||||
{
|
||||
if (logger_)
|
||||
logger_->w(sr->id, "[search %s IPv%c] expired", sr->id.toString().c_str(), sr->af == AF_INET ? '4' : '6');
|
||||
logger_->w(sr->id, "[search %s IPv%c] Expired", sr->id.toString().c_str(), sr->af == AF_INET ? '4' : '6');
|
||||
sr->expire();
|
||||
if (not public_stable)
|
||||
connectivityChanged(sr->af);
|
||||
@@ -804,7 +804,7 @@ unsigned Dht::refill(Dht::Search& sr) {
|
||||
|
||||
if (cached_nodes.empty()) {
|
||||
if (logger_)
|
||||
logger_->e(sr.id, "[search %s IPv%c] no nodes from cache while refilling search",
|
||||
logger_->e(sr.id, "[search %s IPv%c] No nodes from cache while refilling search",
|
||||
sr.id.toString().c_str(), (sr.af == AF_INET) ? '4' : '6');
|
||||
return 0;
|
||||
}
|
||||
@@ -816,7 +816,7 @@ unsigned Dht::refill(Dht::Search& sr) {
|
||||
++inserted;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->d(sr.id, "[search %s IPv%c] refilled search with %u nodes from node cache",
|
||||
logger_->d(sr.id, "[search %s IPv%c] Refilled search with %u nodes from node cache",
|
||||
sr.id.toString().c_str(), (sr.af == AF_INET) ? '4' : '6', inserted);
|
||||
return inserted;
|
||||
}
|
||||
@@ -828,7 +828,7 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback gcb, QueryCallback q
|
||||
{
|
||||
if (!isRunning(af)) {
|
||||
if (logger_)
|
||||
logger_->e(id, "[search %s IPv%c] unsupported protocol", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
logger_->e(id, "[search %s IPv%c] Unsupported protocol", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
if (dcb)
|
||||
dcb(false, {});
|
||||
return {};
|
||||
@@ -856,7 +856,7 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback gcb, QueryCallback q
|
||||
}
|
||||
if (not sr) {
|
||||
if (logger_)
|
||||
logger_->e(id, "[search %s IPv%c] maximum number of searches reached !", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
logger_->e(id, "[search %s IPv%c] Maximum number of searches reached!", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -870,7 +870,7 @@ Dht::search(const InfoHash& id, sa_family_t af, GetCallback gcb, QueryCallback q
|
||||
sr->nodes.reserve(SEARCH_NODES+1);
|
||||
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');
|
||||
logger_->w(id, "[search %s IPv%c] New search", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
|
||||
if (search_id == 0)
|
||||
search_id++;
|
||||
}
|
||||
@@ -904,16 +904,16 @@ Dht::listenTo(const InfoHash& id, sa_family_t af, ValueCallback cb, Value::Filte
|
||||
{
|
||||
if (!isRunning(af))
|
||||
return 0;
|
||||
// logger__ERR("[search %s IPv%c] search_time is now in %lfs", sr->id.toString().c_str(), (sr->af == AF_INET) ? '4' : '6', print_dt(tm-clock::now()));
|
||||
// logger__ERR("[search %s IPv%c] Search_time is now in %lfs", sr->id.toString().c_str(), (sr->af == AF_INET) ? '4' : '6', print_duration(tm-clock::now()));
|
||||
|
||||
//logger__WARN("listenTo %s", id.toString().c_str());
|
||||
auto& srs = searches(af);
|
||||
auto srp = srs.find(id);
|
||||
Sp<Search> sr = (srp == srs.end()) ? search(id, af) : srp->second;
|
||||
if (!sr)
|
||||
throw DhtException("Can't create search");
|
||||
throw DhtException("Unable to create search");
|
||||
if (logger_)
|
||||
logger_->w(id, "[search %s IPv%c] listen", id.to_c_str(), (af == AF_INET) ? '4' : '6');
|
||||
logger_->w(id, "[search %s IPv%c] Listen", id.to_c_str(), (af == AF_INET) ? '4' : '6');
|
||||
return sr->listen(cb, std::move(f), q, scheduler);
|
||||
}
|
||||
|
||||
@@ -1022,7 +1022,7 @@ Dht::put(const InfoHash& id, Sp<Value> val, DoneCallback callback, time_point cr
|
||||
storageStore(id, val, created, {}, permanent);
|
||||
|
||||
if (logger_)
|
||||
logger_->d(id, "put: adding %s -> %s", id.toString().c_str(), val->toString().c_str());
|
||||
logger_->d(id, "put: adding %s → %s", id.toString().c_str(), val->toString().c_str());
|
||||
|
||||
auto op = std::make_shared<OpStatus>();
|
||||
auto donecb = [callback](const std::vector<Sp<Node>>& nodes, OpStatus& op) {
|
||||
@@ -1265,7 +1265,7 @@ Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool ne
|
||||
vals.push_back(v);
|
||||
if (not vals.empty()) {
|
||||
if (logger_)
|
||||
logger_->d(id, "[store %s] sending update local listener with token %lu",
|
||||
logger_->d(id, "[store %s] Sending update local listener with token %lu",
|
||||
id.toString().c_str(),
|
||||
l.first);
|
||||
cbs.emplace_back(l.second.get_cb, std::move(vals));
|
||||
@@ -1286,7 +1286,7 @@ Dht::storageChanged(const InfoHash& id, Storage& st, const Sp<Value>& v, bool ne
|
||||
if (f and not f(*v))
|
||||
continue;
|
||||
if (logger_)
|
||||
logger_->w(id, node_listeners.first->id, "[store %s] [node %s] sending update",
|
||||
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 {};
|
||||
@@ -1392,7 +1392,7 @@ 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)",
|
||||
logger_->d(id, "[store %s] Discarded %ld values (%ld bytes)",
|
||||
id.toString().c_str(), values.size(), totalSize);
|
||||
|
||||
total_store_size -= totalSize;
|
||||
@@ -1410,7 +1410,7 @@ Dht::storageRemoved(const InfoHash& id, Storage& st, const std::vector<Sp<Value>
|
||||
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",
|
||||
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);
|
||||
@@ -1432,7 +1432,7 @@ Dht::expireStore()
|
||||
|
||||
if (i->second.empty() && i->second.listeners.empty() && i->second.local_listeners.empty()) {
|
||||
if (logger_)
|
||||
logger_->d(i->first, "[store %s] discarding empty storage", i->first.toString().c_str());
|
||||
logger_->d(i->first, "[store %s] Discarding empty storage", i->first.toString().c_str());
|
||||
i = store.erase(i);
|
||||
}
|
||||
else
|
||||
@@ -1812,6 +1812,7 @@ fromDhtConfig(const Config& config)
|
||||
netConf.max_peer_req_per_sec = config.max_peer_req_per_sec
|
||||
? config.max_peer_req_per_sec
|
||||
: netConf.max_req_per_sec/8;
|
||||
netConf.is_client = config.client_mode;
|
||||
return netConf;
|
||||
}
|
||||
|
||||
@@ -1899,7 +1900,7 @@ Dht::neighbourhoodMaintenance(RoutingTable& list)
|
||||
auto n = q->randomNode(rd);
|
||||
if (n) {
|
||||
if (logger_)
|
||||
logger_->d(id, n->id, "[node %s] sending [find %s] for neighborhood maintenance",
|
||||
logger_->d(id, n->id, "[node %s] Sending [find %s] for neighborhood maintenance",
|
||||
n->toString().c_str(), id.toString().c_str());
|
||||
/* Since our node-id is the same in both DHTs, it's probably
|
||||
profitable to query both families. */
|
||||
@@ -1953,14 +1954,14 @@ Dht::bucketMaintenance(RoutingTable& list)
|
||||
}
|
||||
|
||||
if (logger_)
|
||||
logger_->d(id, n->id, "[node %s] sending find %s for bucket maintenance", n->toString().c_str(), id.toString().c_str());
|
||||
logger_->d(id, n->id, "[node %s] Sending find %s for bucket maintenance", n->toString().c_str(), id.toString().c_str());
|
||||
//auto start = scheduler.time();
|
||||
network_engine.sendFindNode(n, id, want, nullptr, [this,n](const net::Request&, bool over) {
|
||||
if (over) {
|
||||
const auto& end = scheduler.time();
|
||||
// using namespace std::chrono;
|
||||
// if (logger_)
|
||||
// logger_->d(n->id, "[node %s] bucket maintenance op expired after %s", n->toString().c_str(), print_duration(end-start).c_str());
|
||||
// logger_->d(n->id, "[node %s] Bucket maintenance op expired after %s", n->toString().c_str(), print_duration(end-start).c_str());
|
||||
scheduler.edit(nextNodesConfirmation, end + Node::MAX_RESPONSE_TIME);
|
||||
}
|
||||
});
|
||||
@@ -1978,7 +1979,7 @@ Dht::dataPersistence(InfoHash id)
|
||||
auto str = store.find(id);
|
||||
if (str != store.end() and now > str->second.maintenance_time) {
|
||||
if (logger_)
|
||||
logger_->d(id, "[storage %s] maintenance (%u values, %u bytes)",
|
||||
logger_->d(id, "[storage %s] Maintenance (%u values, %u bytes)",
|
||||
id.toString().c_str(), str->second.valueCount(), str->second.totalSize());
|
||||
maintainStorage(*str);
|
||||
str->second.maintenance_time = now + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME;
|
||||
@@ -2032,7 +2033,7 @@ Dht::periodic(const uint8_t *buf, size_t buflen, SockAddr from, const time_point
|
||||
network_engine.processMessage(buf, buflen, std::move(from));
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->w("Can't process message: %s", e.what());
|
||||
logger_->w("Unable to process message: %s", e.what());
|
||||
}
|
||||
}
|
||||
return scheduler.run();
|
||||
@@ -2086,7 +2087,7 @@ Dht::bootstrap()
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->e(myid, "Can't resolve %s:%s: %s", boootstrap.first.c_str(), boootstrap.second.c_str(), e.what());
|
||||
logger_->e(myid, "Unable to resolve %s:%s: %s", boootstrap.first.c_str(), boootstrap.second.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
scheduler.cancel(bootstrapJob);
|
||||
@@ -2117,12 +2118,12 @@ Dht::confirmNodes()
|
||||
|
||||
if (dht4.searches.empty() and dht4.status == NodeStatus::Connected) {
|
||||
if (logger_)
|
||||
logger_->d(myid, "[confirm nodes] initial IPv4 'get' for my id (%s)", myid.toString().c_str());
|
||||
logger_->d(myid, "[confirm nodes] Initial IPv4 'get' for my id (%s)", myid.toString().c_str());
|
||||
search(myid, AF_INET);
|
||||
}
|
||||
if (dht6.searches.empty() and dht6.status == NodeStatus::Connected) {
|
||||
if (logger_)
|
||||
logger_->d(myid, "[confirm nodes] initial IPv6 'get' for my id (%s)", myid.toString().c_str());
|
||||
logger_->d(myid, "[confirm nodes] Initial IPv6 'get' for my id (%s)", myid.toString().c_str());
|
||||
search(myid, AF_INET6);
|
||||
}
|
||||
|
||||
@@ -2280,7 +2281,7 @@ Dht::onError(Sp<net::Request> req, net::DhtProtocolException e) {
|
||||
const auto& node = req->node;
|
||||
if (e.getCode() == net::DhtProtocolException::UNAUTHORIZED) {
|
||||
if (logger_)
|
||||
logger_->e(node->id, "[node %s] token flush", node->toString().c_str());
|
||||
logger_->e(node->id, "[node %s] Token flush", node->toString().c_str());
|
||||
node->authError();
|
||||
for (auto& srp : searches(node->getFamily())) {
|
||||
auto& sr = srp.second;
|
||||
@@ -2295,7 +2296,7 @@ Dht::onError(Sp<net::Request> req, net::DhtProtocolException e) {
|
||||
}
|
||||
} else if (e.getCode() == net::DhtProtocolException::NOT_FOUND) {
|
||||
if (logger_)
|
||||
logger_->e(node->id, "[node %s] returned error 404: storage not found", node->toString().c_str());
|
||||
logger_->e(node->id, "[node %s] Returned error 404: storage not found", node->toString().c_str());
|
||||
node->cancelRequest(req);
|
||||
}
|
||||
}
|
||||
@@ -2346,7 +2347,7 @@ Dht::onGetValues(Sp<Node> node, const InfoHash& hash, want_t, const Query& query
|
||||
if (st != store.end() && not st->second.empty()) {
|
||||
answer.values = st->second.get(query.where.getFilter());
|
||||
if (logger_)
|
||||
logger_->d(hash, "[node %s] sending %u values", node->toString().c_str(), answer.values.size());
|
||||
logger_->d(hash, "[node %s] Sending %u values", node->toString().c_str(), answer.values.size());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
@@ -2358,18 +2359,18 @@ void Dht::onGetValuesDone(const Sp<Node>& node,
|
||||
{
|
||||
if (not sr) {
|
||||
if (logger_)
|
||||
logger_->w("[search unknown] got reply to 'get'. Ignoring.");
|
||||
logger_->w("[search unknown] Got reply to 'get'. Ignoring.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* if (logger_)
|
||||
logger_->d(sr->id, "[search %s] [node %s] got reply to 'get' with %u nodes",
|
||||
logger_->d(sr->id, "[search %s] [node %s] Got reply to 'get' with %u nodes",
|
||||
sr->id.toString().c_str(), node->toString().c_str(), a.nodes4.size()+a.nodes6.size());*/
|
||||
|
||||
if (not a.ntoken.empty()) {
|
||||
if (not a.values.empty() or not a.fields.empty()) {
|
||||
if (logger_)
|
||||
logger_->d(sr->id, node->id, "[search %s] [node %s] found %u values",
|
||||
logger_->d(sr->id, node->id, "[search %s] [node %s] Found %u values",
|
||||
sr->id.toString().c_str(), node->toString().c_str(), a.values.size());
|
||||
for (auto& getp : sr->callbacks) { /* call all callbacks for this search */
|
||||
auto& get = getp.second;
|
||||
@@ -2418,7 +2419,7 @@ void Dht::onGetValuesDone(const Sp<Node>& node,
|
||||
}
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w(sr->id, "[node %s] no token provided. Ignoring response content.", node->toString().c_str());
|
||||
logger_->w(sr->id, "[node %s] No token provided. Ignoring response content.", node->toString().c_str());
|
||||
network_engine.blacklistNode(node);
|
||||
}
|
||||
|
||||
@@ -2435,7 +2436,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
|
||||
{
|
||||
if (not hash) {
|
||||
if (logger_)
|
||||
logger_->w(node->id, "[node %s] listen with no info_hash", node->toString().c_str());
|
||||
logger_->w(node->id, "[node %s] Listen with no info_hash", node->toString().c_str());
|
||||
throw net::DhtProtocolException {
|
||||
net::DhtProtocolException::NON_AUTHORITATIVE_INFORMATION,
|
||||
net::DhtProtocolException::LISTEN_NO_INFOHASH
|
||||
@@ -2443,7 +2444,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
|
||||
}
|
||||
if (not tokenMatch(token, node->getAddr())) {
|
||||
if (logger_)
|
||||
logger_->w(hash, node->id, "[node %s] incorrect token %s for 'listen'", node->toString().c_str(), hash.toString().c_str());
|
||||
logger_->w(hash, node->id, "[node %s] Incorrect token %s for 'listen'", node->toString().c_str(), hash.toString().c_str());
|
||||
throw net::DhtProtocolException {net::DhtProtocolException::UNAUTHORIZED, net::DhtProtocolException::LISTEN_WRONG_TOKEN};
|
||||
}
|
||||
Query q = query;
|
||||
@@ -2455,7 +2456,7 @@ void
|
||||
Dht::onListenDone(const Sp<Node>& /* node */, net::RequestAnswer& /* answer */, Sp<Search>& sr)
|
||||
{
|
||||
// if (logger_)
|
||||
// logger_->d(sr->id, node->id, "[search %s] [node %s] got listen confirmation",
|
||||
// logger_->d(sr->id, node->id, "[search %s] [node %s] Got listen confirmation",
|
||||
// sr->id.toString().c_str(), node->toString().c_str(), answer.values.size());
|
||||
|
||||
if (not sr->done) {
|
||||
@@ -2475,7 +2476,7 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
auto& node = *n;
|
||||
if (not hash) {
|
||||
if (logger_)
|
||||
logger_->w(node.id, "put with no info_hash");
|
||||
logger_->w(node.id, "Put with no info_hash");
|
||||
throw net::DhtProtocolException {
|
||||
net::DhtProtocolException::NON_AUTHORITATIVE_INFORMATION,
|
||||
net::DhtProtocolException::PUT_NO_INFOHASH
|
||||
@@ -2483,7 +2484,7 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
}
|
||||
if (!tokenMatch(token, node.getAddr())) {
|
||||
if (logger_)
|
||||
logger_->w(hash, node.id, "[node %s] incorrect token %s for 'put'", node.toString().c_str(), hash.toString().c_str());
|
||||
logger_->w(hash, node.id, "[node %s] Incorrect token %s for 'put'", node.toString().c_str(), hash.toString().c_str());
|
||||
throw net::DhtProtocolException {net::DhtProtocolException::UNAUTHORIZED, net::DhtProtocolException::PUT_WRONG_TOKEN};
|
||||
}
|
||||
{
|
||||
@@ -2492,7 +2493,7 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
auto closest_nodes = buckets(node.getFamily()).findClosestNodes(hash, scheduler.time(), SEARCH_NODES);
|
||||
if (closest_nodes.size() >= TARGET_NODES and hash.xorCmp(closest_nodes.back()->id, myid) < 0) {
|
||||
if (logger_)
|
||||
logger_->w(hash, node.id, "[node %s] announce too far from the target. Dropping value.", node.toString().c_str());
|
||||
logger_->w(hash, node.id, "[node %s] Announce too far from the target. Dropping value.", node.toString().c_str());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@@ -2501,7 +2502,7 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
for (const auto& v : values) {
|
||||
if (v->id == Value::INVALID_ID) {
|
||||
if (logger_)
|
||||
logger_->w(hash, node.id, "[value %s] incorrect value id", hash.toString().c_str());
|
||||
logger_->w(hash, node.id, "[value %s] Incorrect value id", hash.toString().c_str());
|
||||
throw net::DhtProtocolException {
|
||||
net::DhtProtocolException::NON_AUTHORITATIVE_INFORMATION,
|
||||
net::DhtProtocolException::PUT_INVALID_ID
|
||||
@@ -2513,17 +2514,17 @@ 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 %016" PRIx64, hash.toString().c_str(), node.toString().c_str(), v->id);
|
||||
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())) {
|
||||
if (logger_)
|
||||
logger_->d(hash, node.id, "[store %s] editing %s",
|
||||
logger_->d(hash, node.id, "[store %s] Editing %s",
|
||||
hash.toString().c_str(), vc->toString().c_str());
|
||||
storageStore(hash, vc, created, node.getAddr());
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->d(hash, node.id, "[store %s] rejecting edition of %s because of storage policy",
|
||||
logger_->d(hash, node.id, "[store %s] Rejecting edition of %s because of storage policy",
|
||||
hash.toString().c_str(), vc->toString().c_str());
|
||||
}
|
||||
}
|
||||
@@ -2532,11 +2533,11 @@ Dht::onAnnounce(Sp<Node> n,
|
||||
const auto& type = getType(vc->type);
|
||||
if (type.storePolicy(hash, vc, node.id, node.getAddr())) {
|
||||
// if (logger_)
|
||||
// logger_->d(hash, node.id, "[store %s] storing %s", hash.toString().c_str(), std::to_string(vc->id).c_str());
|
||||
// logger_->d(hash, node.id, "[store %s] Storing %s", hash.toString().c_str(), std::to_string(vc->id).c_str());
|
||||
storageStore(hash, vc, created, node.getAddr());
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->d(hash, node.id, "[store %s] rejecting storage of %s",
|
||||
logger_->d(hash, node.id, "[store %s] Rejecting storage of %s",
|
||||
hash.toString().c_str(), vc->toString().c_str());
|
||||
}
|
||||
}
|
||||
@@ -2551,15 +2552,15 @@ Dht::onRefresh(Sp<Node> node, const InfoHash& hash, const Blob& token, const Val
|
||||
|
||||
if (not tokenMatch(token, node->getAddr())) {
|
||||
if (logger_)
|
||||
logger_->w(hash, node->id, "[node %s] incorrect token %s for 'put'", node->toString().c_str(), hash.toString().c_str());
|
||||
logger_->w(hash, node->id, "[node %s] Incorrect token %s for 'put'", node->toString().c_str(), hash.toString().c_str());
|
||||
throw DhtProtocolException {DhtProtocolException::UNAUTHORIZED, DhtProtocolException::PUT_WRONG_TOKEN};
|
||||
}
|
||||
if (storageRefresh(hash, vid)) {
|
||||
if (logger_)
|
||||
logger_->d(hash, node->id, "[store %s] [node %s] refreshed value %016" PRIx64, hash.toString().c_str(), node->toString().c_str(), vid);
|
||||
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",
|
||||
logger_->d(hash, node->id, "[store %s] [node %s] Got refresh for unknown value",
|
||||
hash.toString().c_str(), node->toString().c_str());
|
||||
throw DhtProtocolException {DhtProtocolException::NOT_FOUND, DhtProtocolException::STORAGE_NOT_FOUND};
|
||||
}
|
||||
@@ -2582,7 +2583,7 @@ Dht::storageRefresh(const InfoHash& id, Value::Id vid)
|
||||
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 refresh",
|
||||
logger_->w(id, node_listeners.first->id, "[store %s] [node %s] Sending refresh",
|
||||
id.toString().c_str(),
|
||||
node_listeners.first->toString().c_str());
|
||||
Blob ntoken = makeToken(node_listeners.first->getAddr(), false);
|
||||
@@ -2607,7 +2608,7 @@ void
|
||||
Dht::onAnnounceDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>& sr)
|
||||
{
|
||||
if (logger_)
|
||||
logger_->d(sr->id, node->id, "[search %s] [node %s] got reply to put!",
|
||||
logger_->d(sr->id, node->id, "[search %s] [node %s] Got reply to put!",
|
||||
sr->id.toString().c_str(), node->toString().c_str());
|
||||
searchSendGetValues(sr);
|
||||
sr->checkAnnounced(answer.vid);
|
||||
|
||||
+54
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "op_cache.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <http_parser.h>
|
||||
#include <llhttp.h>
|
||||
#include <deque>
|
||||
|
||||
namespace dht {
|
||||
@@ -106,13 +106,26 @@ getRandomSessionId(size_t length = 8) {
|
||||
DhtProxyClient::DhtProxyClient() {}
|
||||
|
||||
DhtProxyClient::DhtProxyClient(
|
||||
std::shared_ptr<dht::crypto::Certificate> serverCA, dht::crypto::Identity clientIdentity,
|
||||
std::function<void()> signal, const std::string& serverHost,
|
||||
const std::string& pushClientId, std::shared_ptr<dht::Logger> logger)
|
||||
std::shared_ptr<dht::crypto::Certificate> serverCA,
|
||||
dht::crypto::Identity clientIdentity,
|
||||
std::function<void()> signal,
|
||||
const std::string& serverHost,
|
||||
const std::string& userAgent,
|
||||
const std::string& pushClientId,
|
||||
const std::string& pushToken,
|
||||
const std::string& pushTopic,
|
||||
const std::string& pushPlatform,
|
||||
std::shared_ptr<dht::Logger> logger
|
||||
)
|
||||
: DhtInterface(logger)
|
||||
, proxyUrl_(serverHost)
|
||||
, clientIdentity_(clientIdentity), serverCertificate_(serverCA)
|
||||
, pushClientId_(pushClientId), pushSessionId_(getRandomSessionId())
|
||||
, userAgent_(userAgent)
|
||||
, pushClientId_(pushClientId)
|
||||
, pushSessionId_(getRandomSessionId())
|
||||
, deviceKey_(pushToken)
|
||||
, notificationTopic_(pushTopic)
|
||||
, platform_(pushPlatform)
|
||||
, loopSignal_(signal)
|
||||
, jsonReader_(Json::CharReaderBuilder{}.newCharReader())
|
||||
{
|
||||
@@ -484,7 +497,7 @@ DhtProxyClient::buildRequest(const std::string& target)
|
||||
request->set_certificate_authority(serverCertificate_);
|
||||
if (clientIdentity_.first and clientIdentity_.second)
|
||||
request->set_identity(clientIdentity_);
|
||||
request->set_header_field(restinio::http_field_t::user_agent, "RESTinio client");
|
||||
request->set_header_field(restinio::http_field_t::user_agent, userAgent_);
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -800,8 +813,8 @@ SockAddr
|
||||
DhtProxyClient::parsePublicAddress(const Json::Value& val)
|
||||
{
|
||||
auto public_ip = val.asString();
|
||||
auto hostAndService = splitPort(public_ip);
|
||||
auto sa = SockAddr::resolve(hostAndService.first);
|
||||
auto [host, service] = splitPort(public_ip);
|
||||
auto sa = SockAddr::resolve(host);
|
||||
if (sa.empty()) return {};
|
||||
return sa.front().getMappedIPv4();
|
||||
}
|
||||
@@ -1220,9 +1233,10 @@ DhtProxyClient::restartListeners(const asio::error_code &ec)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PushNotificationResult
|
||||
DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::string, std::string>& notification)
|
||||
{
|
||||
auto ret = PushNotificationResult::IgnoredNoOp;
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
{
|
||||
// If a push notification is received, the proxy is up and running
|
||||
@@ -1239,7 +1253,7 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
if (sessionId != notification.end() and sessionId->second != pushSessionId_) {
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [push] ignoring push for other session");
|
||||
return;
|
||||
return PushNotificationResult::IgnoredWrongSession;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
auto timeout = notification.find("timeout");
|
||||
@@ -1256,10 +1270,12 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
else
|
||||
put.refreshPutTimer->expires_at(std::chrono::steady_clock::now());
|
||||
put.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, vid));
|
||||
ret = PushNotificationResult::PutRefresh;
|
||||
} else {
|
||||
// Refresh listen
|
||||
for (auto& list : search.listeners)
|
||||
resubscribe(key, list.first, list.second);
|
||||
ret = search.listeners.empty() ? PushNotificationResult::IgnoredNoOp : PushNotificationResult::ListenRefresh;
|
||||
}
|
||||
} else {
|
||||
auto key = InfoHash(notification.at("key"));
|
||||
@@ -1268,12 +1284,12 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
sendTime = system_clock::time_point(std::chrono::milliseconds(std::stoull(notification.at("t"))));
|
||||
} catch (...) {}
|
||||
auto& search = searches_.at(key);
|
||||
auto expired = notification.find("exp");
|
||||
for (auto& list : search.listeners) {
|
||||
if (list.second.opstate->stop)
|
||||
continue;
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [push] [search %s] received", key.to_c_str());
|
||||
auto expired = notification.find("exp");
|
||||
auto token = list.first;
|
||||
auto opstate = list.second.opstate;
|
||||
if (expired == notification.end()) {
|
||||
@@ -1286,6 +1302,7 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
// present in the new list
|
||||
cb(oldValues, true, sendTime);
|
||||
});
|
||||
ret = PushNotificationResult::Values;
|
||||
} else {
|
||||
std::stringstream ss(expired->second);
|
||||
std::vector<Value::Id> ids;
|
||||
@@ -1311,16 +1328,21 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
});
|
||||
}
|
||||
launchLoop = true;
|
||||
ret = PushNotificationResult::ValuesExpired;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::out_of_range& e) {
|
||||
ret = PushNotificationResult::IgnoredNoOp;
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->e("[proxy:client] [push] receive error: %s", e.what());
|
||||
ret = PushNotificationResult::Error;
|
||||
}
|
||||
if (launchLoop)
|
||||
loopSignal_();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1381,4 +1403,24 @@ DhtProxyClient::fillBody(bool resubscribe)
|
||||
}
|
||||
#endif // OPENDHT_PUSH_NOTIFICATIONS
|
||||
|
||||
void
|
||||
DhtProxyClient::setPushNotificationToken([[maybe_unused]] const std::string& token) {
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
|
||||
if (deviceKey_ != token) {
|
||||
deviceKey_ = token;
|
||||
if (statusIpv4_ == NodeStatus::Connected || statusIpv6_ == NodeStatus::Connected) {
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [push] token changed, resubscribing");
|
||||
for (auto& search : searches_) {
|
||||
for (auto& listener : search.second.listeners) {
|
||||
resubscribe(search.first, listener.first, listener.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace dht
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -58,6 +58,19 @@ constexpr const std::chrono::minutes PRINT_STATS_PERIOD {2};
|
||||
using ResponseByParts = restinio::chunked_output_t;
|
||||
using ResponseByPartsBuilder = restinio::response_builder_t<ResponseByParts>;
|
||||
|
||||
namespace http {
|
||||
/**
|
||||
* Session value associated with a connection_id_t key.
|
||||
*/
|
||||
struct ListenerSession
|
||||
{
|
||||
ListenerSession() = default;
|
||||
dht::InfoHash hash;
|
||||
std::future<size_t> token;
|
||||
std::shared_ptr<restinio::response_builder_t<restinio::chunked_output_t>> response;
|
||||
};
|
||||
}
|
||||
|
||||
class opendht_logger_t
|
||||
{
|
||||
public:
|
||||
@@ -116,7 +129,7 @@ private:
|
||||
void
|
||||
DhtProxyServer::ConnectionListener::state_changed(const restinio::connection_state::notice_t& notice) noexcept
|
||||
{
|
||||
if (restinio::holds_alternative<restinio::connection_state::closed_t>(notice.cause())) {
|
||||
if (std::holds_alternative<restinio::connection_state::closed_t>(notice.cause())) {
|
||||
onClosed_(notice.connection_id());
|
||||
}
|
||||
}
|
||||
@@ -210,6 +223,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
|
||||
: ioContext_(std::make_shared<asio::io_context>()),
|
||||
dht_(dht), persistPath_(config.persistStatePath), logger_(logger),
|
||||
printStatsTimer_(std::make_unique<asio::steady_timer>(*ioContext_, 3s)),
|
||||
serverStartTime_(clock::now()),
|
||||
connListener_(std::make_shared<ConnectionListener>(std::bind(&DhtProxyServer::onConnectionClosed, this, std::placeholders::_1))),
|
||||
pushServer_(config.pushServer),
|
||||
bundleId_(config.bundleId)
|
||||
@@ -529,7 +543,15 @@ DhtProxyServer::updateStats(std::shared_ptr<NodeInfo> info) const
|
||||
stats.requestRate = count / dt.count();
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
stats.pushListenersCount = pushListeners_.size();
|
||||
{
|
||||
std::lock_guard lk(pushStatsMutex_);
|
||||
stats.androidPush = androidPush_;
|
||||
stats.iosPush = iosPush_;
|
||||
stats.unifiedPush = unifiedPush_;
|
||||
}
|
||||
#endif
|
||||
stats.serverStartTime = serverStartTime_;
|
||||
stats.lastUpdated = now;
|
||||
stats.totalPermanentPuts = 0;
|
||||
std::for_each(puts_.begin(), puts_.end(), [&stats](const auto& put) {
|
||||
stats.totalPermanentPuts += put.second.puts.size();
|
||||
@@ -609,6 +631,8 @@ DhtProxyServer::createRestRouter()
|
||||
router->http_get("/key/:hash", std::bind(&DhtProxyServer::get, this, _1, _2));
|
||||
// key.post
|
||||
router->http_post("/key/:hash", std::bind(&DhtProxyServer::put, this, _1, _2));
|
||||
router->add_handler(restinio::http_method_options(),
|
||||
"/key/:hash/listen", std::bind(&DhtProxyServer::options, this, _1, _2));
|
||||
// key.listen
|
||||
router->http_get("/key/:hash/listen", std::bind(&DhtProxyServer::listen, this, _1, _2));
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
@@ -1094,10 +1118,14 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
|
||||
notification["tokens"] = std::move(tokens);
|
||||
notification["platform"] = type == PushType::Android ? 2 : 1;
|
||||
notification["data"] = std::move(json);
|
||||
notification["priority"] = highPriority ? "high" : "normal";
|
||||
if (type == PushType::Android)
|
||||
notification["time_to_live"] = 3600 * 24; // 24 hours
|
||||
else {
|
||||
auto priority = highPriority ? "high" : "normal";
|
||||
if (type == PushType::Android) {
|
||||
Json::Value androidConfig(Json::objectValue);
|
||||
androidConfig["priority"] = priority;
|
||||
androidConfig["ttl"] = "86400s"; // time to live = 24 hours
|
||||
notification["android"] = std::move(androidConfig);
|
||||
} else {
|
||||
notification["priority"] = priority;
|
||||
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;
|
||||
@@ -1138,6 +1166,21 @@ DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& jso
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
// For monitoring purposes
|
||||
std::lock_guard lk(pushStatsMutex_);
|
||||
switch (type) {
|
||||
case PushType::Android:
|
||||
androidPush_.increment(highPriority);
|
||||
break;
|
||||
case PushType::iOS:
|
||||
iosPush_.increment(highPriority);
|
||||
break;
|
||||
case PushType::UnifiedPush:
|
||||
unifiedPush_.increment(highPriority);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e){
|
||||
if (logger_)
|
||||
|
||||
+77
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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,7 +36,9 @@
|
||||
|
||||
namespace dht {
|
||||
|
||||
static const std::string PEER_DISCOVERY_DHT_SERVICE = "dht";
|
||||
using namespace std::literals;
|
||||
|
||||
constexpr auto PEER_DISCOVERY_DHT_SERVICE = "dht"sv;
|
||||
|
||||
struct NodeInsertionPack {
|
||||
dht::InfoHash nodeId;
|
||||
@@ -180,9 +182,9 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (context.statusChangedCallback) {
|
||||
statusCb = std::move(context.statusChangedCallback);
|
||||
}
|
||||
statusCbs.clear();
|
||||
if (context.statusChangedCallback)
|
||||
statusCbs.emplace_back(std::move(context.statusChangedCallback));
|
||||
if (context.certificateStore) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
}
|
||||
@@ -264,6 +266,17 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peerDiscovery_) {
|
||||
statusCbs.emplace_back([this](NodeStatus status4, NodeStatus status6) {
|
||||
if (status4 == NodeStatus::Disconnected && status6 == NodeStatus::Disconnected) {
|
||||
peerDiscovery_->connectivityChanged();
|
||||
}
|
||||
else if (status4 != NodeStatus::Connected || status6 != NodeStatus::Connected) {
|
||||
peerDiscovery_->stopConnectivityChanged();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -608,7 +621,7 @@ DhtRunner::getPublicAddress(std::function<void(std::vector<SockAddr>&&)> cb, sa_
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::registerCertificate(std::shared_ptr<crypto::Certificate> cert) {
|
||||
DhtRunner::registerCertificate(const std::shared_ptr<crypto::Certificate>& cert) {
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
dht_->registerCertificate(cert);
|
||||
}
|
||||
@@ -690,8 +703,9 @@ DhtRunner::loop_()
|
||||
if (nstatus4 != status4 || nstatus6 != status6) {
|
||||
status4 = nstatus4;
|
||||
status6 = nstatus6;
|
||||
if (statusCb)
|
||||
statusCb(status4, status6);
|
||||
for (auto& cb : statusCbs){
|
||||
cb(status4, status6);
|
||||
}
|
||||
}
|
||||
|
||||
return wakeup;
|
||||
@@ -876,6 +890,25 @@ DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple c
|
||||
putSigned(InfoHash::get(key), std::forward<Value>(value), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, const PkId& 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, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
@@ -1065,6 +1098,23 @@ DhtRunner::findCertificate(InfoHash hash, std::function<void(const Sp<crypto::Ce
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void DhtRunner::findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)> cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
return;
|
||||
}
|
||||
ongoing_ops++;
|
||||
pending_ops.emplace([this, hash, cb = std::move(cb)] (SecureDht& dht) {
|
||||
dht.findCertificate(hash, [this, cb = std::move(cb)](const Sp<crypto::Certificate>& crt){
|
||||
cb(crt);
|
||||
opEnded();
|
||||
});
|
||||
});
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::resetDht()
|
||||
{
|
||||
@@ -1108,13 +1158,13 @@ DhtRunner::enableProxy(bool proxify)
|
||||
cv.notify_all();
|
||||
}
|
||||
},
|
||||
config_.proxy_server, config_.push_node_id, logger_);
|
||||
if (not config_.push_token.empty())
|
||||
dht_via_proxy->setPushNotificationToken(config_.push_token);
|
||||
if (not config_.push_topic.empty())
|
||||
dht_via_proxy->setPushNotificationTopic(config_.push_topic);
|
||||
if (not config_.push_platform.empty())
|
||||
dht_via_proxy->setPushNotificationPlatform(config_.push_platform);
|
||||
config_.proxy_server,
|
||||
config_.proxy_user_agent,
|
||||
config_.push_node_id,
|
||||
config_.push_token,
|
||||
config_.push_topic,
|
||||
config_.push_platform,
|
||||
logger_);
|
||||
dht_ = std::make_unique<SecureDht>(std::move(dht_via_proxy), config_.dht_config, identityAnnouncedCb_, logger_);
|
||||
// and use it
|
||||
use_proxy = proxify;
|
||||
@@ -1174,18 +1224,25 @@ DhtRunner::setPushNotificationPlatform(const std::string& platform) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::pushNotificationReceived(const std::map<std::string, std::string>& data)
|
||||
std::future<PushNotificationResult>
|
||||
DhtRunner::pushNotificationReceived([[maybe_unused]] const std::map<std::string, std::string>& data)
|
||||
{
|
||||
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
|
||||
auto ret_token = std::make_shared<std::promise<PushNotificationResult>>();
|
||||
auto future = ret_token->get_future();
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht&) {
|
||||
pending_ops_prio.emplace([ret_token, this, data](SecureDht&) {
|
||||
if (dht_)
|
||||
dht_->pushNotificationReceived(data);
|
||||
ret_token->set_value(dht_->pushNotificationReceived(data));
|
||||
else
|
||||
ret_token->set_value(PushNotificationResult::IgnoredStopped);
|
||||
});
|
||||
cv.notify_all();
|
||||
return future;
|
||||
#else
|
||||
(void) data;
|
||||
std::promise<PushNotificationResult> p {};
|
||||
p.set_value(PushNotificationResult::IgnoredDisabled);
|
||||
return p.get_future();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+48
-40
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author: Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <restinio/impl/tls_socket.hpp>
|
||||
#include <http_parser.h>
|
||||
#include <llhttp.h>
|
||||
#include <json/json.h>
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
@@ -54,7 +54,7 @@ constexpr const char HTTPS_PROTOCOL[] = "https://";
|
||||
constexpr const char ORIGIN_PROTOCOL[] = "//";
|
||||
constexpr unsigned MAX_REDIRECTS {5};
|
||||
|
||||
Url::Url(const std::string& url): url(url)
|
||||
Url::Url(std::string_view url): url(url)
|
||||
{
|
||||
size_t addr_begin = 0;
|
||||
// protocol
|
||||
@@ -69,10 +69,9 @@ Url::Url(const std::string& url): url(url)
|
||||
size_t addr_size = url.substr(addr_begin).find("/");
|
||||
if (addr_size == std::string::npos)
|
||||
addr_size = url.size() - addr_begin;
|
||||
auto host_service = splitPort(url.substr(addr_begin, addr_size));
|
||||
host = host_service.first;
|
||||
if (!host_service.second.empty())
|
||||
service = host_service.second;
|
||||
auto [h, s] = splitPort(url.substr(addr_begin, addr_size));
|
||||
host = std::move(h);
|
||||
service = std::move(s);
|
||||
// target, query and fragment
|
||||
size_t query_begin = url.find("?");
|
||||
auto addr_end = addr_begin + addr_size;
|
||||
@@ -457,11 +456,11 @@ Connection::set_ssl_verification(const std::string& hostname, const asio::ssl::v
|
||||
}
|
||||
|
||||
// starts from CA and goes down the presented chain
|
||||
auto verifier = asio::ssl::rfc2818_verification(hostname);
|
||||
auto verifier = asio::ssl::host_name_verification(hostname);
|
||||
bool verified = verifier(preverified, ctx);
|
||||
auto verify_ec = X509_STORE_CTX_get_error(ctx.native_handle());
|
||||
if (verify_ec != 0 /*X509_V_OK*/ and logger)
|
||||
logger->error("[http::connection:{:d}] ssl verification error={:d} %d", id, verify_ec, verified);
|
||||
logger->error("[http::connection:{:d}] ssl verification error={:d} {}", id, verify_ec, verified);
|
||||
if (verified and checkOcsp) {
|
||||
std::unique_ptr<stack_st_X509, void(*)(stack_st_X509*)> chain(
|
||||
X509_STORE_CTX_get1_chain(ctx.native_handle()),
|
||||
@@ -592,12 +591,12 @@ Connection::async_write(BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
if (cb) asio::post(ctx_, [cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_write(*ssl_socket_, write_buf_, wrapCallback(std::move(cb)));
|
||||
else if (socket_) asio::async_write(*socket_, write_buf_, wrapCallback(std::move(cb)));
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
else if (cb) asio::post(ctx_, [cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -605,12 +604,12 @@ Connection::async_read_until(const char* delim, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
if (cb) asio::post(ctx_, [cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallback(std::move(cb)));
|
||||
else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallback(std::move(cb)));
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
else if (cb) asio::post(ctx_, [cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -618,12 +617,12 @@ Connection::async_read_until(char delim, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
if (cb) asio::post(ctx_, [cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read_until(*ssl_socket_, read_buf_, delim, wrapCallback(std::move(cb)));
|
||||
else if (socket_) asio::async_read_until(*socket_, read_buf_, delim, wrapCallback(std::move(cb)));
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
else if (cb) asio::post(ctx_, [cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -631,12 +630,12 @@ Connection::async_read(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
if (cb) asio::post(ctx_, [cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
if (ssl_socket_) asio::async_read(*ssl_socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallback(std::move(cb)));
|
||||
else if (socket_) asio::async_read(*socket_, read_buf_, asio::transfer_exactly(bytes), wrapCallback(std::move(cb)));
|
||||
else if (cb) ctx_.post([cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
else if (cb) asio::post(ctx_, [cb](){ cb(asio::error::operation_aborted, 0); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -644,7 +643,7 @@ Connection::async_read_some(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb) ctx_.post([cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
if (cb) asio::post(ctx_, [cb](){ cb(asio::error::broken_pipe, 0); });
|
||||
return;
|
||||
}
|
||||
auto buf = read_buf_.prepare(bytes);
|
||||
@@ -819,10 +818,21 @@ Resolver::add_callback(ResolverCb cb, sa_family_t family)
|
||||
}
|
||||
|
||||
void
|
||||
Resolver::resolve(const std::string& host, const std::string& service)
|
||||
Resolver::resolve(const std::string& host, const std::string& serviceName)
|
||||
{
|
||||
asio::ip::tcp::resolver::query query_(host, service);
|
||||
resolver_.async_resolve(query_, [this, host, service, destroyed = destroyed_]
|
||||
auto service = serviceName;
|
||||
// The async_resolve function used below typically relies on the contents of the
|
||||
// /etc/services (Linux/POSIX) or c:\windows\system32\drivers\etc\services (Windows)
|
||||
// file in order to resolve a descriptive service name into a port number. A
|
||||
// resolution attempt that would otherwise succeed can therefore fail if the file
|
||||
// is inaccessible or corrupted (which is rare but can happen in practice). We
|
||||
// hardcode the port numbers for http and https to prevent this failure mode.
|
||||
if (service == "http") {
|
||||
service = "80";
|
||||
} else if (service == "https") {
|
||||
service = "443";
|
||||
}
|
||||
resolver_.async_resolve(host, service, [this, host, service, destroyed = destroyed_]
|
||||
(const asio::error_code& ec, asio::ip::tcp::resolver::results_type endpoints)
|
||||
{
|
||||
if (ec == asio::error::operation_aborted or *destroyed)
|
||||
@@ -1137,13 +1147,11 @@ Request::init_parser()
|
||||
response_.request = shared_from_this();
|
||||
|
||||
if (!parser_)
|
||||
parser_ = std::make_unique<http_parser>();
|
||||
http_parser_init(parser_.get(), HTTP_RESPONSE);
|
||||
parser_->data = static_cast<void*>(this);
|
||||
parser_ = std::make_unique<llhttp_t>();
|
||||
|
||||
if (!parser_s_)
|
||||
parser_s_ = std::make_unique<http_parser_settings>();
|
||||
http_parser_settings_init(parser_s_.get());
|
||||
parser_s_ = std::make_unique<llhttp_settings_t>();
|
||||
llhttp_settings_init(parser_s_.get());
|
||||
|
||||
cbs_.on_status = [this, statusCb = std::move(cbs_.on_status)](unsigned int status_code){
|
||||
response_.status_code = status_code;
|
||||
@@ -1158,31 +1166,33 @@ Request::init_parser()
|
||||
response_.headers[*header_field] = std::string(at, length);
|
||||
};
|
||||
|
||||
// http_parser raw c callback (note: no context can be passed into them)
|
||||
parser_s_->on_status = [](http_parser* parser, const char* /*at*/, size_t /*length*/) -> int {
|
||||
// llhttp raw c callback (note: no context can be passed into them)
|
||||
parser_s_->on_status = [](llhttp_t* parser, const char* /*at*/, size_t /*length*/) -> int {
|
||||
static_cast<Request*>(parser->data)->cbs_.on_status(parser->status_code);
|
||||
return 0;
|
||||
};
|
||||
parser_s_->on_header_field = [](http_parser* parser, const char* at, size_t length) -> int {
|
||||
parser_s_->on_header_field = [](llhttp_t* parser, const char* at, size_t length) -> int {
|
||||
static_cast<Request*>(parser->data)->cbs_.on_header_field(at, length);
|
||||
return 0;
|
||||
};
|
||||
parser_s_->on_header_value = [](http_parser* parser, const char* at, size_t length) -> int {
|
||||
parser_s_->on_header_value = [](llhttp_t* parser, const char* at, size_t length) -> int {
|
||||
static_cast<Request*>(parser->data)->cbs_.on_header_value(at, length);
|
||||
return 0;
|
||||
};
|
||||
parser_s_->on_body = [](http_parser* parser, const char* at, size_t length) -> int {
|
||||
parser_s_->on_body = [](llhttp_t* parser, const char* at, size_t length) -> int {
|
||||
static_cast<Request*>(parser->data)->onBody(at, length);
|
||||
return 0;
|
||||
};
|
||||
parser_s_->on_headers_complete = [](http_parser* parser) -> int {
|
||||
parser_s_->on_headers_complete = [](llhttp_t* parser) -> int {
|
||||
static_cast<Request*>(parser->data)->onHeadersComplete();
|
||||
return 0;
|
||||
};
|
||||
parser_s_->on_message_complete = [](http_parser* parser) -> int {
|
||||
parser_s_->on_message_complete = [](llhttp_t* parser) -> int {
|
||||
static_cast<Request*>(parser->data)->onComplete();
|
||||
return 0;
|
||||
};
|
||||
llhttp_init(parser_.get(), HTTP_RESPONSE, parser_s_.get());
|
||||
parser_->data = static_cast<void*>(this);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1339,7 +1349,7 @@ Request::terminate(const asio::error_code& ec)
|
||||
logger_->debug("[http:request:{:d}] done with status code {:d}", id_, response_.status_code);
|
||||
}
|
||||
|
||||
if (!parser_ or !http_should_keep_alive(parser_.get()))
|
||||
if (!parser_ or !llhttp_should_keep_alive(parser_.get()))
|
||||
if (auto c = conn_)
|
||||
c->close();
|
||||
notify_state_change(State::DONE);
|
||||
@@ -1378,17 +1388,15 @@ Request::handle_response(const asio::error_code& ec, size_t /* n_bytes */)
|
||||
return;
|
||||
}
|
||||
auto request = (ec == asio::error::eof) ? std::string{} : conn_->read_bytes();
|
||||
size_t ret = http_parser_execute(parser_.get(), parser_s_.get(), request.c_str(), request.size());
|
||||
if (ret != request.size()) {
|
||||
enum llhttp_errno ret = llhttp_execute(parser_.get(), request.c_str(), request.size());
|
||||
if (ret != HPE_OK && ret != HPE_PAUSED) {
|
||||
if (logger_)
|
||||
logger_->e("Error parsing HTTP: %zu %s %s", ret,
|
||||
http_errno_name(HTTP_PARSER_ERRNO(parser_)),
|
||||
http_errno_description(HTTP_PARSER_ERRNO(parser_)));
|
||||
logger_->e("Error parsing HTTP: %zu %s %d", (int)ret, llhttp_errno_name(ret), llhttp_get_error_reason(parser_.get()));
|
||||
terminate(asio::error::basic_errors::broken_pipe);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state_ != State::DONE and parser_ and not http_body_is_final(parser_.get())) {
|
||||
if (state_ != State::DONE and parser_ and not llhttp_message_needs_eof(parser_.get())) {
|
||||
auto toRead = parser_->content_length ? std::min<uint64_t>(parser_->content_length, 64 * 1024) : 64 * 1024;
|
||||
std::weak_ptr<Request> wthis = shared_from_this();
|
||||
conn_->async_read_some(toRead, [wthis](const asio::error_code& ec, size_t bytes){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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
|
||||
|
||||
+83
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
@@ -143,7 +143,7 @@ NetworkEngine::tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const Inf
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(version >= 1 ? KEY_A : KEY_U);
|
||||
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
@@ -166,6 +166,9 @@ NetworkEngine::tellListenerRefreshed(const Sp<Node>& n, Tid socket_id, const Inf
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
if (version >= 1) {
|
||||
Tid tid (n->getNewTid());
|
||||
@@ -194,7 +197,7 @@ NetworkEngine::tellListenerExpired(const Sp<Node>& n, Tid socket_id, const InfoH
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0));
|
||||
pk.pack_map(4 + (version >= 1 ? 1 : 0) + (config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(version >= 1 ? KEY_A : KEY_U);
|
||||
pk.pack_map(1 + (version >= 1 ? 1 : 0) + (not values.empty()?1:0) + (not token.empty()?1:0));
|
||||
@@ -217,6 +220,9 @@ NetworkEngine::tellListenerExpired(const Sp<Node>& n, Tid socket_id, const InfoH
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
if (version >= 1) {
|
||||
Tid tid (n->getNewTid());
|
||||
@@ -520,8 +526,13 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
throw DhtProtocolException {DhtProtocolException::UNKNOWN_TID, "Can't find socket", msg->id};
|
||||
node->received(now, {});
|
||||
onNewNode(node, 2);
|
||||
deserializeNodes(*msg, from);
|
||||
rsocket->on_receive(node, std::move(*msg));
|
||||
try {
|
||||
deserializeNodes(*msg, from);
|
||||
rsocket->on_receive(node, std::move(*msg));
|
||||
} catch (const DhtProtocolException& e) {
|
||||
if (logger_)
|
||||
logger_->w("Can't deserialize nodes %s", e.what());
|
||||
}
|
||||
}
|
||||
else if (msg->type == MessageType::Error or msg->type == MessageType::Reply) {
|
||||
auto rsocket = node->getSocket(msg->tid);
|
||||
@@ -584,13 +595,22 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
|
||||
r.node->authSuccess();
|
||||
}
|
||||
r.reply_time = scheduler.time();
|
||||
|
||||
deserializeNodes(*msg, from);
|
||||
r.setDone(std::move(*msg));
|
||||
try {
|
||||
deserializeNodes(*msg, from);
|
||||
r.setDone(std::move(*msg));
|
||||
} catch (const DhtProtocolException& e) {
|
||||
if (logger_)
|
||||
logger_->w("Can't deserialize nodes %s", e.what());
|
||||
}
|
||||
break;
|
||||
} else { /* request socket data */
|
||||
deserializeNodes(*msg, from);
|
||||
rsocket->on_receive(node, std::move(*msg));
|
||||
try {
|
||||
deserializeNodes(*msg, from);
|
||||
rsocket->on_receive(node, std::move(*msg));
|
||||
} catch (const DhtProtocolException& e) {
|
||||
if (logger_)
|
||||
logger_->w("Can't deserialize nodes %s", e.what());
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -704,7 +724,7 @@ NetworkEngine::sendPing(const Sp<Node>& node, RequestCb&& on_done, RequestExpire
|
||||
Tid tid (node->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map(1);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -716,6 +736,9 @@ NetworkEngine::sendPing(const Sp<Node>& node, RequestCb&& on_done, RequestExpire
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Ping, tid, node,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -741,7 +764,7 @@ void
|
||||
NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_R); pk.pack_map(2);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -753,6 +776,9 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
@@ -763,7 +789,7 @@ NetworkEngine::sendFindNode(const Sp<Node>& n, const InfoHash& target, want_t wa
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map(2 + (want>0?1:0));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -782,6 +808,9 @@ NetworkEngine::sendFindNode(const Sp<Node>& n, const InfoHash& target, want_t wa
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::FindNode, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -808,7 +837,7 @@ NetworkEngine::sendGetValues(const Sp<Node>& n, const InfoHash& info_hash, const
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
unsigned sendQuery = (not query.where.empty() or not query.select.empty()) ? 1 : 0;
|
||||
unsigned sendWant = (want > 0) ? 1 : 0;
|
||||
@@ -835,7 +864,10 @@ NetworkEngine::sendGetValues(const Sp<Node>& n, const InfoHash& info_hash, const
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::GetValues, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
[=](const Request& req_status, ParsedMessage&& msg) { /* on done */
|
||||
@@ -952,10 +984,13 @@ NetworkEngine::sendValueParts(Tid tid, const std::vector<Blob>& svals, const Soc
|
||||
end = std::min(start + MTU, v.size());
|
||||
buffer.clear();
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(3+(config.network?1:0));
|
||||
pk.pack_map(3+(config.network?1:0)+(config.is_client?1:0));
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
pk.pack(KEY_Y); pk.pack(KEY_V);
|
||||
pk.pack(KEY_TID); pk.pack(tid);
|
||||
pk.pack(KEY_V); pk.pack_map(1);
|
||||
@@ -976,7 +1011,7 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_R);
|
||||
pk.pack_map(2 + (not st.empty()?1:0) + (nodes.size()>0?1:0) + (nodes6.size()>0?1:0) + (not token.empty()?1:0));
|
||||
@@ -1018,6 +1053,9 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
// send response
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
@@ -1089,7 +1127,7 @@ NetworkEngine::sendListen(const Sp<Node>& n,
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
auto has_query = not query.where.empty() or not query.select.empty();
|
||||
pk.pack(KEY_A); pk.pack_map(5 + has_query);
|
||||
@@ -1109,6 +1147,9 @@ NetworkEngine::sendListen(const Sp<Node>& n,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Listen, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -1130,7 +1171,7 @@ void
|
||||
NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_R); pk.pack_map(2);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -1142,6 +1183,9 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
@@ -1158,7 +1202,7 @@ NetworkEngine::sendAnnounceValue(const Sp<Node>& n,
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
bool add_created = created < scheduler.time();
|
||||
pk.pack(KEY_A); pk.pack_map(add_created ? 5 : 4);
|
||||
@@ -1178,6 +1222,9 @@ NetworkEngine::sendAnnounceValue(const Sp<Node>& n,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -1244,7 +1291,7 @@ NetworkEngine::sendUpdateValues(const Sp<Node>& n,
|
||||
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map((created < scheduler.time() ? 7 : 6));
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -1265,6 +1312,9 @@ NetworkEngine::sendUpdateValues(const Sp<Node>& n,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::UpdateValue, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -1289,7 +1339,7 @@ NetworkEngine::sendRefreshValue(const Sp<Node>& n,
|
||||
Tid tid (n->getNewTid());
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(5+(config.network?1:0));
|
||||
pk.pack_map(5+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_A); pk.pack_map(4);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -1304,6 +1354,9 @@ NetworkEngine::sendRefreshValue(const Sp<Node>& n,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
auto req = std::make_shared<Request>(MessageType::Refresh, tid, n,
|
||||
Blob(buffer.data(), buffer.data() + buffer.size()),
|
||||
@@ -1335,7 +1388,7 @@ void
|
||||
NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid) {
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4+(config.network?1:0));
|
||||
pk.pack_map(4+(config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_R); pk.pack_map(3);
|
||||
pk.pack(KEY_REQ_ID); pk.pack(myid);
|
||||
@@ -1348,6 +1401,9 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
@@ -1361,7 +1417,7 @@ NetworkEngine::sendError(const SockAddr& addr,
|
||||
{
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_map(4 + (include_id?1:0) + (config.network?1:0));
|
||||
pk.pack_map(4 + (include_id?1:0) + (config.network?1:0)+(config.is_client?1:0));
|
||||
|
||||
pk.pack(KEY_E); pk.pack_array(2);
|
||||
pk.pack(code);
|
||||
@@ -1378,6 +1434,9 @@ NetworkEngine::sendError(const SockAddr& addr,
|
||||
if (config.network) {
|
||||
pk.pack(KEY_NETID); pk.pack(config.network);
|
||||
}
|
||||
if (config.is_client) {
|
||||
pk.pack(KEY_ISCLIENT); pk.pack(config.is_client);
|
||||
}
|
||||
|
||||
send(addr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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
|
||||
|
||||
+88
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author(s) : Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
||||
* Vsevolod Ivanov <vsevolod.ivanov@savoirfairelinux.com>
|
||||
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
@@ -22,6 +22,10 @@
|
||||
#include "network_utils.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "compat/getif_workaround_android.h"
|
||||
#endif
|
||||
|
||||
#include <asio.hpp>
|
||||
|
||||
using namespace std::literals;
|
||||
@@ -38,16 +42,17 @@ public:
|
||||
DomainPeerDiscovery(asio::ip::udp domain, in_port_t port, Sp<asio::io_context> ioContext = {}, Sp<Logger> logger = {});
|
||||
~DomainPeerDiscovery();
|
||||
|
||||
void startDiscovery(const std::string &type, ServiceDiscoveredCallback callback);
|
||||
void startPublish(const std::string &type, const msgpack::sbuffer &pack_buf);
|
||||
void startDiscovery(std::string_view type, ServiceDiscoveredCallback callback);
|
||||
void startPublish(std::string_view type, const msgpack::sbuffer &pack_buf);
|
||||
|
||||
void stop();
|
||||
|
||||
bool stopDiscovery(const std::string &type);
|
||||
bool stopPublish(const std::string &type);
|
||||
bool stopDiscovery(std::string_view type);
|
||||
bool stopPublish(std::string_view type);
|
||||
|
||||
void connectivityChanged();
|
||||
|
||||
void stopConnectivityChanged();
|
||||
private:
|
||||
Sp<Logger> logger_;
|
||||
//dmtx_ for callbackmap_ and drunning_ (write)
|
||||
@@ -55,6 +60,14 @@ private:
|
||||
//mtx_ for messages_ and lrunning (listen)
|
||||
std::mutex mtx_;
|
||||
std::shared_ptr<asio::io_context> ioContext_;
|
||||
|
||||
static constexpr dht::duration PeerDiscovery_PERIOD_MAX{
|
||||
std::chrono::minutes(1)};
|
||||
static constexpr std::chrono::seconds PeerDiscovery_PERIOD{10};
|
||||
asio::steady_timer peerDiscoveryTimer;
|
||||
std::chrono::steady_clock::duration peerDiscovery_period{
|
||||
PeerDiscovery_PERIOD};
|
||||
|
||||
asio::ip::udp::socket sockFd_;
|
||||
asio::ip::udp::endpoint sockAddrSend_;
|
||||
|
||||
@@ -62,7 +75,7 @@ private:
|
||||
asio::ip::udp::endpoint receiveFrom_;
|
||||
|
||||
msgpack::sbuffer sbuf_;
|
||||
std::map<std::string, msgpack::sbuffer> messages_;
|
||||
std::map<std::string, msgpack::sbuffer, std::less<>> messages_;
|
||||
std::map<std::string, ServiceDiscoveredCallback, std::less<>> callbackmap_;
|
||||
bool lrunning_ {false};
|
||||
bool drunning_ {false};
|
||||
@@ -82,8 +95,9 @@ private:
|
||||
PeerDiscovery::DomainPeerDiscovery::DomainPeerDiscovery(asio::ip::udp domain, in_port_t port, Sp<asio::io_context> ioContext, Sp<Logger> logger)
|
||||
: logger_(logger)
|
||||
, ioContext_(ioContext)
|
||||
, peerDiscoveryTimer(*ioContext_)
|
||||
, sockFd_(*ioContext_, domain)
|
||||
, sockAddrSend_(asio::ip::address::from_string(domain.family() == AF_INET ? MULTICAST_ADDRESS_IPV4
|
||||
, sockAddrSend_(asio::ip::make_address(domain.family() == AF_INET ? MULTICAST_ADDRESS_IPV4
|
||||
: MULTICAST_ADDRESS_IPV6), port)
|
||||
{
|
||||
try {
|
||||
@@ -91,8 +105,23 @@ PeerDiscovery::DomainPeerDiscovery::DomainPeerDiscovery(asio::ip::udp domain, in
|
||||
sockFd_.set_option(asio::ip::udp::socket::reuse_address(true));
|
||||
sockFd_.bind({domain, port});
|
||||
} catch (const std::exception& e) {
|
||||
#ifdef __ANDROID__
|
||||
if(domain.family() == AF_INET && strcmp(e.what(), "set_option: No such device") == 0) {
|
||||
try{
|
||||
sockFd_.set_option(asio::ip::udp::socket::reuse_address(true));
|
||||
auto mc_interface = workaround::get_interface();
|
||||
sockFd_.set_option(asio::ip::multicast::outbound_interface(mc_interface));
|
||||
sockFd_.set_option(asio::ip::multicast::join_group(sockAddrSend_.address().to_v4(), mc_interface));
|
||||
sockFd_.bind({domain, port});
|
||||
} catch(const std::exception& e){
|
||||
if (logger_)
|
||||
logger_->error("Can't start peer discovery using android workaround: {}", e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (logger_)
|
||||
logger_->e("Can't start peer discovery for %s: %s",
|
||||
logger_->error("Can't start peer discovery for {}: {}",
|
||||
domain.family() == AF_INET ? "IPv4" : "IPv6", e.what());
|
||||
}
|
||||
}
|
||||
@@ -104,13 +133,13 @@ PeerDiscovery::DomainPeerDiscovery::~DomainPeerDiscovery()
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::startDiscovery(const std::string &type, ServiceDiscoveredCallback callback)
|
||||
PeerDiscovery::DomainPeerDiscovery::startDiscovery(std::string_view type, ServiceDiscoveredCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
callbackmap_[type] = callback;
|
||||
callbackmap_[std::string(type)] = callback;
|
||||
if (not drunning_) {
|
||||
drunning_ = true;
|
||||
ioContext_->post([this] () {
|
||||
asio::post(*ioContext_, [this] () {
|
||||
loopListener();
|
||||
query(sockAddrSend_);
|
||||
});
|
||||
@@ -207,23 +236,25 @@ PeerDiscovery::DomainPeerDiscovery::publish(const asio::ip::udp::endpoint& peer)
|
||||
|
||||
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::startPublish(const std::string &type, const msgpack::sbuffer &pack_buf)
|
||||
PeerDiscovery::DomainPeerDiscovery::startPublish(std::string_view type, const msgpack::sbuffer &pack_buf)
|
||||
{
|
||||
msgpack::sbuffer pack_buf_c(pack_buf.size());
|
||||
pack_buf_c.write(pack_buf.data(), pack_buf.size());
|
||||
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
messages_[type] = std::move(pack_buf_c);
|
||||
messages_[std::string(type)] = std::move(pack_buf_c);
|
||||
reloadMessages();
|
||||
lrunning_ = true;
|
||||
ioContext_->post([this] () { publish(sockAddrSend_); });
|
||||
asio::post(*ioContext_, [this] () { publish(sockAddrSend_); });
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopDiscovery(const std::string& type)
|
||||
PeerDiscovery::DomainPeerDiscovery::stopDiscovery(std::string_view type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
if (callbackmap_.erase(type) > 0) {
|
||||
auto it = callbackmap_.find(type);
|
||||
if (it != callbackmap_.end()) {
|
||||
callbackmap_.erase(it);
|
||||
if (callbackmap_.empty())
|
||||
stopDiscovery();
|
||||
return true;
|
||||
@@ -232,10 +263,12 @@ PeerDiscovery::DomainPeerDiscovery::stopDiscovery(const std::string& type)
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopPublish(const std::string& type)
|
||||
PeerDiscovery::DomainPeerDiscovery::stopPublish(std::string_view type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
if (messages_.erase(type) > 0) {
|
||||
auto it = messages_.find(type);
|
||||
if (it != messages_.end()) {
|
||||
messages_.erase(it);
|
||||
if (messages_.empty())
|
||||
stopPublish();
|
||||
else
|
||||
@@ -298,8 +331,30 @@ PeerDiscovery::DomainPeerDiscovery::reDiscover()
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::connectivityChanged()
|
||||
{
|
||||
reDiscover();
|
||||
publish(sockAddrSend_);
|
||||
asio::post(*ioContext_, [this] () {
|
||||
reDiscover();
|
||||
publish(sockAddrSend_);
|
||||
});
|
||||
if (logger_)
|
||||
logger_->d("PeerDiscovery: connectivity changed");
|
||||
|
||||
if (peerDiscovery_period == PeerDiscovery_PERIOD_MAX ){
|
||||
peerDiscovery_period = PeerDiscovery_PERIOD;
|
||||
}
|
||||
else{
|
||||
peerDiscoveryTimer.expires_after(peerDiscovery_period);
|
||||
peerDiscoveryTimer.async_wait([this](const asio::error_code& ec) {
|
||||
if (ec == asio::error::operation_aborted)
|
||||
return;
|
||||
connectivityChanged();
|
||||
});
|
||||
peerDiscovery_period = std::min(peerDiscovery_period * 2, PeerDiscovery_PERIOD_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerDiscovery::DomainPeerDiscovery::stopConnectivityChanged() {
|
||||
peerDiscoveryTimer.cancel();
|
||||
peerDiscovery_period = PeerDiscovery_PERIOD;
|
||||
}
|
||||
|
||||
PeerDiscovery::PeerDiscovery(in_port_t port, Sp<asio::io_context> ioContext, Sp<Logger> logger)
|
||||
@@ -346,21 +401,21 @@ PeerDiscovery::~PeerDiscovery() {
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startDiscovery(const std::string& type, ServiceDiscoveredCallback callback)
|
||||
PeerDiscovery::startDiscovery(std::string_view type, ServiceDiscoveredCallback callback)
|
||||
{
|
||||
if (peerDiscovery4_) peerDiscovery4_->startDiscovery(type, callback);
|
||||
if (peerDiscovery6_) peerDiscovery6_->startDiscovery(type, callback);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startPublish(const std::string& type, const msgpack::sbuffer& pack_buf)
|
||||
PeerDiscovery::startPublish(std::string_view type, const msgpack::sbuffer& pack_buf)
|
||||
{
|
||||
if (peerDiscovery4_) peerDiscovery4_->startPublish(type, pack_buf);
|
||||
if (peerDiscovery6_) peerDiscovery6_->startPublish(type, pack_buf);
|
||||
}
|
||||
|
||||
void
|
||||
PeerDiscovery::startPublish(sa_family_t domain, const std::string& type, const msgpack::sbuffer& pack_buf)
|
||||
PeerDiscovery::startPublish(sa_family_t domain, std::string_view type, const msgpack::sbuffer& pack_buf)
|
||||
{
|
||||
if (domain == AF_INET) {
|
||||
if (peerDiscovery4_) peerDiscovery4_->startPublish(type, pack_buf);
|
||||
@@ -377,7 +432,7 @@ PeerDiscovery::stop()
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopDiscovery(const std::string &type)
|
||||
PeerDiscovery::stopDiscovery(std::string_view type)
|
||||
{
|
||||
bool stopped4 = peerDiscovery4_ and peerDiscovery4_->stopDiscovery(type);
|
||||
bool stopped6 = peerDiscovery6_ and peerDiscovery6_->stopDiscovery(type);
|
||||
@@ -385,7 +440,7 @@ PeerDiscovery::stopDiscovery(const std::string &type)
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopPublish(const std::string &type)
|
||||
PeerDiscovery::stopPublish(std::string_view type)
|
||||
{
|
||||
bool stopped4 = peerDiscovery4_ and peerDiscovery4_->stopPublish(type);
|
||||
bool stopped6 = peerDiscovery6_ and peerDiscovery6_->stopPublish(type);
|
||||
@@ -393,7 +448,7 @@ PeerDiscovery::stopPublish(const std::string &type)
|
||||
}
|
||||
|
||||
bool
|
||||
PeerDiscovery::stopPublish(sa_family_t domain, const std::string& type)
|
||||
PeerDiscovery::stopPublish(sa_family_t domain, std::string_view type)
|
||||
{
|
||||
if (domain == AF_INET) {
|
||||
return peerDiscovery4_ and peerDiscovery4_->stopPublish(type);
|
||||
@@ -412,4 +467,11 @@ PeerDiscovery::connectivityChanged()
|
||||
peerDiscovery6_->connectivityChanged();
|
||||
}
|
||||
|
||||
void PeerDiscovery::stopConnectivityChanged() {
|
||||
if (peerDiscovery4_)
|
||||
peerDiscovery4_->stopConnectivityChanged();
|
||||
if (peerDiscovery6_)
|
||||
peerDiscovery6_->stopConnectivityChanged();
|
||||
}
|
||||
|
||||
} /* namespace dht */
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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
|
||||
|
||||
+27
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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
|
||||
@@ -45,7 +45,7 @@ struct Dht::Announce {
|
||||
bool permanent;
|
||||
Sp<Value> value;
|
||||
time_point created;
|
||||
DoneCallback callback;
|
||||
std::vector<DoneCallback> callbacks;
|
||||
};
|
||||
|
||||
struct Dht::SearchNode {
|
||||
@@ -442,8 +442,9 @@ struct Dht::Search {
|
||||
g.second.done_cb = {};
|
||||
}
|
||||
for (auto& a : announce) {
|
||||
a.callback(false, {});
|
||||
a.callback = {};
|
||||
for (auto& cb : a.callbacks)
|
||||
cb(false, {});
|
||||
a.callbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,7 +628,9 @@ struct Dht::Search {
|
||||
return a.value->id == value->id;
|
||||
});
|
||||
if (a_sr == announce.end()) {
|
||||
announce.emplace_back(Announce {permanent, value, created, callback});
|
||||
auto& a = announce.emplace_back(Announce {permanent, value, created, {}} );
|
||||
if (callback)
|
||||
a.callbacks.emplace_back(std::move(callback));
|
||||
for (auto& n : nodes) {
|
||||
n->probe_query.reset();
|
||||
n->acked[value->id].req.reset();
|
||||
@@ -635,24 +638,26 @@ struct Dht::Search {
|
||||
} else {
|
||||
a_sr->permanent = permanent;
|
||||
a_sr->created = created;
|
||||
if (a_sr->value != value) {
|
||||
if (a_sr->value != value && *a_sr->value != *value) {
|
||||
// Value is updated, previous ops are failed
|
||||
a_sr->value = value;
|
||||
for (auto& n : nodes) {
|
||||
n->acked[value->id].req.reset();
|
||||
n->probe_query.reset();
|
||||
}
|
||||
}
|
||||
if (isAnnounced(value->id)) {
|
||||
if (a_sr->callback)
|
||||
a_sr->callback(true, {});
|
||||
a_sr->callback = {};
|
||||
for (auto& cb: a_sr->callbacks)
|
||||
cb(false, {});
|
||||
a_sr->callbacks.clear();
|
||||
if (callback)
|
||||
a_sr->callbacks.emplace_back(std::move(callback));
|
||||
} else if (isAnnounced(value->id)) {
|
||||
// Same value, already announced
|
||||
if (callback)
|
||||
callback(true, {});
|
||||
return;
|
||||
} else {
|
||||
if (a_sr->callback)
|
||||
a_sr->callback(false, {});
|
||||
a_sr->callback = callback;
|
||||
// Same value, not announced yet
|
||||
if (callback)
|
||||
a_sr->callbacks.emplace_back(std::move(callback));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -722,8 +727,8 @@ struct Dht::Search {
|
||||
std::vector<DoneCallback> a_cbs;
|
||||
a_cbs.reserve(announce.size());
|
||||
for (auto ait = announce.begin() ; ait != announce.end(); ) {
|
||||
if (ait->callback)
|
||||
a_cbs.emplace_back(std::move(ait->callback));
|
||||
a_cbs.insert(a_cbs.end(), std::make_move_iterator(ait->callbacks.begin()), std::make_move_iterator(ait->callbacks.end()));
|
||||
ait->callbacks.clear();
|
||||
if (not ait->permanent)
|
||||
ait = announce.erase(ait);
|
||||
else
|
||||
@@ -747,9 +752,11 @@ struct Dht::Search {
|
||||
if (vid != Value::INVALID_ID and (!a.value || a.value->id != vid))
|
||||
return true;
|
||||
if (isAnnounced(a.value->id)) {
|
||||
if (a.callback) {
|
||||
a.callback(true, getNodes());
|
||||
a.callback = nullptr;
|
||||
if (!a.callbacks.empty()) {
|
||||
const auto& nodes = getNodes();
|
||||
for (auto& cb : a.callbacks)
|
||||
cb(true, nodes);
|
||||
a.callbacks.clear();
|
||||
}
|
||||
if (not a.permanent)
|
||||
return false;
|
||||
|
||||
+157
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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>
|
||||
@@ -50,9 +50,10 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf,
|
||||
|
||||
if (certificate_) {
|
||||
auto certId = certificate_->getId();
|
||||
if (key_ and certId != key_->getPublicKey().getId())
|
||||
auto certLongId = certificate_->getLongId();
|
||||
if (key_ and (certId != key_->getPublicKey().getId() or certLongId != key_->getPublicKey().getLongId()))
|
||||
throw DhtException("SecureDht: provided certificate doesn't match private key.");
|
||||
dht_->addOnConnectedCallback([this, certId, cb=std::move(iacb)]{
|
||||
dht_->addOnConnectedCallback([this, certId, certLongId, cb=std::move(iacb)]{
|
||||
dht_->put(certId, Value {
|
||||
CERTIFICATE_TYPE,
|
||||
*certificate_,
|
||||
@@ -62,6 +63,15 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf,
|
||||
if (logger_)
|
||||
logger_->d(certId, "SecureDht: certificate announcement %s", ok ? "succeeded" : "failed");
|
||||
}, {}, true);
|
||||
dht_->put(InfoHash::get(certLongId), Value {
|
||||
CERTIFICATE_TYPE,
|
||||
*certificate_,
|
||||
1
|
||||
}, [this, cb=std::move(cb)](bool ok) {
|
||||
if (cb) cb(ok);
|
||||
if (logger_)
|
||||
logger_->debug("SecureDht: certificate announcement {}", ok ? "succeeded" : "failed");
|
||||
}, {}, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -131,6 +141,30 @@ SecureDht::getPublicKey(const InfoHash& node) const
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::getCertificate(const PkId& node) const
|
||||
{
|
||||
if (node == getLongId())
|
||||
return certificate_;
|
||||
auto it = nodesCertificatesLong_.find(node);
|
||||
if (it == nodesCertificatesLong_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Sp<crypto::PublicKey>
|
||||
SecureDht::getPublicKey(const PkId& node) const
|
||||
{
|
||||
if (node == getLongId())
|
||||
return certificate_->getSharedPublicKey();
|
||||
auto it = nodesPubKeysLong_.find(node);
|
||||
if (it == nodesPubKeysLong_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
{
|
||||
@@ -143,25 +177,44 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
|
||||
InfoHash h = crt->getPublicKey().getId();
|
||||
if (node == h) {
|
||||
if (logger_)
|
||||
logger_->d("Registering certificate for %s", h.toString().c_str());
|
||||
auto it = nodesCertificates_.find(h);
|
||||
if (it == nodesCertificates_.end())
|
||||
std::tie(it, std::ignore) = nodesCertificates_.emplace(h, std::move(crt));
|
||||
else
|
||||
it->second = std::move(crt);
|
||||
return it->second;
|
||||
logger_->debug("Registering certificate for {}", h.toString());
|
||||
registerCertificate(crt);
|
||||
return crt;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w("Certificate %s for node %s does not match node id !", h.toString().c_str(), node.toString().c_str());
|
||||
logger_->w("Certificate {} for node {} does not match node id !", h.toString(), node.toString());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::registerCertificate(const PkId& node, const Blob& data)
|
||||
{
|
||||
Sp<crypto::Certificate> crt;
|
||||
try {
|
||||
crt = std::make_shared<crypto::Certificate>(data);
|
||||
} catch (const std::exception& e) {
|
||||
return nullptr;
|
||||
}
|
||||
auto h = crt->getPublicKey().getLongId();
|
||||
if (node == h) {
|
||||
if (logger_)
|
||||
logger_->debug("Registering certificate for {}", h.toString());
|
||||
registerCertificate(crt);
|
||||
return crt;
|
||||
} else {
|
||||
if (logger_)
|
||||
logger_->w("Certificate {} for node {} does not match node id !", h.toString(), node.toString());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::registerCertificate(Sp<crypto::Certificate>& cert)
|
||||
SecureDht::registerCertificate(const Sp<crypto::Certificate>& cert)
|
||||
{
|
||||
if (cert)
|
||||
if (cert) {
|
||||
nodesCertificates_[cert->getId()] = cert;
|
||||
nodesCertificatesLong_[cert->getLongId()] = cert;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -222,6 +275,63 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp
|
||||
auto pk = crt->getSharedPublicKey();
|
||||
if (*pk) {
|
||||
nodesPubKeys_[pk->getId()] = pk;
|
||||
nodesPubKeysLong_[pk->getLongId()] = pk;
|
||||
if (cb) cb(pk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cb) cb(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findCertificate(const PkId& node, const std::function<void(const Sp<crypto::Certificate>)>& cb)
|
||||
{
|
||||
Sp<crypto::Certificate> b = getCertificate(node);
|
||||
if (b && *b) {
|
||||
if (logger_)
|
||||
logger_->debug("Using certificate from cache for {}", node.to_c_str());
|
||||
if (cb)
|
||||
cb(b);
|
||||
return;
|
||||
}
|
||||
|
||||
auto found = std::make_shared<bool>(false);
|
||||
dht_->get(InfoHash::get(node), [cb,node,found,this](const std::vector<Sp<Value>>& vals) {
|
||||
for (const auto& v : vals) {
|
||||
if (auto cert = registerCertificate(node, v->data)) {
|
||||
*found = true;
|
||||
if (logger_)
|
||||
logger_->debug("Found certificate for {}", node.to_c_str());
|
||||
if (cb)
|
||||
cb(cert);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !*found;
|
||||
}, [cb,found](bool) {
|
||||
if (!*found and cb)
|
||||
cb(nullptr);
|
||||
}, Value::TypeFilter(CERTIFICATE_TYPE));
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findPublicKey(const PkId& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb)
|
||||
{
|
||||
auto pk = getPublicKey(node);
|
||||
if (pk && *pk) {
|
||||
if (logger_)
|
||||
logger_->debug("Found public key from cache for {}", node.to_c_str());
|
||||
if (cb)
|
||||
cb(pk);
|
||||
return;
|
||||
}
|
||||
findCertificate(node, [=](const Sp<crypto::Certificate>& crt) {
|
||||
if (crt && *crt) {
|
||||
auto pk = crt->getSharedPublicKey();
|
||||
if (*pk) {
|
||||
nodesPubKeys_[pk->getId()] = pk;
|
||||
nodesPubKeysLong_[pk->getLongId()] = pk;
|
||||
if (cb) cb(pk);
|
||||
return;
|
||||
}
|
||||
@@ -246,8 +356,10 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
auto isDecrypted = v->isDecrypted();
|
||||
if (auto decrypted_val = v->decrypt(*key_)) {
|
||||
auto cacheValue = not isDecrypted and decrypted_val->owner;
|
||||
if (cacheValue)
|
||||
if (cacheValue) {
|
||||
nodesPubKeys_[decrypted_val->owner->getId()] = decrypted_val->owner;
|
||||
nodesPubKeysLong_[decrypted_val->owner->getLongId()] = decrypted_val->owner;
|
||||
}
|
||||
return decrypted_val;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
@@ -259,8 +371,10 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
else if (v->isSigned()) {
|
||||
auto cacheValue = not v->isSignatureChecked() and enableCache_ and v->owner;
|
||||
if (v->checkSignature()) {
|
||||
if (cacheValue)
|
||||
if (cacheValue) {
|
||||
nodesPubKeys_[v->owner->getId()] = v->owner;
|
||||
nodesPubKeysLong_[v->owner->getLongId()] = v->owner;
|
||||
}
|
||||
return v;
|
||||
} else if (logger_)
|
||||
logger_->w("Signature verification failed for %s", v->toString().c_str());
|
||||
@@ -401,6 +515,33 @@ SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val,
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
if (not key_) {
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
}
|
||||
findPublicKey(to, [this, hash, val = std::move(val), callback = std::move(callback), permanent](const Sp<crypto::PublicKey>& pk) {
|
||||
if(!pk || !*pk) {
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->warn("Encrypting data for PK: {}", pk->getLongId());
|
||||
try {
|
||||
dht_->put(hash, encrypt(*val, *pk), callback, time_point::max(), permanent);
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->e("Error putting encrypted data: %s", e.what());
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const crypto::PublicKey& pk, Sp<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
@@ -410,7 +551,7 @@ SecureDht::putEncrypted(const InfoHash& hash, const crypto::PublicKey& pk, Sp<Va
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->w("Encrypting data for PK: %s", pk.getLongId().to_c_str());
|
||||
logger_->warn("Encrypting data for PK: {}", pk.getLongId());
|
||||
try {
|
||||
dht_->put(hash, encrypt(*val, pk), callback, time_point::max(), permanent);
|
||||
} catch (const std::exception& e) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 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
|
||||
@@ -224,7 +224,7 @@ Storage::store(const InfoHash& id, const Sp<Value>& value, time_point created, t
|
||||
//DHT_LOG.DEBUG("Updating %s -> %s", id.toString().c_str(), value->toString().c_str());
|
||||
// clear quota for previous value
|
||||
if (it->store_bucket)
|
||||
it->store_bucket->erase(id, *value, it->expiration);
|
||||
it->store_bucket->erase(id, *it->data, it->expiration);
|
||||
it->expiration = expiration;
|
||||
// update quota for new value
|
||||
it->store_bucket = sb;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2023 Savoir-faire Linux Inc.
|
||||
* Copyright (C) 2014-2025 Savoir-faire Linux Inc.
|
||||
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -39,28 +39,26 @@ const char* version() {
|
||||
return PACKAGE_VERSION;
|
||||
}
|
||||
|
||||
const HexMap hex_map = {};
|
||||
|
||||
static constexpr std::array<uint8_t, 12> MAPPED_IPV4_PREFIX {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}};
|
||||
|
||||
std::pair<std::string, std::string>
|
||||
splitPort(const std::string& s) {
|
||||
splitPort(std::string_view s) {
|
||||
if (s.empty())
|
||||
return {};
|
||||
if (s[0] == '[') {
|
||||
std::size_t closure = s.find_first_of(']');
|
||||
std::size_t found = s.find_last_of(':');
|
||||
if (closure == std::string::npos)
|
||||
return {s, ""};
|
||||
if (found == std::string::npos or found < closure)
|
||||
return {s.substr(1,closure-1), ""};
|
||||
return {s.substr(1,closure-1), s.substr(found+1)};
|
||||
if (closure == std::string_view::npos)
|
||||
return {std::string(s), ""};
|
||||
if (found == std::string_view::npos or found < closure)
|
||||
return {std::string(s.substr(1,closure-1)), ""};
|
||||
return {std::string(s.substr(1,closure-1)), std::string(s.substr(found+1))};
|
||||
}
|
||||
std::size_t found = s.find_last_of(':');
|
||||
std::size_t first = s.find_first_of(':');
|
||||
if (found == std::string::npos or found != first)
|
||||
return {s, ""};
|
||||
return {s.substr(0,found), s.substr(found+1)};
|
||||
if (found == std::string_view::npos or found != first)
|
||||
return {std::string(s), ""};
|
||||
return {std::string(s.substr(0,found)), std::string(s.substr(found+1))};
|
||||
}
|
||||
|
||||
std::vector<SockAddr>
|
||||
|
||||
Loaded 100 of 130 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user