mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
Compare commits
53
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
370f619ac4 | ||
|
|
7cf3e8b738 | ||
|
|
e924ef5620 | ||
|
|
d96115b445 | ||
|
|
bb96d2d80e | ||
|
|
8b96652b32 | ||
|
|
d1235660d5 | ||
|
|
23c6b5547b | ||
|
|
61c4a3880f | ||
|
|
44f2aaa876 | ||
|
|
a363d573e3 | ||
|
|
3ff9338980 | ||
|
|
ea3c0f0d93 | ||
|
|
f0cf074576 | ||
|
|
760586ed4a | ||
|
|
b951f4f40a | ||
|
|
63cc650a72 | ||
|
|
c020d2e1ef | ||
|
|
aae1bb2ae5 | ||
|
|
593e59e093 | ||
|
|
86d5065aca | ||
|
|
308d8ff82b | ||
|
|
34b9ddd023 | ||
|
|
88cb14ad95 | ||
|
|
e453a47242 | ||
|
|
199090b959 | ||
|
|
d250e6a349 | ||
|
|
99da0be2b7 | ||
|
|
22d219c695 | ||
|
|
ccd4865df5 | ||
|
|
5afc452f32 | ||
|
|
a06596d365 | ||
|
|
aa260c7b40 | ||
|
|
7183847e44 | ||
|
|
884cb09220 | ||
|
|
04edaafa57 | ||
|
|
6be58884aa | ||
|
|
d50d3d4f32 | ||
|
|
8acafe844d | ||
|
|
688b713c09 | ||
|
|
017df59dde | ||
|
|
964800a506 | ||
|
|
4f423d066f | ||
|
|
ae49b96c2d | ||
|
|
3701b21425 | ||
|
|
55af602026 | ||
|
|
eda121297b | ||
|
|
603e777c9e | ||
|
|
bef4e61fc6 | ||
|
|
42971d9587 | ||
|
|
4a43326de1 | ||
|
|
8fcb19627d | ||
|
|
b6ea2ed8e2 |
No files matched your search
@@ -23,11 +23,11 @@ jobs:
|
||||
|
||||
# Run locally with: pipx run cibuildwheel --platform linux python
|
||||
- name: Build wheels
|
||||
uses: pypa/cibuildwheel@v3.4.0
|
||||
uses: pypa/cibuildwheel@v3.4.1
|
||||
with:
|
||||
package-dir: python
|
||||
|
||||
- uses: actions/upload-artifact@v6
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-wheels-${{ matrix.os }}
|
||||
path: ./wheelhouse/*.whl
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
pipx run cibuildwheel python
|
||||
shell: pwsh
|
||||
|
||||
- uses: actions/upload-artifact@v6
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-wheels-win_amd64
|
||||
path: ./build/wheelhouse/*.whl
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_wheels, build_wheels_windows]
|
||||
steps:
|
||||
- uses: actions/download-artifact@v7
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: opendht-wheels-*
|
||||
path: dist
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDeps
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS_LLVM }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDepsLlvm
|
||||
@@ -171,7 +171,7 @@ jobs:
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LLVM }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileLlvm
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DHTNODE }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDhtnode
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE_DEPS }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileDepsAlpine
|
||||
@@ -296,7 +296,7 @@ jobs:
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
file: docker/DockerfileAlpine
|
||||
@@ -324,7 +324,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up MSVC developer environment
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Install WIX using .net tools
|
||||
run: |
|
||||
@@ -403,7 +403,7 @@ jobs:
|
||||
}
|
||||
|
||||
- name: Upload MSI Artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-windows-msi
|
||||
path: build/${{ steps.cpack_msi.outputs.msi_path }} # Path to the MSI in the build directory
|
||||
@@ -428,7 +428,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up MSVC developer environment
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Cache vcpkg static installed packages
|
||||
id: cache-vcpkg-static
|
||||
@@ -483,7 +483,7 @@ jobs:
|
||||
cmake --build build_static --config Release --parallel $([System.Environment]::ProcessorCount)
|
||||
|
||||
- name: Upload Static dhtnode Artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-windows-dhtnode
|
||||
path: |
|
||||
@@ -502,20 +502,20 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download Windows MSI artifact
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: opendht-windows-msi
|
||||
path: downloaded_artifacts/windows_msi
|
||||
|
||||
- name: Download Static dhtnode artifact
|
||||
uses: actions/download-artifact@v7
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: opendht-windows-dhtnode
|
||||
path: downloaded_artifacts/static_dhtnode
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up MSVC
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Generate Cache Key
|
||||
id: generate_cache_key
|
||||
@@ -78,7 +78,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up MSVC
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Generate Cache Key for Static Libs
|
||||
id: generate_static_cache_key
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up MSVC
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Restore vcpkg installed packages
|
||||
id: cache-vcpkg-restore
|
||||
@@ -181,7 +181,7 @@ jobs:
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-windows-${{ matrix.arch }}-cxx${{ matrix.cxx_standard }}-${{ matrix.build_type }}
|
||||
path: |
|
||||
@@ -205,7 +205,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up MSVC
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@v3
|
||||
|
||||
- name: Restore vcpkg static installed packages
|
||||
id: cache-vcpkg-static-restore
|
||||
@@ -256,7 +256,7 @@ jobs:
|
||||
ctest --build-config ${{ matrix.build_type }} --output-on-failure --parallel 4
|
||||
|
||||
- name: Upload static build artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-windows-static-${{ matrix.arch }}-cxx${{ matrix.cxx_standard }}-${{ matrix.build_type }}
|
||||
path: |
|
||||
@@ -375,7 +375,7 @@ jobs:
|
||||
|
||||
- name: Upload MinGW artifacts
|
||||
if: matrix.build_type == 'Release'
|
||||
uses: actions/upload-artifact@v6
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: opendht-windows-mingw-${{ matrix.build_type }}
|
||||
path: |
|
||||
|
||||
@@ -67,7 +67,7 @@ sudo dnf install python3-Cython python3-devel redhat-rpm-config
|
||||
### macOS
|
||||
|
||||
```sh
|
||||
brew install gnutls msgpack-cxx argon2 asio readline jsoncpp fmt
|
||||
brew install gnutls msgpack-cxx argon2 asio readline jsoncpp fmt llhttp
|
||||
```
|
||||
|
||||
## Build
|
||||
@@ -81,7 +81,7 @@ git clone https://github.com/savoirfairelinux/opendht.git
|
||||
# Build and install
|
||||
cd opendht
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
```
|
||||
@@ -100,8 +100,7 @@ cmake -DOPENDHT_PYTHON=ON \
|
||||
-DOPENDHT_PROXY_SERVER=ON \
|
||||
-DOPENDHT_PROXY_SERVER_IDENTITY=ON \
|
||||
-DOPENDHT_PROXY_CLIENT=ON \
|
||||
-DOPENDHT_PUSH_NOTIFICATIONS=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr ..
|
||||
-DOPENDHT_PUSH_NOTIFICATIONS=ON ..
|
||||
```
|
||||
|
||||
#### Common CMake options
|
||||
|
||||
+9
-2
@@ -9,8 +9,8 @@ if(POLICY CMP0167)
|
||||
cmake_policy(SET CMP0167 NEW)
|
||||
endif()
|
||||
|
||||
set (opendht_VERSION_MAJOR 3)
|
||||
set (opendht_VERSION_MINOR 7.3)
|
||||
set (opendht_VERSION_MAJOR 4)
|
||||
set (opendht_VERSION_MINOR 0.0)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -130,6 +130,7 @@ if (NOT MSVC)
|
||||
message(STATUS "simdutf not found with pkgconfig")
|
||||
if (OPENDHT_DOWNLOAD_DEPS)
|
||||
message(STATUS "Fallback mode specified, downloading simdutf")
|
||||
set(SIMDUTF_CXX_STANDARD ${CMAKE_CXX_STANDARD} CACHE INTERNAL "C++ standard for simdutf downloader")
|
||||
set(SIMDUTF_TESTS OFF CACHE INTERNAL "Disable tests for simdutf downloader")
|
||||
set(SIMDUTF_TOOLS OFF CACHE INTERNAL "Disable tools for simdutf downloader")
|
||||
FetchContent_Declare(simdutf
|
||||
@@ -870,6 +871,12 @@ if (BUILD_TESTING)
|
||||
tests/test_networkengine.h
|
||||
tests/test_networkengine.cpp
|
||||
)
|
||||
if (OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND test_FILES
|
||||
tests/test_dhtproxy_client.h
|
||||
tests/test_dhtproxy_client.cpp
|
||||
)
|
||||
endif()
|
||||
if (OPENDHT_TESTS_NETWORK)
|
||||
if (OPENDHT_PROXY_SERVER AND OPENDHT_PROXY_CLIENT)
|
||||
list (APPEND test_FILES
|
||||
|
||||
+2
-2
@@ -600,7 +600,7 @@ dht_runner_put_signed(
|
||||
void
|
||||
dht_runner_put_encrypted(dht_runner* r,
|
||||
const dht_infohash* h,
|
||||
const dht_infohash* to,
|
||||
const dht_pkid* to,
|
||||
const dht_value* v,
|
||||
dht_done_cb done_cb,
|
||||
void* cb_user_data,
|
||||
@@ -608,7 +608,7 @@ dht_runner_put_encrypted(dht_runner* r,
|
||||
{
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
|
||||
auto toHash = reinterpret_cast<const dht::InfoHash*>(to);
|
||||
auto toHash = reinterpret_cast<const dht::PkId*>(to);
|
||||
auto value = reinterpret_cast<const ValueSp*>(v);
|
||||
runner->putEncrypted(
|
||||
*hash,
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@ OPENDHT_C_PUBLIC void dht_runner_put_signed(dht_runner* runner,
|
||||
bool permanent);
|
||||
OPENDHT_C_PUBLIC void dht_runner_put_encrypted(dht_runner* runner,
|
||||
const dht_infohash* hash,
|
||||
const dht_infohash* to,
|
||||
const dht_pkid* to,
|
||||
const dht_value* value,
|
||||
dht_done_cb done_cb,
|
||||
void* cb_user_data,
|
||||
|
||||
+145
-54
@@ -1,102 +1,193 @@
|
||||
.TH DHTNODE 1 2019-06-08
|
||||
.TH DHTNODE 1 2026-04-18
|
||||
.SH NAME
|
||||
.B dhtnode
|
||||
- a simple OpenDHT command line node runner.
|
||||
.SH SYNOPSIS
|
||||
.B dhtnode
|
||||
[\fB\-h\fR]
|
||||
[\fB\-V\fR]
|
||||
[\fB\-v\fR [\fB\-l\fR \fIlogfile\fR] [\fB\-L\fR]]
|
||||
[\fB\-i\fR [\fB\-\-save\-identity\fR \fIfile\fR]]
|
||||
[\fB\-i\fR [\fB\-I\fR \fIfile\fR]]
|
||||
[\fB\-c\fR \fIfile\fR]
|
||||
[\fB\-k\fR \fIfile\fR]
|
||||
[\fB\-m\fR \fIpassword\fR]
|
||||
[\fB\-d\fR] [\fB\-s\fR]
|
||||
[\fB\-D\fR] [\fB\-U\fR] [\fB\-P\fR]
|
||||
[\fB\-n\fR \fInetwork_id\fR]
|
||||
[\fB\-p\fR \fIlocal_port\fR]
|
||||
[\fB\-b\fR \fIbootstrap_host\fR[:\fIport\fR]]
|
||||
[\fB\-\-certificate\fR \fIfile\fR]
|
||||
[\fB\-\-privkey\fR \fIfile\fR]
|
||||
[\fB\-\-privkey\-password\fR \fIpassword\fR]
|
||||
[\fB\-\-proxyserver\fR \fIport\fR]
|
||||
[\fB\-\-proxyclient\fR \fIserver\fR]
|
||||
[\fB\-f\fR \fIpath\fR]
|
||||
[\fB\-S\fR \fIport\fR]
|
||||
[\fB\-e\fR \fIport\fR]
|
||||
[\fB\-a\fR \fIaddress\fR]
|
||||
[\fB\-w\fR \fIfile\fR]
|
||||
[\fB\-K\fR \fIfile\fR]
|
||||
[\fB\-M\fR \fIpassword\fR]
|
||||
[\fB\-C\fR \fIserver\fR]
|
||||
[\fB\-y\fR \fIendpoint\fR]
|
||||
[\fB\-z\fR \fIkey\fR]
|
||||
[\fB\-u\fR \fIbundleid\fR]
|
||||
.SH DESCRIPTION
|
||||
Runs an OpenDHT node, with a CLI (default) or as a daemon (with \fB'-d'\fP or \fB'-s'\fP).
|
||||
Runs an OpenDHT node, with an interactive CLI (default) or as a daemon (with \fB'-d'\fP or \fB'-s'\fP).
|
||||
Commands available in the interactive shell are:
|
||||
.EX
|
||||
h, help Print this help message.
|
||||
q, quit Quit the program.
|
||||
x, quit Quit the program.
|
||||
log Start/stop printing DHT logs.
|
||||
|
||||
Node information:
|
||||
ll Print basic information and stats about the current node.
|
||||
ls Print basic information about current searches.
|
||||
ld Print basic information about currenty stored values on this node.
|
||||
lr Print the full current routing table of this node
|
||||
ls [key] Print basic information about current search(es).
|
||||
ld [key] Print basic information about currenty stored values on this
|
||||
node (or for a specific key).
|
||||
lr Print the full current routing table of this node.
|
||||
|
||||
Operations on the DHT:
|
||||
b ip:port Ping potential node at given IP address/port.
|
||||
g [key] Get values at [key].
|
||||
l [key] Listen for value changes at [key].
|
||||
p [key] [str] Put string value at [key].
|
||||
s [key] [str] Put string value at [key], signed with our generated
|
||||
private key.
|
||||
e [key] [dest] [str] Put string value at [key], encrypted for [dest] with
|
||||
its public key (if found).
|
||||
b <ip:port> Ping potential node at given IP address/port.
|
||||
g <key> Get values at <key>.
|
||||
l <key> Listen for value changes at <key>.
|
||||
cl <key> <token> Cancel listen for <token> and <key>.
|
||||
p <key> <str> Put string value at <key>.
|
||||
pp <key> <str> Put string value at <key> (persistent version).
|
||||
cpp <key> <id> Cancel persistent put operation for <key> and
|
||||
value <id>.
|
||||
s <key> <str> Put string value at <key>, signed with our
|
||||
generated private key.
|
||||
e <key> <dest> <str> Put string value at <key>, encrypted for <dest>
|
||||
with its public key (if found).
|
||||
cc Trigger connectivity changed signal.
|
||||
|
||||
Operations with the proxy (if compiled with proxy server support):
|
||||
pst [port] <pushServer> Start the proxy interface on port.
|
||||
psx [port] Start the proxy SSL interface on port.
|
||||
psp [port] Stop the proxy interface on port.
|
||||
|
||||
Operations with the proxy (if compiled with proxy client support):
|
||||
stt [server_address] <device_key> Start the proxy client.
|
||||
stp Stop the proxy client.
|
||||
rs [token] Resubscribe to opendht.
|
||||
rp [token] Inject a push notification.
|
||||
.EE
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-h\fP
|
||||
Prints some help.
|
||||
\fB\-h\fP, \fB\-\-help\fP
|
||||
Prints help and exits.
|
||||
.TP
|
||||
\fB\-v\fP
|
||||
Enable the verbose mode (log to stdout/stderr by default)
|
||||
\fB\-V\fP, \fB\-\-version\fP
|
||||
Prints version information and exits.
|
||||
.TP
|
||||
\fB\-l\fP \fIlog_file\fP
|
||||
Write log to file instead of stdout/stderr
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
Enable verbose mode (log to stdout/stderr by default).
|
||||
.TP
|
||||
\fB\-L\fP
|
||||
Write log to syslog instead of stdout/stderr
|
||||
\fB\-l\fP \fIlogfile\fP, \fB\-\-logfile\fP \fIlogfile\fP
|
||||
Write log to file instead of stdout/stderr.
|
||||
.TP
|
||||
\fB\-i\fP
|
||||
Generate cryptographic identity for the node.
|
||||
\fB\-L\fP, \fB\-\-syslog\fP
|
||||
Write log to syslog instead of stdout/stderr (enables verbose mode).
|
||||
.TP
|
||||
\fB\-\-save\-identity\fP \fIfile\fP
|
||||
\fB\-i\fP, \fB\-\-identity\fP
|
||||
Generate a cryptographic identity (RSA key pair and self-signed certificate)
|
||||
for the node. Required to perform cryptographic operations (encrypt/sign values)
|
||||
if no private key file is provided.
|
||||
.TP
|
||||
\fB\-I\fP \fIfile\fP, \fB\-\-save\-identity\fP \fIfile\fP
|
||||
Save generated identity (certificate and private key) to given file prefix.
|
||||
Files are saved as \fIfile\fP and \fIfile\fP_ca.
|
||||
.TP
|
||||
\fB\-\-certificate\fP \fIfile\fP
|
||||
Load identity certificate from given file.
|
||||
\fB\-c\fP \fIfile\fP, \fB\-\-certificate\fP \fIfile\fP
|
||||
Load identity certificate from given file. If specified, the certificate is
|
||||
published on the DHT.
|
||||
.TP
|
||||
\fB\-\-privkey\fP \fIfile\fP
|
||||
Load identity private key from given file.
|
||||
\fB\-k\fP \fIfile\fP, \fB\-\-privkey\fP \fIfile\fP
|
||||
Load identity private key from given file. Required to perform cryptographic
|
||||
operations if no identity is generated.
|
||||
.TP
|
||||
\fB\-\-privkey\-password\fP \fIpassword\fP
|
||||
\fB\-m\fP \fIpassword\fP, \fB\-\-privkey\-password\fP \fIpassword\fP
|
||||
Password to use for private key encryption or decryption (optional).
|
||||
.TP
|
||||
\fB\-d\fP
|
||||
Run the program in daemon mode (will fork in the background).
|
||||
\fB\-d\fP, \fB\-\-daemonize\fP
|
||||
Run the program in daemon mode (will fork in the background). When verbose mode
|
||||
is enabled, logs to syslog by default.
|
||||
.TP
|
||||
\fB\-s\fP
|
||||
\fB\-s\fP, \fB\-\-service\fP
|
||||
Run the program in service mode (non\-forking daemon).
|
||||
.TP
|
||||
\fB\-D\fP
|
||||
\fB\-D\fP, \fB\-\-peer\-discovery\fP
|
||||
Enables multicast automatic local peer discovery.
|
||||
.TP
|
||||
\fB\-f\fP \fIfile\fP
|
||||
Specify a file path to persist/load the node state.
|
||||
\fB\-U\fP, \fB\-\-no\-rate\-limit\fP
|
||||
Disable rate limiting (allows unlimited requests and storage).
|
||||
.TP
|
||||
\fB\-n\fP \fInetwork_id\fP
|
||||
Specify the network id. This let you connect to distinct networks and prevents
|
||||
the merge of two different networks (available since OpenDHT v0.6.1).
|
||||
\fB\-P\fP, \fB\-\-public\-stable\fP
|
||||
Enable public stable mode.
|
||||
.TP
|
||||
\fB\-p\fP \fIlocal_port\fP
|
||||
Use UDP port \fIlocal_port\fP for the program to bind to.
|
||||
\fB\-f\fP \fIpath\fP, \fB\-\-persist\fP \fIpath\fP
|
||||
Specify a file path to persist/load the node state (routing table and values).
|
||||
.TP
|
||||
\fB\-b\fP \fIbootstrap_host\fP[:\fIport\fP]
|
||||
The program needs to be given a node to connect to the network. You use this
|
||||
option to provide the ip address of that node.
|
||||
\fB\-n\fP \fInetwork_id\fP, \fB\-\-net\fP \fInetwork_id\fP
|
||||
Specify the network id. This lets you connect to distinct networks and prevents
|
||||
the merge of two different networks. Defaults to 0 (the main public network).
|
||||
.TP
|
||||
\fB\-\-proxyserver\fP \fIlocal_port\fP
|
||||
Run a proxy server bound to this DHT node on HTTP port \fIlocal_port\fP
|
||||
\fB\-p\fP \fIlocal_port\fP, \fB\-\-port\fP \fIlocal_port\fP
|
||||
Use UDP port \fIlocal_port\fP for the program to bind to. If not set, will use
|
||||
any available port. The default OpenDHT port for public nodes is 4222.
|
||||
.TP
|
||||
\fB\-\-proxyclient\fP \fIserver\fP
|
||||
Run this DHT node in proxy client mode, and connect to \fIserver\fP
|
||||
\fB\-b\fP \fIbootstrap_host\fP[:\fIport\fP], \fB\-\-bootstrap\fP \fIbootstrap_host\fP[:\fIport\fP]
|
||||
Specify a bootstrap node address to connect to the network.
|
||||
.TP
|
||||
\fB\-S\fP \fIlocal_port\fP, \fB\-\-proxyserver\fP \fIlocal_port\fP
|
||||
Run a REST API proxy server bound to this DHT node on HTTP port \fIlocal_port\fP.
|
||||
.TP
|
||||
\fB\-e\fP \fIlocal_port\fP, \fB\-\-proxyserverssl\fP \fIlocal_port\fP
|
||||
Run a REST API proxy server with SSL bound to this DHT node on HTTPS port \fIlocal_port\fP.
|
||||
.TP
|
||||
\fB\-a\fP \fIaddress\fP, \fB\-\-proxy\-addr\fP \fIaddress\fP
|
||||
Proxy server bind address.
|
||||
.TP
|
||||
\fB\-w\fP \fIfile\fP, \fB\-\-proxy\-certificate\fP \fIfile\fP
|
||||
Load proxy SSL certificate from given file.
|
||||
.TP
|
||||
\fB\-K\fP \fIfile\fP, \fB\-\-proxy\-privkey\fP \fIfile\fP
|
||||
Load proxy SSL private key from given file.
|
||||
.TP
|
||||
\fB\-M\fP \fIpassword\fP, \fB\-\-proxy\-privkey\-password\fP \fIpassword\fP
|
||||
Password for the proxy private key encryption or decryption (optional).
|
||||
.TP
|
||||
\fB\-C\fP \fIserver\fP, \fB\-\-proxyclient\fP \fIserver\fP
|
||||
Run this DHT node in proxy client mode, and connect to \fIserver\fP.
|
||||
.TP
|
||||
\fB\-y\fP \fIendpoint\fP, \fB\-\-pushserver\fP \fIendpoint\fP
|
||||
Push notification server endpoint.
|
||||
.TP
|
||||
\fB\-z\fP \fIkey\fP, \fB\-\-devicekey\fP \fIkey\fP
|
||||
Device key for push notifications.
|
||||
.TP
|
||||
\fB\-u\fP \fIbundleid\fP, \fB\-\-bundleid\fP \fIbundleid\fP
|
||||
Bundle ID for push notifications.
|
||||
.SH EXAMPLES
|
||||
Run a node using bootstrap.jami.net as a bootstrap:
|
||||
.PP
|
||||
.EX
|
||||
dhtnode -b bootstrap.jami.net:4222
|
||||
.EE
|
||||
.PP
|
||||
Run a node as a non-forking daemon on port 4222:
|
||||
.PP
|
||||
.EX
|
||||
dhtnode -b bootstrap.jami.net -p 4222 -s
|
||||
.EE
|
||||
.PP
|
||||
Run a proxy server on port 8000:
|
||||
.PP
|
||||
.EX
|
||||
dhtnode -b bootstrap.jami.net:4222 --proxyserver 8000
|
||||
.EE
|
||||
.PP
|
||||
Use a proxy client to connect to a proxy server:
|
||||
.PP
|
||||
.EX
|
||||
dhtnode --proxyclient dhtproxy.jami.net:80
|
||||
.EE
|
||||
.SH AUTHORS
|
||||
.TP
|
||||
Program written by
|
||||
|
||||
@@ -187,8 +187,6 @@ using ShutdownCallback = std::function<void()>;
|
||||
using IdentityAnnouncedCb = std::function<void(bool)>;
|
||||
using PublicAddressChangedCb = std::function<void(std::vector<SockAddr>)>;
|
||||
|
||||
using CertificateStoreQueryLegacy
|
||||
= std::function<std::vector<std::shared_ptr<crypto::Certificate>>(const InfoHash& pk_id)>;
|
||||
using CertificateStoreQuery = std::function<std::vector<std::shared_ptr<crypto::Certificate>>(const PkId& pk_id)>;
|
||||
|
||||
using DoneCallback = std::function<void(bool success, const std::vector<std::shared_ptr<Node>>& nodes)>;
|
||||
|
||||
@@ -214,7 +214,7 @@ private:
|
||||
PrivateKey& operator=(const PrivateKey&) = delete;
|
||||
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
|
||||
|
||||
mutable std::mutex publicKeyMutex_ {};
|
||||
mutable std::mutex publicKeyMutex_;
|
||||
mutable std::shared_ptr<PublicKey> publicKey_ {};
|
||||
};
|
||||
|
||||
@@ -685,7 +685,7 @@ private:
|
||||
|
||||
std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
|
||||
|
||||
mutable std::mutex publicKeyMutex_ {};
|
||||
mutable std::mutex publicKeyMutex_;
|
||||
mutable std::shared_ptr<PublicKey> publicKey_ {};
|
||||
};
|
||||
|
||||
|
||||
@@ -411,6 +411,7 @@ private:
|
||||
std::vector<std::pair<std::string, std::string>> bootstrap_nodes {};
|
||||
std::chrono::steady_clock::duration bootstrap_period {BOOTSTRAP_PERIOD};
|
||||
Sp<Scheduler::Job> bootstrapJob {};
|
||||
bool bootstrap_pending {false};
|
||||
|
||||
std::map<InfoHash, Storage> store;
|
||||
std::map<SockAddr, StorageBucket, SockAddr::ipCmp> store_quota;
|
||||
@@ -627,7 +628,7 @@ private:
|
||||
/* when we receive a listen request */
|
||||
net::RequestAnswer onListen(
|
||||
Sp<Node> node, const InfoHash& hash, const Blob& token, size_t socket_id, const Query& query, int version = 0);
|
||||
void onListenDone(const Sp<Node>& status, net::RequestAnswer& a, Sp<Search>& sr);
|
||||
void onListenDone(const Sp<Node>& node, net::RequestAnswer& a, Sp<Search>& sr);
|
||||
/* when we receive an announce request */
|
||||
net::RequestAnswer onAnnounce(Sp<Node> node,
|
||||
const InfoHash& hash,
|
||||
|
||||
@@ -425,7 +425,7 @@ private:
|
||||
p.pack(clientId);
|
||||
}
|
||||
if (sessionCtx) {
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
p.pack("sid");
|
||||
p.pack(sessionCtx->sessionId);
|
||||
}
|
||||
@@ -478,7 +478,7 @@ private:
|
||||
p.pack("exp");
|
||||
p.pack(to_time_t(expiration));
|
||||
if (sessionCtx) {
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
p.pack("sid");
|
||||
p.pack(sessionCtx->sessionId);
|
||||
}
|
||||
|
||||
+13
-27
@@ -61,8 +61,7 @@ public:
|
||||
std::unique_ptr<net::DatagramSocket> sock;
|
||||
std::shared_ptr<PeerDiscovery> peerDiscovery {};
|
||||
StatusCallback statusChangedCallback {};
|
||||
CertificateStoreQueryLegacy certificateStore {};
|
||||
CertificateStoreQuery certificateStorePkId {};
|
||||
CertificateStoreQuery certificateStore {};
|
||||
IdentityAnnouncedCb identityAnnouncedCb {};
|
||||
PublicAddressChangedCb publicAddressChangedCb {};
|
||||
std::unique_ptr<std::mt19937_64> rng {};
|
||||
@@ -286,21 +285,6 @@ public:
|
||||
}
|
||||
void putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb = {}, bool permanent = false);
|
||||
|
||||
void putEncrypted(
|
||||
InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb = {}, bool permanent = false);
|
||||
void putEncrypted(
|
||||
InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false)
|
||||
{
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb = {}, bool permanent = false);
|
||||
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallbackSimple cb, bool permanent = false)
|
||||
{
|
||||
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
|
||||
}
|
||||
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb = {}, bool permanent = false);
|
||||
|
||||
void putEncrypted(InfoHash hash,
|
||||
const std::shared_ptr<crypto::PublicKey>& to,
|
||||
std::shared_ptr<Value> value,
|
||||
@@ -315,13 +299,11 @@ 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,
|
||||
@@ -338,6 +320,14 @@ public:
|
||||
{
|
||||
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
|
||||
}
|
||||
void putEncrypted(InfoHash hash, const PkId& to, Value&& value, DoneCallback cb = {}, bool permanent = false)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
|
||||
}
|
||||
void putEncrypted(InfoHash hash, const PkId& to, Value&& value, DoneCallbackSimple cb, bool permanent = false)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), bindDoneCb(cb), permanent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert known nodes to the routing table, without necessarly ping them.
|
||||
@@ -450,13 +440,9 @@ public:
|
||||
void getPublicAddress(std::function<void(std::vector<SockAddr>&&)>, sa_family_t af = AF_UNSPEC);
|
||||
|
||||
// securedht methods
|
||||
|
||||
[[deprecated("Use PkId version")]] void findCertificate(
|
||||
InfoHash hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
|
||||
void findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
|
||||
|
||||
void registerCertificate(const std::shared_ptr<crypto::Certificate>& cert);
|
||||
void setLocalCertificateStore(CertificateStoreQueryLegacy&& query_method);
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
|
||||
|
||||
/**
|
||||
@@ -499,7 +485,7 @@ public:
|
||||
*/
|
||||
time_point loop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return loop_();
|
||||
}
|
||||
|
||||
@@ -579,16 +565,16 @@ private:
|
||||
*/
|
||||
void resetDht();
|
||||
|
||||
mutable std::mutex dht_mtx {};
|
||||
mutable std::mutex dht_mtx;
|
||||
std::thread dht_thread {};
|
||||
std::condition_variable cv {};
|
||||
std::mutex sock_mtx {};
|
||||
std::mutex sock_mtx;
|
||||
net::PacketList rcv {};
|
||||
decltype(rcv) rcv_free {};
|
||||
|
||||
std::queue<std::function<void(SecureDht&)>> pending_ops_prio {};
|
||||
std::queue<std::function<void(SecureDht&)>> pending_ops {};
|
||||
std::mutex storage_mtx {};
|
||||
std::mutex storage_mtx;
|
||||
|
||||
std::atomic<State> running {State::Idle};
|
||||
std::atomic_size_t ongoing_ops {0};
|
||||
|
||||
@@ -269,7 +269,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
T data_;
|
||||
alignas(alignof(uint32_t)) T data_;
|
||||
static constexpr T fromBytes(const uint8_t*, size_t);
|
||||
static constexpr T fromString(std::string_view);
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@ struct OPENDHT_PUBLIC Logger
|
||||
|
||||
std::shared_ptr<Logger> createChild(std::string tag)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock {children_mutex_};
|
||||
std::lock_guard lock {children_mutex_};
|
||||
auto child = std::make_shared<Logger>(*this, std::move(tag));
|
||||
children_.push_back(child);
|
||||
return child;
|
||||
@@ -139,7 +139,7 @@ struct OPENDHT_PUBLIC Logger
|
||||
|
||||
void setFilter(std::string_view filter)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock {children_mutex_};
|
||||
std::lock_guard lock {children_mutex_};
|
||||
enable_ = filter.empty() or tag_.find(filter) != std::string_view::npos;
|
||||
for (auto it = children_.begin(); it != children_.end();) {
|
||||
if (auto c = it->lock()) {
|
||||
@@ -196,7 +196,7 @@ private:
|
||||
const LogMethod logger_ = {};
|
||||
const std::string tag_ {};
|
||||
const std::string prefix_ {};
|
||||
std::mutex children_mutex_ {};
|
||||
std::mutex children_mutex_;
|
||||
std::vector<std::weak_ptr<Logger>> children_ {};
|
||||
bool enable_ {true};
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
inline void setOnReceive(OnReceive&& cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
rx_callback = std::move(cb);
|
||||
}
|
||||
|
||||
@@ -67,12 +67,12 @@ public:
|
||||
|
||||
SockAddr getBound(sa_family_t family = AF_UNSPEC) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
return getBoundRef(family);
|
||||
}
|
||||
in_port_t getPort(sa_family_t family = AF_UNSPEC) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
return getBoundRef(family).getPort();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ protected:
|
||||
|
||||
inline void onReceived(PacketList&& packets)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
if (rx_callback) {
|
||||
auto r = rx_callback(std::move(packets));
|
||||
if (not r.empty() and toRecycle_.size() < RX_QUEUE_MAX_SIZE)
|
||||
@@ -134,12 +134,12 @@ public:
|
||||
|
||||
bool hasIPv4() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
return s4 != -1;
|
||||
}
|
||||
bool hasIPv6() const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
return s6 != -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -113,14 +113,6 @@ public:
|
||||
* and put it in the DHT.
|
||||
* 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,
|
||||
@@ -145,19 +137,11 @@ public:
|
||||
|
||||
Value decrypt(const Value& v);
|
||||
|
||||
[[deprecated("Use PkId version")]] void findCertificate(
|
||||
const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
|
||||
[[deprecated("Use PkId version")]] void findPublicKey(const InfoHash& node,
|
||||
const std::function<void(const Sp<crypto::PublicKey>)>& cb);
|
||||
|
||||
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);
|
||||
|
||||
[[deprecated("Use PkId version")]] Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
|
||||
[[deprecated("Use PkId version")]] Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
|
||||
|
||||
Sp<crypto::Certificate> getCertificate(const PkId& node) const;
|
||||
Sp<crypto::PublicKey> getPublicKey(const PkId& node) const;
|
||||
|
||||
@@ -166,10 +150,6 @@ public:
|
||||
* The search key used is the public key ID, so there may be multiple certificates retured, signed with
|
||||
* the same private key.
|
||||
*/
|
||||
void setLocalCertificateStore(CertificateStoreQueryLegacy&& query_method)
|
||||
{
|
||||
localQueryMethodLegacy_ = std::move(query_method);
|
||||
}
|
||||
void setLocalCertificateStore(CertificateStoreQuery&& query_method) { localQueryMethod_ = std::move(query_method); }
|
||||
void setOnPublicAddressChanged(PublicAddressChangedCb cb) override { dht_->setOnPublicAddressChanged(cb); }
|
||||
|
||||
@@ -347,13 +327,10 @@ private:
|
||||
|
||||
// method to query the local certificate store
|
||||
CertificateStoreQuery localQueryMethod_ {};
|
||||
CertificateStoreQueryLegacy localQueryMethodLegacy_ {};
|
||||
|
||||
// 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::map<PkId, Sp<crypto::Certificate>> nodesCertificates_ {};
|
||||
std::map<PkId, Sp<crypto::PublicKey>> nodesPubKeys_ {};
|
||||
|
||||
std::atomic_bool forward_all_ {false};
|
||||
bool enableCache_ {false};
|
||||
|
||||
@@ -53,12 +53,14 @@ public:
|
||||
void detach();
|
||||
|
||||
private:
|
||||
std::mutex lock_ {};
|
||||
std::mutex lock_;
|
||||
std::condition_variable cv_ {};
|
||||
std::condition_variable stopCv_ {};
|
||||
std::queue<std::function<void()>> tasks_ {};
|
||||
std::vector<std::unique_ptr<std::thread>> threads_;
|
||||
unsigned readyThreads_ {0};
|
||||
bool running_ {true};
|
||||
bool stopping_ {false};
|
||||
|
||||
unsigned minThreads_;
|
||||
const unsigned maxThreads_;
|
||||
@@ -81,7 +83,7 @@ public:
|
||||
private:
|
||||
std::reference_wrapper<ThreadPool> threadPool_;
|
||||
const unsigned maxConcurrent_ {1};
|
||||
std::mutex lock_ {};
|
||||
std::mutex lock_;
|
||||
unsigned current_ {0};
|
||||
std::queue<std::function<void()>> tasks_ {};
|
||||
|
||||
@@ -104,7 +106,7 @@ public:
|
||||
|
||||
void run(std::function<void()>&& task)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state_->mtx);
|
||||
std::lock_guard lock(state_->mtx);
|
||||
if (state_->shutdown_)
|
||||
return;
|
||||
state_->pendingTasks++;
|
||||
@@ -114,7 +116,7 @@ public:
|
||||
private:
|
||||
struct SharedState
|
||||
{
|
||||
std::mutex mtx {};
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv {};
|
||||
unsigned pendingTasks {0};
|
||||
unsigned ongoingTasks {0};
|
||||
@@ -125,7 +127,7 @@ private:
|
||||
|
||||
void destroy(bool wait = true)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
std::unique_lock lock(mtx);
|
||||
if (destroyed)
|
||||
return;
|
||||
if (wait) {
|
||||
@@ -141,7 +143,7 @@ private:
|
||||
void run(const std::function<void()>& task)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::lock_guard lock(mtx);
|
||||
pendingTasks--;
|
||||
ongoingTasks++;
|
||||
}
|
||||
@@ -149,7 +151,7 @@ private:
|
||||
return;
|
||||
task();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::lock_guard lock(mtx);
|
||||
ongoingTasks--;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
+14
-1
@@ -31,6 +31,7 @@ using namespace std::literals;
|
||||
static constexpr auto VALUE_KEY_ID("id");
|
||||
static const std::string VALUE_KEY_DAT("dat");
|
||||
static const std::string VALUE_KEY_PRIO("p");
|
||||
static const std::string VALUE_KEY_PUSHTYPE("pt");
|
||||
static const std::string VALUE_KEY_SIGNATURE("sig");
|
||||
|
||||
static const std::string VALUE_KEY_SEQ("seq");
|
||||
@@ -451,6 +452,7 @@ struct OPENDHT_PUBLIC Value
|
||||
, signature(std::move(o.signature))
|
||||
, cypher(std::move(o.cypher))
|
||||
, priority(o.priority)
|
||||
, pushType(std::move(o.pushType))
|
||||
{}
|
||||
|
||||
template<typename Type>
|
||||
@@ -574,7 +576,7 @@ struct OPENDHT_PUBLIC Value
|
||||
template<typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_map(2 + (priority ? 1 : 0));
|
||||
pk.pack_map(2 + (priority ? 1 : 0) + (!pushType.empty() ? 1 : 0));
|
||||
pk.pack(VALUE_KEY_ID);
|
||||
pk.pack(id);
|
||||
pk.pack(VALUE_KEY_DAT);
|
||||
@@ -583,6 +585,10 @@ struct OPENDHT_PUBLIC Value
|
||||
pk.pack(VALUE_KEY_PRIO);
|
||||
pk.pack(priority);
|
||||
}
|
||||
if (!pushType.empty()) {
|
||||
pk.pack(VALUE_KEY_PUSHTYPE);
|
||||
pk.pack(pushType);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Packer>
|
||||
@@ -672,6 +678,13 @@ struct OPENDHT_PUBLIC Value
|
||||
*/
|
||||
unsigned priority {0};
|
||||
|
||||
/**
|
||||
* Push notification type — set by the sender so that the proxy server
|
||||
* can include it in the FCM/APNs payload without decrypting the value.
|
||||
* Example: "audioCall", "videoCall"
|
||||
*/
|
||||
std::string pushType {};
|
||||
|
||||
inline bool isSignatureChecked() const { return signatureChecked; }
|
||||
inline bool isDecrypted() const { return decrypted; }
|
||||
bool checkSignature();
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ project(
|
||||
'cython',
|
||||
license: 'MIT',
|
||||
license_files: 'LICENSE',
|
||||
version: '3.7.3',
|
||||
version: '4.0.0',
|
||||
meson_version: '>=1.1.0',
|
||||
default_options: ['cpp_std=c++20', 'warning_level=3'],
|
||||
)
|
||||
@@ -281,7 +281,7 @@ if get_option('tests').enabled()
|
||||
'tests/tests_runner.cpp',
|
||||
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack, gnutls],
|
||||
)
|
||||
test('Crypto', test_crypto)
|
||||
test('Crypto', test_crypto, timeout: 60)
|
||||
|
||||
test_dhtrunner = executable(
|
||||
'test_dhtrunner',
|
||||
@@ -289,7 +289,7 @@ if get_option('tests').enabled()
|
||||
'tests/tests_runner.cpp',
|
||||
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
|
||||
)
|
||||
test('DhtRunner', test_dhtrunner)
|
||||
test('DhtRunner', test_dhtrunner, timeout: 60)
|
||||
|
||||
test_threadpool = executable(
|
||||
'test_threadpool',
|
||||
|
||||
+11
-1
@@ -28,8 +28,18 @@ install(CODE [[
|
||||
if(NOT _pip_check EQUAL 0)
|
||||
message(WARNING "Skipping Python package install: pip not available for ${Python3_EXECUTABLE}.")
|
||||
else()
|
||||
set(_pip_install_args
|
||||
install
|
||||
--no-deps
|
||||
--no-build-isolation
|
||||
--break-system-packages
|
||||
--prefix ${CMAKE_INSTALL_PREFIX})
|
||||
if(DEFINED ENV{DESTDIR} AND NOT "$ENV{DESTDIR}" STREQUAL "")
|
||||
list(APPEND _pip_install_args --root "$ENV{DESTDIR}")
|
||||
endif()
|
||||
list(APPEND _pip_install_args .)
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip install --no-deps --break-system-packages .
|
||||
COMMAND ${Python3_EXECUTABLE} -m pip ${_pip_install_args}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/python
|
||||
OUTPUT_VARIABLE _pip_output
|
||||
ERROR_VARIABLE _pip_error
|
||||
|
||||
+1
-6
@@ -820,13 +820,8 @@ cdef class DhtRunner(_WithID):
|
||||
key._infohash, (<PkId>to)._pkid, val._value,
|
||||
cpp.bindDoneCb(done_callback, <void*>cb_obj), permanent
|
||||
)
|
||||
elif isinstance(to, InfoHash):
|
||||
self.thisptr.get().putEncrypted(
|
||||
key._infohash, (<InfoHash>to)._infohash, val._value,
|
||||
cpp.bindDoneCb(done_callback, <void*>cb_obj), permanent
|
||||
)
|
||||
else:
|
||||
raise TypeError("'to' must be PublicKey, PkId, or InfoHash")
|
||||
raise TypeError("'to' must be PublicKey or PkId")
|
||||
except:
|
||||
ref.Py_DECREF(cb_obj)
|
||||
raise
|
||||
|
||||
@@ -282,7 +282,6 @@ cdef extern from "opendht/dhtrunner.h" namespace "dht":
|
||||
void get(InfoHash key, GetCallback get_cb, DoneCallback done_cb, nullptr_t f, Where w)
|
||||
void put(InfoHash key, shared_ptr[Value] val, DoneCallback done_cb, time_point created, bool permanent)
|
||||
void putSigned(InfoHash key, shared_ptr[Value] val, DoneCallback done_cb, bool permanent)
|
||||
void putEncrypted(InfoHash key, InfoHash to, shared_ptr[Value] val, DoneCallback done_cb, bool permanent)
|
||||
void putEncrypted(InfoHash key, PkId to, shared_ptr[Value] val, DoneCallback done_cb, bool permanent)
|
||||
void putEncrypted(InfoHash key, shared_ptr[PublicKey] to, shared_ptr[Value] val, DoneCallback done_cb, bool permanent)
|
||||
void cancelPut(InfoHash key, shared_ptr[Value] val)
|
||||
|
||||
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.cibuildwheel]
|
||||
build = [
|
||||
'cp3{9,10,11,12,13}-manylinux_x86_64',
|
||||
'cp3{10,11,12,13}-manylinux_aarch64',
|
||||
'cp3{11,12,13}-macosx_x86_64',
|
||||
'cp3{11,12,13}-macosx_arm64',
|
||||
'cp3{11,12,13}-win_amd64',
|
||||
'cp3{9,10,11,12,13,14}-manylinux_x86_64',
|
||||
'cp3{10,11,12,13,14}-manylinux_aarch64',
|
||||
'cp3{11,12,13,14}-macosx_x86_64',
|
||||
'cp3{11,12,13,14}-macosx_arm64',
|
||||
'cp3{11,12,13,14}-win_amd64',
|
||||
]
|
||||
|
||||
[tool.cibuildwheel.linux]
|
||||
|
||||
@@ -226,7 +226,7 @@ impl DhtRunner {
|
||||
pub fn put_encrypted<'a>(
|
||||
&mut self,
|
||||
h: &InfoHash,
|
||||
to: &InfoHash,
|
||||
to: &PkId,
|
||||
v: Box<Value>,
|
||||
done_cb: &'a mut (dyn FnMut(bool)),
|
||||
permanent: bool,
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ extern {
|
||||
cb_user_data: *mut c_void,
|
||||
permanent: bool);
|
||||
pub fn dht_runner_put_encrypted(dht: *mut DhtRunner, h: *const InfoHash,
|
||||
to: *const InfoHash, v: *const Value,
|
||||
to: *const PkId, v: *const Value,
|
||||
done_cb: extern fn(bool, *mut c_void),
|
||||
cb_user_data: *mut c_void,
|
||||
permanent: bool);
|
||||
|
||||
+52
-11
@@ -11,6 +11,7 @@ extern "C" {
|
||||
#include <nettle/gcm.h>
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/hmac.h>
|
||||
#include <nettle/version.h>
|
||||
#include <gnutls/crypto.h>
|
||||
|
||||
#include <argon2.h>
|
||||
@@ -98,6 +99,46 @@ private:
|
||||
#define GCM_DIGEST_SIZE GCM_BLOCK_SIZE
|
||||
#endif
|
||||
|
||||
static void
|
||||
gcmAes128Digest(gcm_aes128_ctx* ctx, uint8_t* digest)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR >= 4
|
||||
gcm_aes128_digest(ctx, digest);
|
||||
#else
|
||||
gcm_aes128_digest(ctx, GCM_DIGEST_SIZE, digest);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gcmAes192Digest(gcm_aes192_ctx* ctx, uint8_t* digest)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR >= 4
|
||||
gcm_aes192_digest(ctx, digest);
|
||||
#else
|
||||
gcm_aes192_digest(ctx, GCM_DIGEST_SIZE, digest);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gcmAes256Digest(gcm_aes256_ctx* ctx, uint8_t* digest)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR >= 4
|
||||
gcm_aes256_digest(ctx, digest);
|
||||
#else
|
||||
gcm_aes256_digest(ctx, GCM_DIGEST_SIZE, digest);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
hmacSha256Digest(hmac_sha256_ctx* ctx, uint8_t* digest)
|
||||
{
|
||||
#if NETTLE_VERSION_MAJOR >= 4
|
||||
hmac_sha256_digest(ctx, digest);
|
||||
#else
|
||||
hmac_sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
|
||||
#endif
|
||||
}
|
||||
|
||||
Blob
|
||||
aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
{
|
||||
@@ -115,19 +156,19 @@ aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
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);
|
||||
gcmAes128Digest(&aes, 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);
|
||||
gcmAes192Digest(&aes, 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);
|
||||
gcmAes256Digest(&aes, ret.data() + GCM_IV_SIZE + data_length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -160,19 +201,19 @@ aesDecrypt(const uint8_t* data, size_t data_length, const Blob& key)
|
||||
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());
|
||||
gcmAes128Digest(&aes, 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());
|
||||
gcmAes192Digest(&aes, 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());
|
||||
gcmAes256Digest(&aes, digest.data());
|
||||
}
|
||||
|
||||
if (not std::equal(digest.begin(), digest.end(), data + data_length - GCM_DIGEST_SIZE)) {
|
||||
@@ -446,7 +487,7 @@ PrivateKey::getPublicKey() const
|
||||
const std::shared_ptr<PublicKey>&
|
||||
PrivateKey::getSharedPublicKey() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(publicKeyMutex_);
|
||||
std::lock_guard lock(publicKeyMutex_);
|
||||
if (not publicKey_) {
|
||||
auto pk = std::make_shared<PublicKey>();
|
||||
if (auto err = gnutls_pubkey_import_privkey(pk->pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
|
||||
@@ -959,7 +1000,7 @@ Certificate::getPublicKey() const
|
||||
const std::shared_ptr<PublicKey>&
|
||||
Certificate::getSharedPublicKey() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(publicKeyMutex_);
|
||||
std::lock_guard lock(publicKeyMutex_);
|
||||
if (not publicKey_) {
|
||||
auto pk = std::make_shared<PublicKey>();
|
||||
if (auto err = gnutls_pubkey_import_x509(pk->pk, cert, 0))
|
||||
@@ -2045,7 +2086,7 @@ hkdf_extract(const Blob& salt, const Blob& ikm)
|
||||
hmac_sha256_set_key(&ctx, salt.size(), salt.data());
|
||||
hmac_sha256_update(&ctx, ikm.size(), ikm.data());
|
||||
Blob prk(SHA256_DIGEST_SIZE);
|
||||
hmac_sha256_digest(&ctx, SHA256_DIGEST_SIZE, prk.data());
|
||||
hmacSha256Digest(&ctx, prk.data());
|
||||
return prk;
|
||||
}
|
||||
|
||||
@@ -2063,7 +2104,7 @@ hkdf_expand(const Blob& prk, const uint8_t* info, size_t info_len, size_t len)
|
||||
hmac_sha256_update(&ctx, info_len, info);
|
||||
hmac_sha256_update(&ctx, 1, &i);
|
||||
T.resize(SHA256_DIGEST_SIZE);
|
||||
hmac_sha256_digest(&ctx, SHA256_DIGEST_SIZE, T.data());
|
||||
hmacSha256Digest(&ctx, T.data());
|
||||
okm.insert(okm.end(), T.begin(), T.end());
|
||||
i++;
|
||||
}
|
||||
@@ -2223,7 +2264,7 @@ webPushEncrypt(const Blob& p256dh,
|
||||
|
||||
Blob ciphertext(plaintext.size() + GCM_DIGEST_SIZE);
|
||||
gcm_aes128_encrypt(&aes, plaintext.size(), ciphertext.data(), plaintext.data());
|
||||
gcm_aes128_digest(&aes, GCM_DIGEST_SIZE, ciphertext.data() + plaintext.size());
|
||||
gcmAes128Digest(&aes, ciphertext.data() + plaintext.size());
|
||||
|
||||
// 6. Construct Output
|
||||
Blob output;
|
||||
|
||||
+23
-3
@@ -35,7 +35,7 @@ Dht::updateStatus(sa_family_t af)
|
||||
auto& d = dht(af);
|
||||
auto old = d.status;
|
||||
d.status = d.getStatus(scheduler.time());
|
||||
if (d.status == NodeStatus::Disconnected && bootstrapJob && !bootstrap_nodes.empty())
|
||||
if (d.status == NodeStatus::Disconnected && bootstrap_pending && bootstrapJob && !bootstrap_nodes.empty())
|
||||
d.status = NodeStatus::Connecting;
|
||||
if (d.status != old) {
|
||||
auto& other = dht(af == AF_INET ? AF_INET6 : AF_INET);
|
||||
@@ -661,8 +661,9 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
|
||||
/* on new values */
|
||||
if (auto sr = ws.lock()) {
|
||||
scheduler.edit(sr->nextSearchStep, scheduler.time());
|
||||
sr->insertNode(node, scheduler.time(), answer.ntoken);
|
||||
if (auto sn = sr->getNode(node)) {
|
||||
if (not answer.ntoken.empty())
|
||||
sn->refreshToken(answer.ntoken);
|
||||
sn->onValues(query, std::move(answer), types, scheduler);
|
||||
}
|
||||
}
|
||||
@@ -1431,6 +1432,8 @@ Dht::storageStore(const InfoHash& id,
|
||||
created = std::min(created, now);
|
||||
if (expiration == time_point::min())
|
||||
expiration = permanent ? time_point::max() : created + getType(value->type).expiration;
|
||||
else if (not permanent)
|
||||
expiration = std::min(expiration, created + getType(value->type).expiration);
|
||||
if (expiration < now)
|
||||
return false;
|
||||
|
||||
@@ -2271,6 +2274,7 @@ Dht::bootstrap()
|
||||
return;
|
||||
if (logger_)
|
||||
logger_->debug("[{}] Bootstraping", myid.to_view());
|
||||
bootstrap_pending = false;
|
||||
for (const auto& boootstrap : bootstrap_nodes) {
|
||||
try {
|
||||
auto ips = network_engine.getSocket()->resolve(boootstrap.first, boootstrap.second);
|
||||
@@ -2297,6 +2301,7 @@ void
|
||||
Dht::startBootstrap()
|
||||
{
|
||||
stopBootstrap();
|
||||
bootstrap_pending = !bootstrap_nodes.empty();
|
||||
bootstrapJob = scheduler.add(scheduler.time(), std::bind(&Dht::bootstrap, this));
|
||||
}
|
||||
|
||||
@@ -2304,6 +2309,7 @@ void
|
||||
Dht::stopBootstrap()
|
||||
{
|
||||
scheduler.cancel(bootstrapJob);
|
||||
bootstrap_pending = false;
|
||||
bootstrap_period = BOOTSTRAP_PERIOD;
|
||||
}
|
||||
|
||||
@@ -2532,6 +2538,17 @@ Dht::onError(Sp<net::Request> req, net::DhtProtocolException e)
|
||||
continue;
|
||||
n->token.clear();
|
||||
n->last_get_reply = time_point::min();
|
||||
for (auto& listen : n->listenStatus) {
|
||||
if (listen.second.req and listen.second.req->pending())
|
||||
n->node->cancelRequest(listen.second.req);
|
||||
listen.second.req = {};
|
||||
n->node->closeSocket(listen.second.socketId);
|
||||
if (listen.second.refresh) {
|
||||
listen.second.refresh->cancel();
|
||||
listen.second.refresh = {};
|
||||
}
|
||||
listen.second.cache.onSynced(false);
|
||||
}
|
||||
searchSendGetValues(sr);
|
||||
scheduler.edit(sr->nextSearchStep, scheduler.time());
|
||||
break;
|
||||
@@ -2694,7 +2711,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
|
||||
}
|
||||
|
||||
void
|
||||
Dht::onListenDone(const Sp<Node>& /* node */, net::RequestAnswer& /* answer */, Sp<Search>& sr)
|
||||
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",
|
||||
@@ -2702,6 +2719,9 @@ Dht::onListenDone(const Sp<Node>& /* node */, net::RequestAnswer& /* answer */,
|
||||
|
||||
if (not sr->done) {
|
||||
const auto& now = scheduler.time();
|
||||
if (not answer.ntoken.empty())
|
||||
if (auto sn = sr->getNode(node))
|
||||
sn->refreshToken(answer.ntoken);
|
||||
searchSendGetValues(sr);
|
||||
scheduler.edit(sr->nextSearchStep, now);
|
||||
}
|
||||
|
||||
+57
-54
@@ -195,7 +195,7 @@ DhtProxyClient::stop()
|
||||
if (not isDestroying_.exchange(true)) {
|
||||
std::shared_ptr<http::Resolver> resolver;
|
||||
{
|
||||
std::lock_guard<std::mutex> l(resolverLock_);
|
||||
std::lock_guard l(resolverLock_);
|
||||
resolver = std::move(resolver_);
|
||||
}
|
||||
if (resolver)
|
||||
@@ -204,7 +204,7 @@ DhtProxyClient::stop()
|
||||
if (infoState_)
|
||||
infoState_->cancel = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(requestLock_);
|
||||
std::lock_guard lock(requestLock_);
|
||||
for (auto& request : requests_)
|
||||
request.second->cancel();
|
||||
}
|
||||
@@ -219,7 +219,7 @@ DhtProxyClient::stop()
|
||||
std::vector<Sp<Value>>
|
||||
DhtProxyClient::getLocal(const InfoHash& k, const Value::Filter& filter) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto s = searches_.find(k);
|
||||
if (s == searches_.end())
|
||||
return {};
|
||||
@@ -229,7 +229,7 @@ DhtProxyClient::getLocal(const InfoHash& k, const Value::Filter& filter) const
|
||||
Sp<Value>
|
||||
DhtProxyClient::getLocalById(const InfoHash& k, Value::Id id) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto s = searches_.find(k);
|
||||
if (s == searches_.end())
|
||||
return {};
|
||||
@@ -239,7 +239,7 @@ DhtProxyClient::getLocalById(const InfoHash& k, Value::Id id) const
|
||||
void
|
||||
DhtProxyClient::cancelAllListeners()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [listeners] [{} searches] cancel all", searches_.size());
|
||||
for (auto& s : searches_) {
|
||||
@@ -266,7 +266,7 @@ DhtProxyClient::shutdown(ShutdownCallback cb, bool)
|
||||
NodeStatus
|
||||
DhtProxyClient::getStatus(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return statusIpv4_;
|
||||
@@ -280,7 +280,7 @@ DhtProxyClient::getStatus(sa_family_t af) const
|
||||
bool
|
||||
DhtProxyClient::isRunning(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return statusIpv4_ != NodeStatus::Disconnected;
|
||||
@@ -297,7 +297,7 @@ DhtProxyClient::periodic(const uint8_t*, size_t, SockAddr, const time_point& /*n
|
||||
// Exec all currently stored callbacks
|
||||
decltype(callbacks_) callbacks;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks = std::move(callbacks_);
|
||||
}
|
||||
for (auto& callback : callbacks)
|
||||
@@ -357,7 +357,7 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
|
||||
}
|
||||
if (not values.empty() and cb) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([opstate, cb, values = std::move(values)]() {
|
||||
if (not opstate->stop.load() and not cb(values)) {
|
||||
opstate->stop.store(true);
|
||||
@@ -382,7 +382,7 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
|
||||
}
|
||||
if (donecb) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([donecb, opstate]() {
|
||||
donecb(opstate->ok, {});
|
||||
opstate->stop.store(true);
|
||||
@@ -391,12 +391,12 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
|
||||
loopSignal_();
|
||||
}
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
@@ -419,7 +419,7 @@ DhtProxyClient::put(const InfoHash& key, Sp<Value> val, DoneCallback cb, time_po
|
||||
|
||||
std::shared_ptr<std::atomic_bool> ok;
|
||||
if (permanent) {
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
ok = std::make_shared<std::atomic_bool>(true);
|
||||
auto& search = searches_[key];
|
||||
if (val->id) {
|
||||
@@ -443,7 +443,7 @@ DhtProxyClient::put(const InfoHash& key, Sp<Value> val, DoneCallback cb, time_po
|
||||
if (ok)
|
||||
*ok = result;
|
||||
if (cb) {
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([cb, result]() { cb(result, {}); });
|
||||
}
|
||||
loopSignal_();
|
||||
@@ -464,7 +464,7 @@ DhtProxyClient::handleRefreshPut(const asio::error_code& ec, InfoHash key, Value
|
||||
}
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [put] [refresh {}]", key.to_view());
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto search = searches_.find(key);
|
||||
if (search != searches_.end()) {
|
||||
auto p = search->second.puts.find(id);
|
||||
@@ -480,7 +480,7 @@ DhtProxyClient::handleRefreshPut(const asio::error_code& ec, InfoHash key, Value
|
||||
std::shared_ptr<http::Request>
|
||||
DhtProxyClient::buildRequest(const std::string& target)
|
||||
{
|
||||
std::unique_lock<std::mutex> l(resolverLock_);
|
||||
std::unique_lock l(resolverLock_);
|
||||
auto resolver = resolver_;
|
||||
l.unlock();
|
||||
if (not resolver)
|
||||
@@ -535,7 +535,7 @@ DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb,
|
||||
auto id = dht::Value(parsedValue).id;
|
||||
val->id = id;
|
||||
if (permanent) {
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto& search = searches_[key];
|
||||
auto it = search.pendingPuts.find(val);
|
||||
if (it != search.pendingPuts.end()) {
|
||||
@@ -565,12 +565,12 @@ DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb,
|
||||
if (cb)
|
||||
cb(ok);
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
@@ -640,7 +640,7 @@ DhtProxyClient::getProxyInfos()
|
||||
logger_->debug("[proxy:client] [info] requesting proxy server node information");
|
||||
auto infoState = std::make_shared<InfoState>();
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
if (infoState_)
|
||||
infoState_->cancel = true;
|
||||
infoState_ = infoState;
|
||||
@@ -655,7 +655,7 @@ DhtProxyClient::getProxyInfos()
|
||||
auto resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
|
||||
queryProxyInfo(infoState, resolver, AF_INET);
|
||||
queryProxyInfo(infoState, resolver, AF_INET6);
|
||||
std::lock_guard<std::mutex> l(resolverLock_);
|
||||
std::lock_guard l(resolverLock_);
|
||||
resolver_ = resolver;
|
||||
}
|
||||
|
||||
@@ -701,7 +701,7 @@ DhtProxyClient::queryProxyInfo(const Sp<InfoState>& infoState, const Sp<http::Re
|
||||
}
|
||||
}
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
@@ -709,7 +709,7 @@ DhtProxyClient::queryProxyInfo(const Sp<InfoState>& infoState, const Sp<http::Re
|
||||
if (infoState->cancel.load())
|
||||
return;
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
@@ -724,7 +724,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
{
|
||||
if (isDestroying_)
|
||||
return;
|
||||
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::unique_lock l(lockCurrentProxyInfos_);
|
||||
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
auto& status = family == AF_INET ? statusIpv4_ : statusIpv6_;
|
||||
auto& pubAddress = family == AF_INET ? publicAddressV4_ : publicAddressV6_;
|
||||
@@ -761,7 +761,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
addresses.emplace_back(publicAddressV4_);
|
||||
if (publicAddressV6_)
|
||||
addresses.emplace_back(publicAddressV6_);
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back(
|
||||
[cb = publicAddressChangedCb_, addresses = std::move(addresses)]() { cb(std::move(addresses)); });
|
||||
}
|
||||
@@ -785,7 +785,7 @@ DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, const sa_family_t fa
|
||||
listenerRestartTimer_->expires_at(std::chrono::steady_clock::now());
|
||||
listenerRestartTimer_->async_wait(std::bind(&DhtProxyClient::restartListeners, this, std::placeholders::_1));
|
||||
if (not onConnectCallbacks_.empty()) {
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([cbs = std::move(onConnectCallbacks_)]() mutable {
|
||||
while (not cbs.empty()) {
|
||||
cbs.front()();
|
||||
@@ -820,7 +820,7 @@ DhtProxyClient::parsePublicAddress(const Json::Value& val)
|
||||
std::vector<SockAddr>
|
||||
DhtProxyClient::getPublicAddress(sa_family_t family)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
std::vector<SockAddr> result;
|
||||
if (publicAddressV6_ && family != AF_INET)
|
||||
result.emplace_back(publicAddressV6_);
|
||||
@@ -837,7 +837,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
|
||||
if (isDestroying_)
|
||||
return 0;
|
||||
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto& search = searches_[key];
|
||||
auto query = std::make_shared<Query>(Select {}, std::move(where));
|
||||
return search.ops
|
||||
@@ -874,7 +874,7 @@ DhtProxyClient::listen(const InfoHash& key, ValueCallback cb, Value::Filter filt
|
||||
system_clock::time_point t) {
|
||||
if (opstate->stop)
|
||||
return false;
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto s = searches_.find(key);
|
||||
if (s != searches_.end()) {
|
||||
auto l = s->second.listeners.find(token);
|
||||
@@ -929,7 +929,7 @@ DhtProxyClient::handleResubscribe(const asio::error_code& ec,
|
||||
}
|
||||
if (opstate->stop)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto s = searches_.find(key);
|
||||
if (s != searches_.end()) {
|
||||
auto l = s->second.listeners.find(token);
|
||||
@@ -948,7 +948,7 @@ DhtProxyClient::cancelListen(const InfoHash& key, size_t gtoken)
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [search {}] cancel listen {}", key.to_view(), gtoken);
|
||||
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
// find the listener in cache
|
||||
auto it = searches_.find(key);
|
||||
if (it == searches_.end())
|
||||
@@ -979,7 +979,7 @@ DhtProxyClient::handleExpireListener(const asio::error_code& ec, const InfoHash&
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [listen {}] expire listener", key.to_view());
|
||||
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto search = searches_.find(key);
|
||||
if (search == searches_.end())
|
||||
return;
|
||||
@@ -1015,12 +1015,12 @@ DhtProxyClient::handleExpireListener(const asio::error_code& ec, const InfoHash&
|
||||
opFailed();
|
||||
}
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
@@ -1097,7 +1097,7 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t& header,
|
||||
if (cb) {
|
||||
auto expired = json.get("expired", Json::Value(false)).asBool();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockCallbacks_);
|
||||
std::lock_guard lock(lockCallbacks_);
|
||||
callbacks_.emplace_back([cb, value, opstate, expired]() {
|
||||
if (not opstate->stop.load()
|
||||
and not cb({value}, expired, system_clock::time_point::min()))
|
||||
@@ -1124,12 +1124,12 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t& header,
|
||||
opFailed();
|
||||
}
|
||||
if (not isDestroying_) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->add_on_status_callback([request, seconds = this->listenKeepIdle()](unsigned status_code) {
|
||||
@@ -1153,7 +1153,7 @@ DhtProxyClient::opFailed()
|
||||
if (logger_)
|
||||
logger_->error("[proxy:client] proxy request failed");
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
statusIpv4_ = NodeStatus::Disconnected;
|
||||
statusIpv6_ = NodeStatus::Disconnected;
|
||||
}
|
||||
@@ -1186,7 +1186,7 @@ DhtProxyClient::restartListeners(const asio::error_code& ec)
|
||||
if (logger_)
|
||||
logger_->d("[proxy:client] [listeners] refresh permanent puts");
|
||||
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
for (auto& search : searches_) {
|
||||
const auto& key = search.first;
|
||||
for (auto& put : search.second.puts) {
|
||||
@@ -1249,7 +1249,7 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
{
|
||||
// If a push notification is received, the proxy is up and running
|
||||
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
|
||||
std::lock_guard l(lockCurrentProxyInfos_);
|
||||
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
|
||||
if (oldStatus != NodeStatus::Connected)
|
||||
launchConnectedCbs_ = true;
|
||||
@@ -1264,7 +1264,7 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
logger_->debug("[proxy:client] [push] ignoring push for other session");
|
||||
return PushNotificationResult::IgnoredWrongSession;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto timeout = notification.find("timeout");
|
||||
if (timeout != notification.cend()) {
|
||||
InfoHash key(timeout->second);
|
||||
@@ -1326,11 +1326,11 @@ DhtProxyClient::pushNotificationReceived([[maybe_unused]] const std::map<std::st
|
||||
ids.emplace_back(std::stoull(substr));
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lockCb(lockCallbacks_);
|
||||
std::lock_guard lockCb(lockCallbacks_);
|
||||
callbacks_.emplace_back([this, key, token, opstate, ids, sendTime]() {
|
||||
if (opstate->stop)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lock(searchLock_);
|
||||
std::lock_guard lock(searchLock_);
|
||||
auto s = searches_.find(key);
|
||||
if (s == searches_.end())
|
||||
return;
|
||||
@@ -1376,7 +1376,7 @@ DhtProxyClient::resubscribe([[maybe_unused]] const InfoHash& key,
|
||||
|
||||
restinio::http_request_header_t header;
|
||||
header.method(restinio::http_method_subscribe());
|
||||
header.request_target("/" + key.toString());
|
||||
header.request_target("/key/" + key.toString());
|
||||
if (!listener.refreshSubscriberTimer) {
|
||||
listener.refreshSubscriberTimer = std::make_unique<asio::steady_timer>(httpContext_);
|
||||
}
|
||||
@@ -1422,17 +1422,20 @@ void
|
||||
DhtProxyClient::setPushNotificationToken([[maybe_unused]] const std::string& token)
|
||||
{
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
std::unique_lock<std::mutex> l(lockCurrentProxyInfos_);
|
||||
if (deviceKey_ != token) {
|
||||
{
|
||||
std::unique_lock l(lockCurrentProxyInfos_);
|
||||
if (deviceKey_ == token)
|
||||
return;
|
||||
deviceKey_ = token;
|
||||
if (statusIpv4_ == NodeStatus::Connected || statusIpv6_ == NodeStatus::Connected) {
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [push] token changed, resubscribing");
|
||||
for (auto& search : searches_) {
|
||||
for (auto& listener : search.second.listeners) {
|
||||
resubscribe(search.first, listener.first, listener.second);
|
||||
}
|
||||
}
|
||||
if (!(statusIpv4_ == NodeStatus::Connected || statusIpv6_ == NodeStatus::Connected))
|
||||
return;
|
||||
}
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:client] [push] token changed, resubscribing");
|
||||
std::lock_guard lock(searchLock_);
|
||||
for (auto& search : searches_) {
|
||||
for (auto& listener : search.second.listeners) {
|
||||
resubscribe(search.first, listener.first, listener.second);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+28
-23
@@ -176,7 +176,7 @@ DhtProxyServer::ConnectionListener::state_changed(const restinio::connection_sta
|
||||
void
|
||||
DhtProxyServer::onConnectionClosed(restinio::connection_id_t id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
auto it = listeners_.find(id);
|
||||
if (it != listeners_.end()) {
|
||||
dht_->cancelListen(it->second.hash, std::move(it->second.token));
|
||||
@@ -381,13 +381,13 @@ DhtProxyServer::saveState(Os& stream)
|
||||
msgpack::packer<Os> pk(&stream);
|
||||
pk.pack_map(2);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockSearchPuts_);
|
||||
std::lock_guard lock(lockSearchPuts_);
|
||||
pk.pack("puts");
|
||||
pk.pack(puts_);
|
||||
}
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
pk.pack("pushListeners");
|
||||
pk.pack(pushListeners_);
|
||||
}
|
||||
@@ -408,7 +408,7 @@ DhtProxyServer::loadState(Is& is, size_t size)
|
||||
if (oh.get().type != msgpack::type::MAP)
|
||||
continue;
|
||||
if (auto puts = findMapValue(oh.get(), "puts"sv)) {
|
||||
std::lock_guard<std::mutex> lock(lockSearchPuts_);
|
||||
std::lock_guard lock(lockSearchPuts_);
|
||||
puts_ = puts->as<decltype(puts_)>();
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:server] Loading {} persistent puts", puts_.size());
|
||||
@@ -432,7 +432,7 @@ DhtProxyServer::loadState(Is& is, size_t size)
|
||||
json["to"] = clientId;
|
||||
json["vid"] = std::to_string(vid);
|
||||
if (sessionCtx) {
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
json["s"] = sessionCtx->sessionId;
|
||||
}
|
||||
return json;
|
||||
@@ -459,7 +459,7 @@ DhtProxyServer::loadState(Is& is, size_t size)
|
||||
}
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
if (auto pushListeners = findMapValue(oh.get(), "pushListeners"sv)) {
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
pushListeners_ = pushListeners->as<decltype(pushListeners_)>();
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:server] Loading {} push listeners", pushListeners_.size());
|
||||
@@ -496,7 +496,7 @@ DhtProxyServer::loadState(Is& is, size_t size)
|
||||
Json::Value json;
|
||||
json["timeout"] = infoHash;
|
||||
json["to"] = clientId;
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
json["s"] = sessionCtx->sessionId;
|
||||
return json;
|
||||
};
|
||||
@@ -546,7 +546,7 @@ DhtProxyServer::~DhtProxyServer()
|
||||
saveState(stateFile);
|
||||
}
|
||||
if (dht_) {
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
for (auto& l : listeners_) {
|
||||
dht_->cancelListen(l.second.hash, std::move(l.second.token));
|
||||
if (l.second.response)
|
||||
@@ -817,7 +817,7 @@ DhtProxyServer::listen(restinio::request_handle_t request, restinio::router::rou
|
||||
auto response = std::make_shared<ResponseByPartsBuilder>(
|
||||
initHttpResponse(request->create_response<ResponseByParts>()));
|
||||
response->flush();
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
// save the listener to handle a disconnect
|
||||
auto& session = listeners_[request->connection_id()];
|
||||
session.hash = infoHash;
|
||||
@@ -931,7 +931,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request, restinio::router::
|
||||
logger_->debug("[proxy:server] [subscribe {}] [client {}] [session {}]", infoHash, clientId, sessionId);
|
||||
|
||||
// Insert new or return existing push listeners of a token
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
auto& pushListener = pushListeners_[pushToken];
|
||||
auto& pushListeners = pushListener.listeners[infoHash];
|
||||
|
||||
@@ -945,7 +945,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request, restinio::router::
|
||||
listIt->clientId = clientId;
|
||||
listIt->sessionCtx = std::make_shared<PushSessionContext>(sessionId);
|
||||
} else {
|
||||
std::lock_guard<std::mutex> l(listIt->sessionCtx->lock);
|
||||
std::lock_guard l(listIt->sessionCtx->lock);
|
||||
listIt->sessionCtx->sessionId = sessionId;
|
||||
}
|
||||
auto& listener = *listIt;
|
||||
@@ -963,7 +963,7 @@ DhtProxyServer::subscribe(restinio::request_handle_t request, restinio::router::
|
||||
Json::Value json;
|
||||
json["timeout"] = h;
|
||||
json["to"] = clientId;
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
json["s"] = sessionCtx->sessionId;
|
||||
return json;
|
||||
};
|
||||
@@ -1110,7 +1110,7 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code& ec,
|
||||
}
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:server] [listen:push {}] cancelled for {}", key, clientId);
|
||||
std::lock_guard<std::mutex> lock(lockListener_);
|
||||
std::lock_guard lock(lockListener_);
|
||||
|
||||
auto pushListener = pushListeners_.find(pushToken);
|
||||
if (pushListener == pushListeners_.end())
|
||||
@@ -1151,19 +1151,24 @@ DhtProxyServer::handlePushListen(const InfoHash& infoHash,
|
||||
json["t"] = Json::Value::Int64(duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count());
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
json["s"] = sessionCtx->sessionId;
|
||||
}
|
||||
|
||||
// Build a comma-separated list of ids from the values. This is intended to be used when
|
||||
// streaming from the iOS notification extension in order to filter out unwanted values.
|
||||
std::string ids;
|
||||
std::string pushTypes;
|
||||
for (const auto& value : values) {
|
||||
if (!ids.empty())
|
||||
if (!ids.empty()) {
|
||||
ids += ",";
|
||||
pushTypes += ",";
|
||||
}
|
||||
pushTypes += value->pushType;
|
||||
ids += std::to_string(value->id);
|
||||
}
|
||||
json["ids"] = ids;
|
||||
json["pt"] = pushTypes;
|
||||
|
||||
// If message is expired copy the value ID to the `exp` field.
|
||||
// This is presumably used by the Android notification system.
|
||||
@@ -1302,12 +1307,12 @@ DhtProxyServer::sendPushNotification(
|
||||
if (state == http::Request::State::DONE) {
|
||||
if (logger_ and response.status_code != 200)
|
||||
logger_->error("[proxy:server] [notification] push failed: {}", response.status_code);
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
});
|
||||
{
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_[reqid] = request;
|
||||
}
|
||||
request->send();
|
||||
@@ -1330,7 +1335,7 @@ DhtProxyServer::sendPushNotification(
|
||||
if (logger_)
|
||||
logger_->error("[proxy:server] [notification] error send push: {}", e.what());
|
||||
if (reqid) {
|
||||
std::lock_guard<std::mutex> l(requestLock_);
|
||||
std::lock_guard l(requestLock_);
|
||||
requests_.erase(reqid);
|
||||
}
|
||||
}
|
||||
@@ -1349,7 +1354,7 @@ DhtProxyServer::handleCancelPermamentPut(const asio::error_code& ec, const InfoH
|
||||
}
|
||||
if (logger_)
|
||||
logger_->debug("[proxy:server] [put {}] cancel permament put {}", key, vid);
|
||||
std::lock_guard<std::mutex> lock(lockSearchPuts_);
|
||||
std::lock_guard lock(lockSearchPuts_);
|
||||
auto sPuts = puts_.find(key);
|
||||
if (sPuts == puts_.end())
|
||||
return;
|
||||
@@ -1406,7 +1411,7 @@ DhtProxyServer::put(restinio::request_handle_t request, restinio::router::route_
|
||||
sessionId = pVal["session_id"].asString();
|
||||
topic = pVal["topic"].asString();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(lockSearchPuts_);
|
||||
std::lock_guard lock(lockSearchPuts_);
|
||||
auto timeout = std::chrono::steady_clock::now() + proxy::OP_TIMEOUT;
|
||||
auto& sPuts = puts_[infoHash];
|
||||
if (value->id == Value::INVALID_ID) {
|
||||
@@ -1423,7 +1428,7 @@ DhtProxyServer::put(restinio::request_handle_t request, restinio::router::route_
|
||||
if (not pp.second.sessionCtx)
|
||||
pp.second.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
|
||||
else {
|
||||
std::lock_guard<std::mutex> l(pp.second.sessionCtx->lock);
|
||||
std::lock_guard l(pp.second.sessionCtx->lock);
|
||||
pp.second.sessionCtx->sessionId = sessionId;
|
||||
}
|
||||
}
|
||||
@@ -1458,7 +1463,7 @@ DhtProxyServer::put(restinio::request_handle_t request, restinio::router::route_
|
||||
if (not pput.sessionCtx)
|
||||
pput.sessionCtx = std::make_shared<PushSessionContext>(sessionId);
|
||||
else {
|
||||
std::lock_guard<std::mutex> l(pput.sessionCtx->lock);
|
||||
std::lock_guard l(pput.sessionCtx->lock);
|
||||
pput.sessionCtx->sessionId = sessionId;
|
||||
}
|
||||
}
|
||||
@@ -1475,7 +1480,7 @@ DhtProxyServer::put(restinio::request_handle_t request, restinio::router::route_
|
||||
json["timeout"] = infoHash.toString();
|
||||
json["to"] = clientId;
|
||||
json["vid"] = std::to_string(vid);
|
||||
std::lock_guard<std::mutex> l(sessionCtx->lock);
|
||||
std::lock_guard l(sessionCtx->lock);
|
||||
json["s"] = sessionCtx->sessionId;
|
||||
return json;
|
||||
};
|
||||
|
||||
+72
-134
@@ -76,7 +76,7 @@ DhtRunner::run(const char* ip4, const char* ip6, const char* service, Config& co
|
||||
void
|
||||
DhtRunner::run(const Config& config, Context&& context)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
auto expected = State::Idle;
|
||||
if (not running.compare_exchange_strong(expected, State::Running)) {
|
||||
if (context.logger)
|
||||
@@ -141,7 +141,7 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
context.sock->setOnReceive([&](net::PacketList&& pkts) {
|
||||
net::PacketList ret;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
std::lock_guard lck(sock_mtx);
|
||||
rcv.splice(rcv.end(), std::move(pkts));
|
||||
size_t dropped = 0;
|
||||
while (rcv.size() > net::RX_QUEUE_MAX_SIZE) {
|
||||
@@ -186,9 +186,6 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
if (context.certificateStore) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStore));
|
||||
}
|
||||
if (context.certificateStorePkId) {
|
||||
dht_->setLocalCertificateStore(std::move(context.certificateStorePkId));
|
||||
}
|
||||
if (context.publicAddressChangedCb) {
|
||||
dht_->setOnPublicAddressChanged(std::move(context.publicAddressChangedCb));
|
||||
}
|
||||
@@ -197,19 +194,19 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
return;
|
||||
dht_thread = std::thread([this]() {
|
||||
while (running != State::Idle) {
|
||||
std::unique_lock<std::mutex> lk(dht_mtx);
|
||||
std::unique_lock lk(dht_mtx);
|
||||
time_point wakeup = loop_();
|
||||
|
||||
auto hasJobToDo = [this]() {
|
||||
if (running == State::Idle)
|
||||
return true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
std::lock_guard lck(sock_mtx);
|
||||
if (not rcv.empty())
|
||||
return true;
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (not pending_ops_prio.empty())
|
||||
return true;
|
||||
auto s = getStatus();
|
||||
@@ -284,7 +281,7 @@ DhtRunner::run(const Config& config, Context&& context)
|
||||
void
|
||||
DhtRunner::shutdown(ShutdownCallback cb, bool stop)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
auto expected = State::Running;
|
||||
if (not running.compare_exchange_strong(expected, State::Stopping)) {
|
||||
if (expected == State::Stopping and ongoing_ops) {
|
||||
@@ -344,7 +341,7 @@ DhtRunner::checkShutdown()
|
||||
{
|
||||
decltype(shutdownCallbacks_) cbs;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (running != State::Stopping or ongoing_ops)
|
||||
return false;
|
||||
cbs = std::move(shutdownCallbacks_);
|
||||
@@ -359,7 +356,7 @@ void
|
||||
DhtRunner::join()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (running.exchange(State::Idle) == State::Idle)
|
||||
return;
|
||||
cv.notify_all();
|
||||
@@ -378,7 +375,7 @@ DhtRunner::join()
|
||||
dht_thread.join();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (ongoing_ops and logger_) {
|
||||
logger_->warn("[runner {:p}] stopping with {:d} remaining ops", fmt::ptr(this), ongoing_ops.load());
|
||||
}
|
||||
@@ -388,7 +385,7 @@ DhtRunner::join()
|
||||
shutdownCallbacks_.clear();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
resetDht();
|
||||
status4 = NodeStatus::Disconnected;
|
||||
status6 = NodeStatus::Disconnected;
|
||||
@@ -398,7 +395,7 @@ DhtRunner::join()
|
||||
SockAddr
|
||||
DhtRunner::getBound(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
if (auto sock = dht_->getSocket())
|
||||
return sock->getBound(af);
|
||||
@@ -408,7 +405,7 @@ DhtRunner::getBound(sa_family_t af) const
|
||||
in_port_t
|
||||
DhtRunner::getBoundPort(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
if (auto sock = dht_->getSocket())
|
||||
return sock->getPort(af);
|
||||
@@ -418,7 +415,7 @@ DhtRunner::getBoundPort(sa_family_t af) const
|
||||
void
|
||||
DhtRunner::dumpTables() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
dht_->dumpTables();
|
||||
}
|
||||
|
||||
@@ -443,7 +440,7 @@ DhtRunner::getNodeId() const
|
||||
std::pair<size_t, size_t>
|
||||
DhtRunner::getStoreSize() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
return {};
|
||||
return dht_->getStoreSize();
|
||||
@@ -452,7 +449,7 @@ DhtRunner::getStoreSize() const
|
||||
void
|
||||
DhtRunner::setStorageLimit(size_t limit)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
throw std::runtime_error("dht is not running");
|
||||
return dht_->setStorageLimit(limit);
|
||||
@@ -461,7 +458,7 @@ DhtRunner::setStorageLimit(size_t limit)
|
||||
size_t
|
||||
DhtRunner::getStorageLimit() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
throw std::runtime_error("dht is not running");
|
||||
return dht_->getStorageLimit();
|
||||
@@ -470,7 +467,7 @@ DhtRunner::getStorageLimit() const
|
||||
void
|
||||
DhtRunner::setLocalStorageLimit(size_t limit)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
throw std::runtime_error("dht is not running");
|
||||
return dht_->setLocalStorageLimit(limit);
|
||||
@@ -479,7 +476,7 @@ DhtRunner::setLocalStorageLimit(size_t limit)
|
||||
size_t
|
||||
DhtRunner::getLocalStorageLimit() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
throw std::runtime_error("dht is not running");
|
||||
return dht_->getLocalStorageLimit();
|
||||
@@ -488,7 +485,7 @@ DhtRunner::getLocalStorageLimit() const
|
||||
std::vector<NodeExport>
|
||||
DhtRunner::exportNodes() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
return {};
|
||||
return dht_->exportNodes();
|
||||
@@ -497,7 +494,7 @@ DhtRunner::exportNodes() const
|
||||
std::vector<ValuesExport>
|
||||
DhtRunner::exportValues() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (!dht_)
|
||||
return {};
|
||||
return dht_->exportValues();
|
||||
@@ -506,7 +503,7 @@ DhtRunner::exportValues() const
|
||||
void
|
||||
DhtRunner::setLogger(const Sp<Logger>& logger)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
logger_ = logger;
|
||||
if (dht_)
|
||||
dht_->setLogger(logger);
|
||||
@@ -515,7 +512,7 @@ DhtRunner::setLogger(const Sp<Logger>& logger)
|
||||
void
|
||||
DhtRunner::setLogFilter(const InfoHash& f)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
dht_->setLogFilter(f);
|
||||
}
|
||||
@@ -523,21 +520,21 @@ DhtRunner::setLogFilter(const InfoHash& f)
|
||||
void
|
||||
DhtRunner::registerType(const ValueType& type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
dht_->registerType(type);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::registerInsecureType(const ValueType& type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
dht_->registerInsecureType(type);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::importValues(const std::vector<ValuesExport>& values)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
dht_->importValues(values);
|
||||
}
|
||||
|
||||
@@ -548,7 +545,7 @@ DhtRunner::getNodesStats(sa_family_t af,
|
||||
unsigned* cached_return,
|
||||
unsigned* incoming_return) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
const auto stats = dht_->getNodesStats(af);
|
||||
if (good_return)
|
||||
*good_return = stats.good_nodes;
|
||||
@@ -564,7 +561,7 @@ DhtRunner::getNodesStats(sa_family_t af,
|
||||
NodeStats
|
||||
DhtRunner::getNodesStats(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getNodesStats(af);
|
||||
}
|
||||
|
||||
@@ -572,7 +569,7 @@ NodeInfo
|
||||
DhtRunner::getNodeInfo() const
|
||||
{
|
||||
NodeInfo info {};
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
info = dht_->getNodeInfo();
|
||||
info.ongoing_ops = ongoing_ops;
|
||||
@@ -582,7 +579,7 @@ DhtRunner::getNodeInfo() const
|
||||
void
|
||||
DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([cb = std::move(cb), this](SecureDht& dht) {
|
||||
auto sinfo = std::make_shared<NodeInfo>();
|
||||
@@ -597,44 +594,44 @@ DhtRunner::getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)> cb)
|
||||
std::vector<unsigned>
|
||||
DhtRunner::getNodeMessageStats(bool in) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getNodeMessageStats(in);
|
||||
}
|
||||
|
||||
std::string
|
||||
DhtRunner::getStorageLog() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getStorageLog();
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getStorageLog(const InfoHash& f) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getStorageLog(f);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getRoutingTablesLog(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getRoutingTablesLog(af);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getSearchesLog(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getSearchesLog(af);
|
||||
}
|
||||
std::string
|
||||
DhtRunner::getSearchLog(const InfoHash& f, sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
return dht_->getSearchLog(f, af);
|
||||
}
|
||||
std::vector<SockAddr>
|
||||
DhtRunner::getPublicAddress(sa_family_t af) const
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
return dht_->getPublicAddress(af);
|
||||
return {};
|
||||
@@ -651,7 +648,7 @@ DhtRunner::getPublicAddressStr(sa_family_t af) const
|
||||
void
|
||||
DhtRunner::getPublicAddress(std::function<void(std::vector<SockAddr>&&)> cb, sa_family_t af)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([cb = std::move(cb), this, af](SecureDht& dht) {
|
||||
cb(dht.getPublicAddress(af));
|
||||
@@ -663,22 +660,14 @@ DhtRunner::getPublicAddress(std::function<void(std::vector<SockAddr>&&)> cb, sa_
|
||||
void
|
||||
DhtRunner::registerCertificate(const std::shared_ptr<crypto::Certificate>& cert)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
dht_->registerCertificate(cert);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLocalCertificateStore(CertificateStoreQueryLegacy&& query_method)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
if (dht_)
|
||||
dht_->setLocalCertificateStore(std::forward<CertificateStoreQueryLegacy>(query_method));
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::setLocalCertificateStore(CertificateStoreQuery&& query_method)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
dht_->setLocalCertificateStore(std::forward<CertificateStoreQuery>(query_method));
|
||||
}
|
||||
@@ -691,7 +680,7 @@ DhtRunner::loop_()
|
||||
|
||||
decltype(pending_ops) ops {};
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
auto s = getStatus();
|
||||
ops = (pending_ops_prio.empty()
|
||||
&& (s == NodeStatus::Connected or s == NodeStatus::Disconnected or running == State::Stopping))
|
||||
@@ -707,7 +696,7 @@ DhtRunner::loop_()
|
||||
decltype(rcv) received {};
|
||||
decltype(rcv) received_treated {};
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
std::lock_guard lck(sock_mtx);
|
||||
// move to stack
|
||||
received = std::move(rcv);
|
||||
}
|
||||
@@ -742,7 +731,7 @@ DhtRunner::loop_()
|
||||
}
|
||||
|
||||
if (not received_treated.empty()) {
|
||||
std::lock_guard<std::mutex> lck(sock_mtx);
|
||||
std::lock_guard lck(sock_mtx);
|
||||
if (rcv_free.size() < net::RX_QUEUE_MAX_SIZE)
|
||||
rcv_free.splice(rcv_free.end(), std::move(received_treated));
|
||||
}
|
||||
@@ -766,7 +755,7 @@ DhtRunner::loop_()
|
||||
void
|
||||
DhtRunner::get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f, Where w)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (dcb)
|
||||
@@ -788,7 +777,7 @@ DhtRunner::get(const std::string& key, GetCallback vcb, DoneCallbackSimple dcb,
|
||||
void
|
||||
DhtRunner::query(const InfoHash& hash, QueryCallback cb, DoneCallback done_cb, Query q)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (done_cb)
|
||||
@@ -806,7 +795,7 @@ std::future<size_t>
|
||||
DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
|
||||
{
|
||||
auto ret_token = std::make_shared<std::promise<size_t>>();
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
ret_token->set_value(0);
|
||||
@@ -828,7 +817,7 @@ DhtRunner::listen(const std::string& key, GetCallback vcb, Value::Filter f, Wher
|
||||
void
|
||||
DhtRunner::cancelListen(InfoHash h, size_t token)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
ongoing_ops++;
|
||||
@@ -842,7 +831,7 @@ DhtRunner::cancelListen(InfoHash h, size_t token)
|
||||
void
|
||||
DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
ongoing_ops++;
|
||||
@@ -856,7 +845,7 @@ DhtRunner::cancelListen(InfoHash h, std::shared_future<size_t> ftoken)
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb, time_point created, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -873,7 +862,7 @@ DhtRunner::put(InfoHash hash, Value&& value, DoneCallback cb, time_point created
|
||||
void
|
||||
DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, time_point created, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -896,7 +885,7 @@ DhtRunner::put(const std::string& key, Value&& value, DoneCallbackSimple cb, tim
|
||||
void
|
||||
DhtRunner::cancelPut(const InfoHash& h, Value::Id id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops.emplace([=](SecureDht& dht) { dht.cancelPut(h, id); });
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -904,7 +893,7 @@ DhtRunner::cancelPut(const InfoHash& h, Value::Id id)
|
||||
void
|
||||
DhtRunner::cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops.emplace([=](SecureDht& dht) { dht.cancelPut(h, value->id); });
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -912,7 +901,7 @@ DhtRunner::cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value)
|
||||
void
|
||||
DhtRunner::putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -941,7 +930,7 @@ DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple c
|
||||
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);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -955,35 +944,6 @@ DhtRunner::putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> va
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash, InfoHash 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, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb, bool permanent)
|
||||
{
|
||||
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb), permanent);
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::putEncrypted(InfoHash hash,
|
||||
const std::shared_ptr<crypto::PublicKey>& to,
|
||||
@@ -991,7 +951,7 @@ DhtRunner::putEncrypted(InfoHash hash,
|
||||
DoneCallback cb,
|
||||
bool permanent)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -1015,7 +975,7 @@ DhtRunner::putEncrypted(
|
||||
void
|
||||
DhtRunner::bootstrap(const std::string& host, const std::string& service)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops_prio.emplace([host, service](SecureDht& dht) mutable { dht.addBootstrap(host, service); });
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -1023,7 +983,7 @@ DhtRunner::bootstrap(const std::string& host, const std::string& service)
|
||||
void
|
||||
DhtRunner::bootstrap(const std::string& hostService)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
auto [h, s] = splitPort(hostService);
|
||||
pending_ops_prio.emplace(
|
||||
[host = std::string(h), service = std::string(s)](SecureDht& dht) { dht.addBootstrap(host, service); });
|
||||
@@ -1033,7 +993,7 @@ DhtRunner::bootstrap(const std::string& hostService)
|
||||
void
|
||||
DhtRunner::clearBootstrap()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops_prio.emplace([](SecureDht& dht) mutable { dht.clearBootstrap(); });
|
||||
cv.notify_all();
|
||||
}
|
||||
@@ -1045,7 +1005,7 @@ DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb)
|
||||
cb(false);
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
ongoing_ops++;
|
||||
pending_ops_prio.emplace([cb = bindOpDoneCallback(std::move(cb)), nodes = std::move(nodes)](SecureDht& dht) mutable {
|
||||
auto rem = cb ? std::make_shared<std::pair<size_t, bool>>(nodes.size(), false) : nullptr;
|
||||
@@ -1068,7 +1028,7 @@ DhtRunner::bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb)
|
||||
void
|
||||
DhtRunner::bootstrap(SockAddr addr, DoneCallbackSimple cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
if (cb)
|
||||
@@ -1085,7 +1045,7 @@ DhtRunner::bootstrap(SockAddr addr, DoneCallbackSimple cb)
|
||||
void
|
||||
DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
pending_ops_prio.emplace([id, address](SecureDht& dht) mutable { dht.insertNode(id, address); });
|
||||
@@ -1095,7 +1055,7 @@ DhtRunner::bootstrap(const InfoHash& id, const SockAddr& address)
|
||||
void
|
||||
DhtRunner::bootstrap(std::vector<NodeExport> nodes)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
if (running != State::Running)
|
||||
return;
|
||||
pending_ops_prio.emplace([nodes = std::move(nodes)](SecureDht& dht) {
|
||||
@@ -1108,7 +1068,7 @@ DhtRunner::bootstrap(std::vector<NodeExport> nodes)
|
||||
void
|
||||
DhtRunner::connectivityChanged()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht& dht) {
|
||||
dht.connectivityChanged();
|
||||
#ifdef OPENDHT_PEER_DISCOVERY
|
||||
@@ -1119,29 +1079,10 @@ DhtRunner::connectivityChanged()
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunner::findCertificate(InfoHash hash, std::function<void(const Sp<crypto::Certificate>&)> cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
cb({});
|
||||
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::findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)> cb)
|
||||
{
|
||||
std::unique_lock<std::mutex> lck(storage_mtx);
|
||||
std::unique_lock lck(storage_mtx);
|
||||
if (running != State::Running) {
|
||||
lck.unlock();
|
||||
return;
|
||||
@@ -1167,7 +1108,7 @@ void
|
||||
DhtRunner::setProxyServer(const std::string& proxy, const std::string& pushNodeId)
|
||||
{
|
||||
#ifdef OPENDHT_PROXY_CLIENT
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (config_.proxy_server == proxy and config_.push_node_id == pushNodeId)
|
||||
return;
|
||||
config_.proxy_server = proxy;
|
||||
@@ -1194,8 +1135,8 @@ DhtRunner::enableProxy(bool proxify)
|
||||
config_.client_identity,
|
||||
[this] {
|
||||
if (config_.threaded) {
|
||||
std::lock_guard<std::mutex> lck(storage_mtx);
|
||||
pending_ops_prio.emplace([=](SecureDht&) mutable {});
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops_prio.emplace([](SecureDht&) {});
|
||||
cv.notify_all();
|
||||
}
|
||||
},
|
||||
@@ -1207,11 +1148,8 @@ DhtRunner::enableProxy(bool proxify)
|
||||
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;
|
||||
} else {
|
||||
use_proxy = proxify;
|
||||
}
|
||||
use_proxy = proxify;
|
||||
#else
|
||||
if (proxify)
|
||||
throw std::runtime_error("DHT proxy requested but OpenDHT built without proxy support.");
|
||||
@@ -1221,7 +1159,7 @@ DhtRunner::enableProxy(bool proxify)
|
||||
void
|
||||
DhtRunner::forwardAllMessages(bool forward)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
if (dht_)
|
||||
dht_->forwardAllMessages(forward);
|
||||
}
|
||||
@@ -1232,7 +1170,7 @@ DhtRunner::forwardAllMessages(bool forward)
|
||||
void
|
||||
DhtRunner::setPushNotificationToken(const std::string& token)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
|
||||
config_.push_token = token;
|
||||
if (dht_)
|
||||
@@ -1245,7 +1183,7 @@ DhtRunner::setPushNotificationToken(const std::string& token)
|
||||
void
|
||||
DhtRunner::setPushNotificationTopic(const std::string& topic)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
|
||||
config_.push_topic = topic;
|
||||
if (dht_)
|
||||
@@ -1258,7 +1196,7 @@ DhtRunner::setPushNotificationTopic(const std::string& topic)
|
||||
void
|
||||
DhtRunner::setPushNotificationPlatform(const std::string& platform)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dht_mtx);
|
||||
std::lock_guard lck(dht_mtx);
|
||||
#if defined(OPENDHT_PROXY_CLIENT) && defined(OPENDHT_PUSH_NOTIFICATIONS)
|
||||
config_.push_platform = platform;
|
||||
if (dht_)
|
||||
@@ -1274,7 +1212,7 @@ DhtRunner::pushNotificationReceived([[maybe_unused]] const std::map<std::string,
|
||||
#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);
|
||||
std::lock_guard lck(storage_mtx);
|
||||
pending_ops_prio.emplace([ret_token, this, data](SecureDht&) {
|
||||
if (dht_)
|
||||
ret_token->set_value(dht_->pushNotificationReceived(data));
|
||||
|
||||
+20
-20
@@ -239,7 +239,7 @@ Connection::~Connection()
|
||||
void
|
||||
Connection::close()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
asio::error_code ec;
|
||||
if (ssl_socket_) {
|
||||
if (ssl_socket_->is_open())
|
||||
@@ -490,7 +490,7 @@ ocspValidateResponse(const OscpRequestInfo& info,
|
||||
void
|
||||
Connection::set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (ssl_socket_) {
|
||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||
SSL_set_tlsext_host_name(ssl_socket_->asio_ssl_stream().native_handle(), hostname.c_str());
|
||||
@@ -576,7 +576,7 @@ Connection::input()
|
||||
std::string
|
||||
Connection::read_bytes(size_t bytes)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (bytes == 0)
|
||||
bytes = read_buf_.in_avail();
|
||||
std::string content;
|
||||
@@ -597,7 +597,7 @@ Connection::read_until(const char delim)
|
||||
void
|
||||
Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!ssl_socket_ && !socket_) {
|
||||
cb(asio::error::operation_aborted, {});
|
||||
return;
|
||||
@@ -629,7 +629,7 @@ Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, Conn
|
||||
void
|
||||
Connection::async_handshake(HandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (ssl_socket_) {
|
||||
std::weak_ptr<Connection> wthis = shared_from_this();
|
||||
ssl_socket_
|
||||
@@ -663,7 +663,7 @@ Connection::async_handshake(HandlerCb cb)
|
||||
void
|
||||
Connection::async_write(BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb)
|
||||
asio::post(ctx_, [cb]() { cb(asio::error::broken_pipe, 0); });
|
||||
@@ -680,7 +680,7 @@ Connection::async_write(BytesHandlerCb cb)
|
||||
void
|
||||
Connection::async_read_until(const char* delim, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb)
|
||||
asio::post(ctx_, [cb]() { cb(asio::error::broken_pipe, 0); });
|
||||
@@ -697,7 +697,7 @@ Connection::async_read_until(const char* delim, BytesHandlerCb cb)
|
||||
void
|
||||
Connection::async_read_until(char delim, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb)
|
||||
asio::post(ctx_, [cb]() { cb(asio::error::broken_pipe, 0); });
|
||||
@@ -714,7 +714,7 @@ Connection::async_read_until(char delim, BytesHandlerCb cb)
|
||||
void
|
||||
Connection::async_read(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb)
|
||||
asio::post(ctx_, [cb]() { cb(asio::error::broken_pipe, 0); });
|
||||
@@ -731,7 +731,7 @@ Connection::async_read(size_t bytes, BytesHandlerCb cb)
|
||||
void
|
||||
Connection::async_read_some(size_t bytes, BytesHandlerCb cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!is_open()) {
|
||||
if (cb)
|
||||
asio::post(ctx_, [cb]() { cb(asio::error::broken_pipe, 0); });
|
||||
@@ -751,7 +751,7 @@ Connection::async_read_some(size_t bytes, BytesHandlerCb cb)
|
||||
void
|
||||
Connection::set_keepalive(uint32_t seconds)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!ssl_socket_ && !socket_)
|
||||
return;
|
||||
|
||||
@@ -871,7 +871,7 @@ Resolver::~Resolver()
|
||||
{
|
||||
decltype(cbs_) cbs;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
cbs = std::move(cbs_);
|
||||
}
|
||||
while (not cbs.empty()) {
|
||||
@@ -907,7 +907,7 @@ filter(const std::vector<asio::ip::tcp::endpoint>& epts, sa_family_t family)
|
||||
void
|
||||
Resolver::add_callback(ResolverCb cb, sa_family_t family)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (!completed_)
|
||||
cbs_.emplace(family == AF_UNSPEC ? std::move(cb)
|
||||
: [cb, family](const asio::error_code& ec,
|
||||
@@ -946,7 +946,7 @@ Resolver::resolve(std::string_view host, std::string_view service)
|
||||
}
|
||||
decltype(cbs_) cbs;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
ec_ = ec;
|
||||
endpoints_ = std::vector<asio::ip::tcp::endpoint> {endpoints.begin(),
|
||||
endpoints.end()};
|
||||
@@ -1390,7 +1390,7 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
|
||||
if (not sthis)
|
||||
return;
|
||||
auto& this_ = *sthis;
|
||||
std::lock_guard<std::mutex> lock(this_.mutex_);
|
||||
std::lock_guard lock(this_.mutex_);
|
||||
if (ec == asio::error::operation_aborted) {
|
||||
this_.terminate(ec);
|
||||
return;
|
||||
@@ -1443,7 +1443,7 @@ Request::send()
|
||||
[wthis](const asio::error_code& ec, std::vector<asio::ip::tcp::endpoint> endpoints) {
|
||||
if (auto sthis = wthis.lock()) {
|
||||
auto& this_ = *sthis;
|
||||
std::lock_guard<std::mutex> lock(this_.mutex_);
|
||||
std::lock_guard lock(this_.mutex_);
|
||||
if (ec) {
|
||||
if (this_.logger_)
|
||||
this_.logger_->error("[http:request:{:d}] resolve error: {:s}", this_.id_, ec.message());
|
||||
@@ -1518,7 +1518,7 @@ Request::terminate(const asio::error_code& ec)
|
||||
void
|
||||
Request::handle_request(const asio::error_code& ec)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (ec and ec != asio::error::eof) {
|
||||
terminate(ec);
|
||||
return;
|
||||
@@ -1542,7 +1542,7 @@ Request::handle_request(const asio::error_code& ec)
|
||||
void
|
||||
Request::handle_response(const asio::error_code& ec, size_t /* n_bytes */)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
if (ec && ec != asio::error::eof) {
|
||||
terminate(ec);
|
||||
return;
|
||||
@@ -1660,11 +1660,11 @@ const Response&
|
||||
Request::await()
|
||||
{
|
||||
std::mutex mtx;
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
std::unique_lock lock(mtx);
|
||||
std::condition_variable cv;
|
||||
bool ok {false};
|
||||
add_on_done_callback([&](const Response&) {
|
||||
std::lock_guard<std::mutex> lk(mtx);
|
||||
std::lock_guard lk(mtx);
|
||||
ok = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
@@ -488,8 +488,9 @@ NetworkEngine::processMessage(const uint8_t* buf, size_t buflen, SockAddr f)
|
||||
try {
|
||||
// process the full message
|
||||
process(std::move(pmsg_it->second.msg), from);
|
||||
} catch (...) {
|
||||
return;
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->warn("Error while processing partial message: {}", e.what());
|
||||
}
|
||||
partial_messages.erase(pmsg_it);
|
||||
} else
|
||||
@@ -516,7 +517,9 @@ NetworkEngine::processMessage(const uint8_t* buf, size_t buflen, SockAddr f)
|
||||
if (msg->value_parts.empty()) {
|
||||
try {
|
||||
process(std::move(msg), from);
|
||||
} catch (...) {
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->warn("Error while processing message: {}", e.what());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -107,14 +107,14 @@ UdpSocket::UdpSocket(in_port_t port, const std::shared_ptr<Logger>& l)
|
||||
SockAddr bind6;
|
||||
bind6.setFamily(AF_INET6);
|
||||
bind6.setPort(port);
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
openSockets(bind4, bind6);
|
||||
}
|
||||
|
||||
UdpSocket::UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const std::shared_ptr<Logger>& l)
|
||||
: logger(l)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
openSockets(bind4, bind6);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ UdpSocket::sendTo(const SockAddr& dest, const uint8_t* data, size_t size, [[mayb
|
||||
if (logger)
|
||||
logger->d("Can't send message to %s: %s", dest.toString().c_str(), strerror(err));
|
||||
if (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
std::lock_guard<std::mutex> lk(lock);
|
||||
std::lock_guard lk(lock);
|
||||
auto bind4 = std::move(bound4), bind6 = std::move(bound6);
|
||||
openSockets(bind4, bind6);
|
||||
return sendTo(dest, data, size, false);
|
||||
@@ -286,13 +286,13 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
pkt.received = clock::now();
|
||||
onReceived(std::move(pkts));
|
||||
} else if (rc == -1) {
|
||||
if (logger)
|
||||
logger->e("Error receiving packet: %s", strerror(errno));
|
||||
int err = errno;
|
||||
if (logger)
|
||||
logger->e("Error receiving packet: %s", strerror(err));
|
||||
if (err == EPIPE || err == ENOTCONN || err == ECONNRESET) {
|
||||
if (not running)
|
||||
break;
|
||||
std::unique_lock<std::mutex> lk(lock, std::try_to_lock);
|
||||
std::unique_lock lk(lock, std::try_to_lock);
|
||||
if (lk.owns_lock()) {
|
||||
if (not running)
|
||||
break;
|
||||
@@ -337,7 +337,7 @@ UdpSocket::openSockets(const SockAddr& bind4, const SockAddr& bind6)
|
||||
close(stop_readfd);
|
||||
if (stopfd != -1)
|
||||
close(stopfd);
|
||||
std::unique_lock<std::mutex> lk(lock, std::try_to_lock);
|
||||
std::unique_lock lk(lock, std::try_to_lock);
|
||||
if (lk.owns_lock()) {
|
||||
s4 = -1;
|
||||
s6 = -1;
|
||||
|
||||
@@ -59,8 +59,12 @@ unpackTid(const msgpack::object& o)
|
||||
switch (o.type) {
|
||||
case msgpack::type::POSITIVE_INTEGER:
|
||||
return o.as<Tid>();
|
||||
default:
|
||||
return ntohl(*reinterpret_cast<const uint32_t*>(o.as<std::array<char, 4>>().data()));
|
||||
default: {
|
||||
auto arr = o.as<std::array<char, 4>>();
|
||||
uint32_t val;
|
||||
std::memcpy(&val, arr.data(), sizeof(val));
|
||||
return ntohl(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -123,7 +123,7 @@ PeerDiscovery::DomainPeerDiscovery::~DomainPeerDiscovery()
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::startDiscovery(std::string_view type, ServiceDiscoveredCallback callback)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
callbackmap_[std::string(type)] = callback;
|
||||
if (not drunning_) {
|
||||
drunning_ = true;
|
||||
@@ -137,7 +137,7 @@ PeerDiscovery::DomainPeerDiscovery::startDiscovery(std::string_view type, Servic
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::loopListener()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
if (not drunning_)
|
||||
return;
|
||||
sockFd_.async_receive_from(asio::buffer(receiveBuf_),
|
||||
@@ -163,7 +163,7 @@ PeerDiscovery::DomainPeerDiscovery::loopListener()
|
||||
continue;
|
||||
ServiceDiscoveredCallback cb;
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
if (drunning_) {
|
||||
auto callback = callbackmap_.find(o.key.as<std::string_view>());
|
||||
if (callback != callbackmap_.end())
|
||||
@@ -189,7 +189,7 @@ PeerDiscovery::DomainPeerDiscovery::loopListener()
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::query(const asio::ip::udp::endpoint& peer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
if (not drunning_)
|
||||
return;
|
||||
|
||||
@@ -209,7 +209,7 @@ PeerDiscovery::DomainPeerDiscovery::query(const asio::ip::udp::endpoint& peer)
|
||||
void
|
||||
PeerDiscovery::DomainPeerDiscovery::publish(const asio::ip::udp::endpoint& peer)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
std::lock_guard lck(mtx_);
|
||||
if (not lrunning_)
|
||||
return;
|
||||
|
||||
@@ -229,7 +229,7 @@ PeerDiscovery::DomainPeerDiscovery::startPublish(std::string_view type, const ms
|
||||
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_);
|
||||
std::lock_guard lck(mtx_);
|
||||
messages_[std::string(type)] = std::move(pack_buf_c);
|
||||
reloadMessages();
|
||||
lrunning_ = true;
|
||||
@@ -239,7 +239,7 @@ PeerDiscovery::DomainPeerDiscovery::startPublish(std::string_view type, const ms
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopDiscovery(std::string_view type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
auto it = callbackmap_.find(type);
|
||||
if (it != callbackmap_.end()) {
|
||||
callbackmap_.erase(it);
|
||||
@@ -253,7 +253,7 @@ PeerDiscovery::DomainPeerDiscovery::stopDiscovery(std::string_view type)
|
||||
bool
|
||||
PeerDiscovery::DomainPeerDiscovery::stopPublish(std::string_view type)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
std::lock_guard lck(mtx_);
|
||||
auto it = messages_.find(type);
|
||||
if (it != messages_.end()) {
|
||||
messages_.erase(it);
|
||||
@@ -282,11 +282,11 @@ void
|
||||
PeerDiscovery::DomainPeerDiscovery::stop()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(dmtx_);
|
||||
std::lock_guard lck(dmtx_);
|
||||
stopDiscovery();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(mtx_);
|
||||
std::lock_guard lck(mtx_);
|
||||
stopPublish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,16 @@ struct Dht::SearchNode
|
||||
return last_get_reply + Node::NODE_EXPIRE_TIME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the token without refreshing last_get_reply,
|
||||
* so that periodic find_node/get requests still occur.
|
||||
*/
|
||||
void refreshToken(const Blob& tok)
|
||||
{
|
||||
if (not tok.empty() and tok.size() <= 64)
|
||||
token = tok;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const SearchNode& node)
|
||||
{
|
||||
s << "getStatus:" << node.getStatus.size() << " listenStatus:" << node.listenStatus.size()
|
||||
|
||||
+9
-141
@@ -96,37 +96,13 @@ SecureDht::secureType(ValueType&& type)
|
||||
return type;
|
||||
}
|
||||
|
||||
Sp<crypto::Certificate>
|
||||
SecureDht::getCertificate(const InfoHash& node) const
|
||||
{
|
||||
if (node == getId())
|
||||
return certificate_;
|
||||
auto it = nodesCertificates_.find(node);
|
||||
if (it == nodesCertificates_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Sp<crypto::PublicKey>
|
||||
SecureDht::getPublicKey(const InfoHash& node) const
|
||||
{
|
||||
if (node == getId())
|
||||
return certificate_->getSharedPublicKey();
|
||||
auto it = nodesPubKeys_.find(node);
|
||||
if (it == nodesPubKeys_.end())
|
||||
return nullptr;
|
||||
else
|
||||
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())
|
||||
auto it = nodesCertificates_.find(node);
|
||||
if (it == nodesCertificates_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
@@ -137,8 +113,8 @@ SecureDht::getPublicKey(const PkId& node) const
|
||||
{
|
||||
if (node == getLongId())
|
||||
return certificate_->getSharedPublicKey();
|
||||
auto it = nodesPubKeysLong_.find(node);
|
||||
if (it == nodesPubKeysLong_.end())
|
||||
auto it = nodesPubKeys_.find(node);
|
||||
if (it == nodesPubKeys_.end())
|
||||
return nullptr;
|
||||
else
|
||||
return it->second;
|
||||
@@ -191,85 +167,10 @@ void
|
||||
SecureDht::registerCertificate(const Sp<crypto::Certificate>& cert)
|
||||
{
|
||||
if (cert) {
|
||||
nodesCertificates_[cert->getId()] = cert;
|
||||
nodesCertificatesLong_[cert->getLongId()] = cert;
|
||||
nodesCertificates_[cert->getLongId()] = cert;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findCertificate(const InfoHash& 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.toString());
|
||||
if (cb)
|
||||
cb(b);
|
||||
return;
|
||||
}
|
||||
if (localQueryMethodLegacy_) {
|
||||
auto res = localQueryMethodLegacy_(node);
|
||||
if (not res.empty()) {
|
||||
if (logger_)
|
||||
logger_->debug("Registering certificate from local store for {}", node.toString());
|
||||
nodesCertificates_.emplace(node, res.front());
|
||||
nodesCertificatesLong_.emplace(res.front()->getLongId(), res.front());
|
||||
if (cb)
|
||||
cb(res.front());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto found = std::make_shared<bool>(false);
|
||||
dht_->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.toString());
|
||||
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 InfoHash& 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.toString());
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (cb)
|
||||
cb(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::findCertificate(const PkId& node, const std::function<void(const Sp<crypto::Certificate>)>& cb)
|
||||
{
|
||||
@@ -287,8 +188,7 @@ SecureDht::findCertificate(const PkId& node, const std::function<void(const Sp<c
|
||||
if (not res.empty()) {
|
||||
if (logger_)
|
||||
logger_->debug("Registering certificate from local store for {}", node.to_c_str());
|
||||
nodesCertificates_.emplace(res.front()->getId(), res.front());
|
||||
nodesCertificatesLong_.emplace(node, res.front());
|
||||
nodesCertificates_.emplace(node, res.front());
|
||||
if (cb)
|
||||
cb(res.front());
|
||||
return;
|
||||
@@ -333,8 +233,7 @@ SecureDht::findPublicKey(const PkId& node, const std::function<void(const Sp<cry
|
||||
if (crt && *crt) {
|
||||
auto pk = crt->getSharedPublicKey();
|
||||
if (*pk) {
|
||||
nodesPubKeys_[pk->getId()] = pk;
|
||||
nodesPubKeysLong_[pk->getLongId()] = pk;
|
||||
nodesPubKeys_[pk->getLongId()] = pk;
|
||||
if (cb)
|
||||
cb(pk);
|
||||
return;
|
||||
@@ -362,8 +261,7 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
if (auto decrypted_val = v->decrypt(*key_)) {
|
||||
auto cacheValue = not isDecrypted and decrypted_val->owner;
|
||||
if (cacheValue) {
|
||||
nodesPubKeys_[decrypted_val->owner->getId()] = decrypted_val->owner;
|
||||
nodesPubKeysLong_[decrypted_val->owner->getLongId()] = decrypted_val->owner;
|
||||
nodesPubKeys_[decrypted_val->owner->getLongId()] = decrypted_val->owner;
|
||||
}
|
||||
return decrypted_val;
|
||||
}
|
||||
@@ -377,8 +275,7 @@ SecureDht::checkValue(const Sp<Value>& v)
|
||||
auto cacheValue = not v->isSignatureChecked() and enableCache_ and v->owner;
|
||||
if (v->checkSignature()) {
|
||||
if (cacheValue) {
|
||||
nodesPubKeys_[v->owner->getId()] = v->owner;
|
||||
nodesPubKeysLong_[v->owner->getLongId()] = v->owner;
|
||||
nodesPubKeys_[v->owner->getLongId()] = v->owner;
|
||||
}
|
||||
return v;
|
||||
} else if (logger_)
|
||||
@@ -492,35 +389,6 @@ SecureDht::putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback,
|
||||
Where().id(val->id));
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& 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->getId().toString());
|
||||
try {
|
||||
dht_->put(hash, encrypt(*val, *pk), callback, time_point::max(), permanent);
|
||||
} catch (const std::exception& e) {
|
||||
if (logger_)
|
||||
logger_->error("Error putting encrypted data: {}", e.what());
|
||||
if (callback)
|
||||
callback(false, {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
SecureDht::putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent)
|
||||
{
|
||||
|
||||
+5
-1
@@ -78,6 +78,8 @@ ThreadPool::run(std::function<void()>&& cb)
|
||||
break;
|
||||
task = std::move(tasks_.front());
|
||||
tasks_.pop();
|
||||
if (tasks_.empty() && stopping_)
|
||||
stopCv_.notify_one();
|
||||
}
|
||||
|
||||
// run task
|
||||
@@ -135,7 +137,9 @@ ThreadPool::stop(bool wait)
|
||||
{
|
||||
std::unique_lock l(lock_);
|
||||
if (wait) {
|
||||
cv_.wait(l, [&]() { return tasks_.empty(); });
|
||||
stopping_ = true;
|
||||
stopCv_.wait(l, [&]() { return tasks_.empty(); });
|
||||
stopping_ = false;
|
||||
}
|
||||
running_ = false;
|
||||
tasks_ = {};
|
||||
|
||||
+7
-1
@@ -85,7 +85,7 @@ ValueType::DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const
|
||||
size_t
|
||||
Value::size() const
|
||||
{
|
||||
return cypher.size() + data.size() + signature.size() + user_type.size();
|
||||
return cypher.size() + data.size() + signature.size() + user_type.size() + pushType.size();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -104,9 +104,14 @@ Value::msgpack_unpack(const msgpack::object& o)
|
||||
} else
|
||||
throw msgpack::type_error();
|
||||
|
||||
priority = 0;
|
||||
pushType.clear();
|
||||
if (auto rprio = findMapValue(o, VALUE_KEY_PRIO)) {
|
||||
priority = rprio->as<unsigned>();
|
||||
}
|
||||
if (auto rpt = findMapValue(o, VALUE_KEY_PUSHTYPE)) {
|
||||
pushType = rpt->as<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -261,6 +266,7 @@ Value::encrypt(const crypto::PrivateKey& from, const crypto::PublicKey& to)
|
||||
sign(from);
|
||||
Value nv {id};
|
||||
nv.priority = priority;
|
||||
nv.pushType = pushType;
|
||||
nv.setCypher(to.encrypt(getToEncrypt()));
|
||||
return nv;
|
||||
}
|
||||
|
||||
+15
-15
@@ -57,11 +57,11 @@ DhtProxyTester::tearDown()
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
nodeProxy->shutdown([&] {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 15s, [&] { return done; }));
|
||||
serverProxy.reset();
|
||||
nodeProxy.reset();
|
||||
@@ -81,11 +81,11 @@ DhtProxyTester::testGetPut()
|
||||
auto val_data = val.data;
|
||||
{
|
||||
nodePeer.put(key, std::move(val), [&](bool) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return done; }));
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ DhtProxyTester::testListen()
|
||||
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
auto key = dht::InfoHash::get("GLaDOs");
|
||||
bool done = false;
|
||||
|
||||
@@ -111,7 +111,7 @@ DhtProxyTester::testListen()
|
||||
auto firstVal_data = firstVal.data;
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool ok) {
|
||||
CPPUNIT_ASSERT(ok);
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
@@ -121,7 +121,7 @@ DhtProxyTester::testListen()
|
||||
std::vector<dht::Blob> values;
|
||||
auto token = nodeClient.listen(key, [&](const std::vector<std::shared_ptr<dht::Value>>& v, bool expired) {
|
||||
if (not expired) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
for (const auto& value : v)
|
||||
values.emplace_back(value->data);
|
||||
done = true;
|
||||
@@ -156,7 +156,7 @@ DhtProxyTester::testResubscribeGetValues()
|
||||
bool done = false;
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
auto key = dht::InfoHash::get("GLaDOs");
|
||||
|
||||
// If a peer sent a value, the listen operation from the client
|
||||
@@ -164,7 +164,7 @@ DhtProxyTester::testResubscribeGetValues()
|
||||
dht::Value firstVal {"Hey! It's been a long time. How have you been?"};
|
||||
auto firstVal_data = firstVal.data;
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool ok) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
CPPUNIT_ASSERT(ok);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
@@ -186,7 +186,7 @@ DhtProxyTester::testResubscribeGetValues()
|
||||
std::vector<std::shared_ptr<dht::Value>> values;
|
||||
auto ftoken = nodeClient.listen(key, [&](const std::vector<std::shared_ptr<dht::Value>>& v, bool expired) {
|
||||
if (not expired) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
values.insert(values.end(), v.begin(), v.end());
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
@@ -218,14 +218,14 @@ DhtProxyTester::testPutGet40KChars()
|
||||
mtu.emplace_back((i % 2) ? 'T' : 'M');
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
bool done_put = false;
|
||||
bool done_get = false;
|
||||
|
||||
// Act
|
||||
dht::Value val {mtu};
|
||||
nodePeer.put(key, std::move(val), [&](bool ok) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done_put = ok;
|
||||
cv.notify_all();
|
||||
});
|
||||
@@ -238,7 +238,7 @@ DhtProxyTester::testPutGet40KChars()
|
||||
return true;
|
||||
},
|
||||
[&](bool ok) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done_get = ok;
|
||||
cv.notify_all();
|
||||
});
|
||||
@@ -316,12 +316,12 @@ DhtProxyTester::testShutdownStop()
|
||||
std::mutex cv_m;
|
||||
nodeTest->shutdown(
|
||||
[&] {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
},
|
||||
true);
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return done; }));
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL(2 * C, callback_count.load());
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "test_dhtproxy_client.h"
|
||||
|
||||
#include <any>
|
||||
#include <mutex>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wkeyword-macro"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
#define private public
|
||||
#include "opendht/http.h"
|
||||
#include "opendht/dht_proxy_client.h"
|
||||
#undef private
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "../src/op_cache.cpp"
|
||||
#include "../src/dht_proxy_client.cpp"
|
||||
|
||||
namespace test {
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(DhtProxyClientTester);
|
||||
|
||||
using namespace dht;
|
||||
|
||||
void
|
||||
DhtProxyClientTester::testResubscribeUsesKeyRoute()
|
||||
{
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
DhtProxyClient client({}, {}, [] {}, "http://127.0.0.1:8080", "OpenDHT-Test", "client-id", "push-token");
|
||||
|
||||
DhtProxyClient::Listener listener {OpValueCache([](const std::vector<Sp<Value>>&, bool) { return true; })};
|
||||
listener.opstate = std::make_shared<DhtProxyClient::OperationState>();
|
||||
listener.cb = [](const std::vector<Sp<Value>>&, bool, system_clock::time_point) {
|
||||
return true;
|
||||
};
|
||||
|
||||
auto key = InfoHash::get("proxy-client-resubscribe");
|
||||
client.resubscribe(key, 1, listener);
|
||||
|
||||
CPPUNIT_ASSERT(listener.request);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("/key/") + key.toString(), std::string(listener.request->header_.request_target()));
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("\"refresh\"") != std::string::npos);
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("true") != std::string::npos);
|
||||
#else
|
||||
CPPUNIT_ASSERT(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DhtProxyClientTester::testSetPushNotificationTokenResubscribesWithNewToken()
|
||||
{
|
||||
#ifdef OPENDHT_PUSH_NOTIFICATIONS
|
||||
DhtProxyClient client({}, {}, [] {}, "http://127.0.0.1:8080", "OpenDHT-Test", "client-id", "old-token");
|
||||
|
||||
client.statusIpv4_ = NodeStatus::Connected;
|
||||
|
||||
auto key = InfoHash::get("proxy-client-token-rotation");
|
||||
auto& search = client.searches_[key];
|
||||
auto [it, inserted] = search.listeners.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(1),
|
||||
std::forward_as_tuple(OpValueCache(
|
||||
[](const std::vector<Sp<Value>>&, bool) { return true; })));
|
||||
CPPUNIT_ASSERT(inserted);
|
||||
|
||||
auto& listener = it->second;
|
||||
listener.opstate = std::make_shared<DhtProxyClient::OperationState>();
|
||||
listener.cb = [](const std::vector<Sp<Value>>&, bool, system_clock::time_point) {
|
||||
return true;
|
||||
};
|
||||
|
||||
client.setPushNotificationToken("new-token");
|
||||
|
||||
CPPUNIT_ASSERT(listener.request);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("/key/") + key.toString(), std::string(listener.request->header_.request_target()));
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("new-token") != std::string::npos);
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("old-token") == std::string::npos);
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("\"refresh\"") != std::string::npos);
|
||||
CPPUNIT_ASSERT(listener.request->body_.find("true") != std::string::npos);
|
||||
#else
|
||||
CPPUNIT_ASSERT(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#pragma once
|
||||
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
namespace test {
|
||||
|
||||
class DhtProxyClientTester : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(DhtProxyClientTester);
|
||||
CPPUNIT_TEST(testResubscribeUsesKeyRoute);
|
||||
CPPUNIT_TEST(testSetPushNotificationTokenResubscribesWithNewToken);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void testResubscribeUsesKeyRoute();
|
||||
void testSetPushNotificationTokenResubscribesWithNewToken();
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -51,11 +51,11 @@ DhtProxyStressTester::tearDown()
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
nodeProxy->shutdown([&] {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 15s, [&] { return done; }));
|
||||
serverProxy.reset();
|
||||
nodeProxy.reset();
|
||||
@@ -70,7 +70,7 @@ DhtProxyStressTester::testRepeatValues()
|
||||
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
auto key = dht::InfoHash::get("GLaDOs");
|
||||
bool done = false;
|
||||
|
||||
@@ -80,7 +80,7 @@ DhtProxyStressTester::testRepeatValues()
|
||||
auto firstVal_data = firstVal.data;
|
||||
nodePeer.put(key, std::move(firstVal), [&](bool ok) {
|
||||
CPPUNIT_ASSERT(ok);
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
@@ -90,7 +90,7 @@ DhtProxyStressTester::testRepeatValues()
|
||||
std::vector<dht::Blob> values;
|
||||
auto token = nodeClient.listen(key, [&](const std::vector<std::shared_ptr<dht::Value>>& v, bool expired) {
|
||||
if (not expired) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
for (const auto& value : v)
|
||||
values.emplace_back(value->data);
|
||||
done = true;
|
||||
@@ -132,7 +132,7 @@ DhtProxyStressTester::testRepeatValues()
|
||||
val->id = id++;
|
||||
nodePeer.put(key, val, [&](bool ok) {
|
||||
CPPUNIT_ASSERT(ok);
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
});
|
||||
@@ -145,7 +145,7 @@ DhtProxyStressTester::testRepeatValues()
|
||||
if (not expired) {
|
||||
for (const auto& value : v) {
|
||||
if (value->id == val->id) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
break;
|
||||
|
||||
+240
-27
@@ -6,6 +6,7 @@
|
||||
#include <opendht/thread_pool.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
using namespace std::chrono_literals;
|
||||
@@ -14,6 +15,14 @@ using namespace std::literals;
|
||||
namespace test {
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(DhtRunnerTester);
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
getFutureValue(std::future<T> future, std::chrono::steady_clock::duration timeout = 30s)
|
||||
{
|
||||
CPPUNIT_ASSERT(std::future_status::ready == future.wait_for(timeout));
|
||||
return future.get();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::setUp()
|
||||
{
|
||||
@@ -72,9 +81,10 @@ DhtRunnerTester::testGetPut()
|
||||
dht::Value val {"hey"};
|
||||
auto val_data = val.data;
|
||||
std::promise<bool> p;
|
||||
auto future = p.get_future();
|
||||
node2.put(key, std::move(val), [&](bool ok) { p.set_value(ok); });
|
||||
CPPUNIT_ASSERT(p.get_future().get());
|
||||
auto vals = node1.get(key).get();
|
||||
CPPUNIT_ASSERT(getFutureValue(std::move(future)));
|
||||
auto vals = getFutureValue(node1.get(key));
|
||||
CPPUNIT_ASSERT(not vals.empty());
|
||||
CPPUNIT_ASSERT(vals.front()->data == val_data);
|
||||
}
|
||||
@@ -88,13 +98,15 @@ DhtRunnerTester::testPutDuplicate()
|
||||
auto val_data = val->data;
|
||||
std::promise<bool> p1;
|
||||
std::promise<bool> p2;
|
||||
auto p1future = p1.get_future();
|
||||
auto p2future = p2.get_future();
|
||||
node2.put(key, val, [&](bool ok) { p1.set_value(ok); });
|
||||
node2.put(key, val, [&](bool ok) { p2.set_value(ok); });
|
||||
auto p1ret = p1.get_future().get();
|
||||
auto p2ret = p2.get_future().get();
|
||||
auto p1ret = getFutureValue(std::move(p1future));
|
||||
auto p2ret = getFutureValue(std::move(p2future));
|
||||
CPPUNIT_ASSERT(p1ret);
|
||||
CPPUNIT_ASSERT(p2ret);
|
||||
auto vals = node1.get(key).get();
|
||||
auto vals = getFutureValue(node1.get(key));
|
||||
CPPUNIT_ASSERT(not vals.empty());
|
||||
CPPUNIT_ASSERT(vals.size() == 1);
|
||||
CPPUNIT_ASSERT(vals.front()->data == val_data);
|
||||
@@ -112,13 +124,15 @@ DhtRunnerTester::testPutOverride()
|
||||
auto val_data = val2->data;
|
||||
std::promise<bool> p1;
|
||||
std::promise<bool> p2;
|
||||
auto p1future = p1.get_future();
|
||||
auto p2future = p2.get_future();
|
||||
node2.put(key, val, [&](bool ok) { p1.set_value(ok); });
|
||||
node2.put(key, val2, [&](bool ok) { p2.set_value(ok); });
|
||||
auto p1ret = p1.get_future().get();
|
||||
auto p2ret = p2.get_future().get();
|
||||
auto p1ret = getFutureValue(std::move(p1future));
|
||||
auto p2ret = getFutureValue(std::move(p2future));
|
||||
CPPUNIT_ASSERT(!p1ret);
|
||||
CPPUNIT_ASSERT(p2ret);
|
||||
auto vals = node1.get(key).get();
|
||||
auto vals = getFutureValue(node1.get(key));
|
||||
CPPUNIT_ASSERT(not vals.empty());
|
||||
CPPUNIT_ASSERT(vals.size() == 1);
|
||||
CPPUNIT_ASSERT(vals.front()->data == val_data);
|
||||
@@ -153,8 +167,9 @@ DhtRunnerTester::testImportValuesPreservesRemoteQuota()
|
||||
auto value2 = std::make_shared<dht::Value>(std::string(1024, 'b'));
|
||||
|
||||
std::promise<bool> p1;
|
||||
auto p1future = p1.get_future();
|
||||
node2.put(key1, value1, [&](bool ok) { p1.set_value(ok); });
|
||||
CPPUNIT_ASSERT(p1.get_future().get());
|
||||
CPPUNIT_ASSERT(getFutureValue(std::move(p1future)));
|
||||
|
||||
std::this_thread::sleep_for(2s);
|
||||
auto exported = node1.exportValues();
|
||||
@@ -179,13 +194,14 @@ DhtRunnerTester::testImportValuesPreservesRemoteQuota()
|
||||
std::this_thread::sleep_for(500ms);
|
||||
|
||||
std::promise<bool> p2;
|
||||
auto p2future = p2.get_future();
|
||||
node2.put(key2, value2, [&](bool ok) { p2.set_value(ok); });
|
||||
CPPUNIT_ASSERT(p2.get_future().get());
|
||||
CPPUNIT_ASSERT(getFutureValue(std::move(p2future)));
|
||||
|
||||
std::this_thread::sleep_for(2s);
|
||||
|
||||
auto vals1 = restored.get(key1).get();
|
||||
auto vals2 = restored.get(key2).get();
|
||||
auto vals1 = getFutureValue(restored.get(key1));
|
||||
auto vals2 = getFutureValue(restored.get(key2));
|
||||
CPPUNIT_ASSERT(vals1.size() + vals2.size() <= 1);
|
||||
|
||||
restored.shutdown();
|
||||
@@ -213,7 +229,9 @@ DhtRunnerTester::testImportValuesPreservesStoredExpiration()
|
||||
pk.pack_bin(0);
|
||||
pk.pack(expiration.time_since_epoch().count());
|
||||
|
||||
node1.importValues({dht::ValuesExport {key, {buffer.data(), buffer.data() + buffer.size()}}});
|
||||
node1.importValues({
|
||||
dht::ValuesExport {key, {buffer.data(), buffer.data() + buffer.size()}}
|
||||
});
|
||||
|
||||
auto exported = node1.exportValues();
|
||||
CPPUNIT_ASSERT(!exported.empty());
|
||||
@@ -244,6 +262,83 @@ DhtRunnerTester::testImportValuesPreservesStoredExpiration()
|
||||
restored.join();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::testImportPermanentValueExpires()
|
||||
{
|
||||
// Simulate importing a value that was originally stored as permanent
|
||||
// (expiration = time_point::max()). After import the permanent flag is lost,
|
||||
// so the value must expire within the type's normal expiration window.
|
||||
static const dht::ValueType SHORT_TYPE {201, "Short perm", 2s};
|
||||
|
||||
auto key = dht::InfoHash::get("import-permanent-expiration");
|
||||
auto now = dht::clock::now();
|
||||
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
pk.pack_array(1);
|
||||
pk.pack_array(4);
|
||||
pk.pack(now.time_since_epoch().count());
|
||||
dht::Value {SHORT_TYPE.id, std::string("was-permanent")}.msgpack_pack(pk);
|
||||
pk.pack_bin(0);
|
||||
// Permanent values are exported with time_point::max() expiration
|
||||
pk.pack(dht::clock::time_point::max().time_since_epoch().count());
|
||||
|
||||
dht::DhtRunner restored;
|
||||
dht::DhtRunner::Config config;
|
||||
config.dht_config.node_config.max_peer_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_store_size = -1;
|
||||
config.dht_config.node_config.max_store_keys = -1;
|
||||
restored.run(0, config);
|
||||
|
||||
restored.importValues({
|
||||
dht::ValuesExport {key, {buffer.data(), buffer.data() + buffer.size()}}
|
||||
});
|
||||
|
||||
// Value should be present right after import
|
||||
auto exportedBefore = restored.exportValues();
|
||||
CPPUNIT_ASSERT(!exportedBefore.empty());
|
||||
|
||||
// Wait longer than the default USER_DATA expiration (10 min) is not
|
||||
// practical, but the type is unregistered so the default 10 min expiration
|
||||
// applies. Instead, register the short type so the cap uses 2 s.
|
||||
// Re-import into a fresh node that knows the short type.
|
||||
dht::DhtRunner restored2;
|
||||
restored2.run(0, config);
|
||||
restored2.registerInsecureType(SHORT_TYPE);
|
||||
restored2.importValues({
|
||||
dht::ValuesExport {key, {buffer.data(), buffer.data() + buffer.size()}}
|
||||
});
|
||||
|
||||
CPPUNIT_ASSERT(!restored2.exportValues().empty());
|
||||
|
||||
// Wait for the short expiration to pass
|
||||
std::this_thread::sleep_for(3s);
|
||||
|
||||
auto restoredValues = restored2.exportValues();
|
||||
bool found = false;
|
||||
for (const auto& ve : restoredValues) {
|
||||
if (ve.first == key) {
|
||||
msgpack::unpacked msg;
|
||||
msgpack::unpack(msg, (const char*) ve.second.data(), ve.second.size());
|
||||
auto valarr = msg.get();
|
||||
CPPUNIT_ASSERT(valarr.type == msgpack::type::ARRAY);
|
||||
// The value should have expired
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t(0), valarr.via.array.size);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
// Either the key was cleaned up entirely or it was found with 0 values
|
||||
CPPUNIT_ASSERT(found || restoredValues.empty()
|
||||
|| std::none_of(restoredValues.begin(), restoredValues.end(),
|
||||
[&](const auto& ve) { return ve.first == key; }));
|
||||
|
||||
restored.shutdown();
|
||||
restored.join();
|
||||
restored2.shutdown();
|
||||
restored2.join();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::testBootstrapSetsConnectingState()
|
||||
{
|
||||
@@ -264,8 +359,9 @@ DhtRunnerTester::testBootstrapSetsConnectingState()
|
||||
|
||||
dht::DhtRunner::Context context;
|
||||
context.statusChangedCallback = [&](dht::NodeStatus status4, dht::NodeStatus status6) {
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
sawConnecting = sawConnecting || status4 == dht::NodeStatus::Connecting || status6 == dht::NodeStatus::Connecting;
|
||||
std::lock_guard lock(mutex);
|
||||
sawConnecting = sawConnecting || status4 == dht::NodeStatus::Connecting
|
||||
|| status6 == dht::NodeStatus::Connecting;
|
||||
cv.notify_all();
|
||||
};
|
||||
|
||||
@@ -278,10 +374,12 @@ DhtRunnerTester::testBootstrapSetsConnectingState()
|
||||
if (bound.isUnspecified())
|
||||
bound.setLoopback();
|
||||
|
||||
clientNode.bootstrap("127.0.0.1", std::to_string(bound.getPort()).c_str());
|
||||
clientNode.bootstrap("127.0.0.1", std::to_string(bound.getPort()));
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lock, 5s, [&] { return sawConnecting; }));
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lock, 5s, [&] { return sawConnecting; }));
|
||||
}
|
||||
|
||||
bootstrapNode.shutdown();
|
||||
bootstrapNode.join();
|
||||
@@ -315,10 +413,13 @@ DhtRunnerTester::testBootstrapThenPutNoRace()
|
||||
clientNode.bootstrap(bound);
|
||||
|
||||
std::promise<bool> putDone;
|
||||
clientNode.put(dht::InfoHash::get("bootstrap-then-put"), dht::Value {"value"}, [&](bool ok) { putDone.set_value(ok); });
|
||||
CPPUNIT_ASSERT(putDone.get_future().get());
|
||||
auto putFuture = putDone.get_future();
|
||||
clientNode.put(dht::InfoHash::get("bootstrap-then-put"), dht::Value {"value"}, [&](bool ok) {
|
||||
putDone.set_value(ok);
|
||||
});
|
||||
CPPUNIT_ASSERT(getFutureValue(std::move(putFuture)));
|
||||
|
||||
auto vals = bootstrapNode.get(dht::InfoHash::get("bootstrap-then-put")).get();
|
||||
auto vals = getFutureValue(bootstrapNode.get(dht::InfoHash::get("bootstrap-then-put")));
|
||||
CPPUNIT_ASSERT(!vals.empty());
|
||||
|
||||
bootstrapNode.shutdown();
|
||||
@@ -327,6 +428,118 @@ DhtRunnerTester::testBootstrapThenPutNoRace()
|
||||
clientNode.join();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::testBootstrapMissingNodeThenPutFails()
|
||||
{
|
||||
node1.shutdown();
|
||||
node1.join();
|
||||
node2.shutdown();
|
||||
node2.join();
|
||||
|
||||
dht::DhtRunner::Config config;
|
||||
config.dht_config.node_config.max_peer_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_store_size = -1;
|
||||
config.dht_config.node_config.max_store_keys = -1;
|
||||
|
||||
auto getUnusedPort = [&]() {
|
||||
dht::DhtRunner tmpNode;
|
||||
tmpNode.run(0, config);
|
||||
auto port = tmpNode.getBoundPort();
|
||||
tmpNode.shutdown();
|
||||
tmpNode.join();
|
||||
return port;
|
||||
};
|
||||
|
||||
auto missingPort = getUnusedPort();
|
||||
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
bool sawConnecting {false};
|
||||
bool sawDisconnectedAfterConnecting {false};
|
||||
bool putReturnedBeforeDisconnect {false};
|
||||
|
||||
dht::DhtRunner::Context context;
|
||||
context.statusChangedCallback = [&](dht::NodeStatus status4, dht::NodeStatus status6) {
|
||||
std::lock_guard lock(mutex);
|
||||
if (status4 == dht::NodeStatus::Connecting || status6 == dht::NodeStatus::Connecting)
|
||||
sawConnecting = true;
|
||||
if (sawConnecting && status4 == dht::NodeStatus::Disconnected && status6 == dht::NodeStatus::Disconnected)
|
||||
sawDisconnectedAfterConnecting = true;
|
||||
cv.notify_all();
|
||||
};
|
||||
|
||||
dht::DhtRunner clientNode;
|
||||
clientNode.run(0, config, std::move(context));
|
||||
while (clientNode.getBoundPort() == missingPort)
|
||||
missingPort = getUnusedPort();
|
||||
|
||||
std::promise<bool> putDone;
|
||||
auto putFuture = putDone.get_future();
|
||||
|
||||
clientNode.bootstrap("127.0.0.1", std::to_string(missingPort));
|
||||
clientNode.put(dht::InfoHash::get("bootstrap-missing-put"), dht::Value {"value"}, [&](bool ok) {
|
||||
std::lock_guard lock(mutex);
|
||||
putReturnedBeforeDisconnect = !sawDisconnectedAfterConnecting;
|
||||
putDone.set_value(ok);
|
||||
cv.notify_all();
|
||||
});
|
||||
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
CPPUNIT_ASSERT(cv.wait_for(lock, 10s, [&] { return sawConnecting; }));
|
||||
CPPUNIT_ASSERT(cv.wait_for(lock, 20s, [&] { return sawDisconnectedAfterConnecting; }));
|
||||
}
|
||||
CPPUNIT_ASSERT(std::future_status::ready == putFuture.wait_for(20s));
|
||||
CPPUNIT_ASSERT(!putFuture.get());
|
||||
CPPUNIT_ASSERT(!putReturnedBeforeDisconnect);
|
||||
|
||||
clientNode.shutdown();
|
||||
clientNode.join();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::testShutdownCompletesWithPendingPut()
|
||||
{
|
||||
node1.shutdown();
|
||||
node1.join();
|
||||
node2.shutdown();
|
||||
node2.join();
|
||||
|
||||
dht::DhtRunner::Config config;
|
||||
config.dht_config.node_config.max_peer_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_req_per_sec = -1;
|
||||
config.dht_config.node_config.max_store_size = -1;
|
||||
config.dht_config.node_config.max_store_keys = -1;
|
||||
|
||||
auto getUnusedPort = [&]() {
|
||||
dht::DhtRunner tmpNode;
|
||||
tmpNode.run(0, config);
|
||||
auto port = tmpNode.getBoundPort();
|
||||
tmpNode.shutdown();
|
||||
tmpNode.join();
|
||||
return port;
|
||||
};
|
||||
|
||||
auto missingPort = getUnusedPort();
|
||||
|
||||
dht::DhtRunner clientNode;
|
||||
clientNode.run(0, config);
|
||||
while (clientNode.getBoundPort() == missingPort)
|
||||
missingPort = getUnusedPort();
|
||||
|
||||
clientNode.bootstrap("127.0.0.1", std::to_string(missingPort));
|
||||
clientNode.put(dht::InfoHash::get("shutdown-pending-put"), dht::Value {"value"}, [](bool) {});
|
||||
|
||||
std::promise<void> shutdownDone;
|
||||
auto shutdownFuture = shutdownDone.get_future();
|
||||
clientNode.shutdown([&]() { shutdownDone.set_value(); });
|
||||
|
||||
CPPUNIT_ASSERT(std::future_status::ready == shutdownFuture.wait_for(5s));
|
||||
|
||||
clientNode.join();
|
||||
}
|
||||
|
||||
void
|
||||
DhtRunnerTester::testListen()
|
||||
{
|
||||
@@ -426,9 +639,9 @@ DhtRunnerTester::testListen()
|
||||
CPPUNIT_ASSERT(ftokenc.valid());
|
||||
CPPUNIT_ASSERT(ftokend.valid());
|
||||
|
||||
auto tokena = ftokena.get();
|
||||
auto tokenc = ftokenc.get();
|
||||
auto tokend = ftokend.get();
|
||||
auto tokena = getFutureValue(std::move(ftokena));
|
||||
auto tokenc = getFutureValue(std::move(ftokenc));
|
||||
auto tokend = getFutureValue(std::move(ftokend));
|
||||
// tokenb might be 0 since the callback returns false.
|
||||
|
||||
CPPUNIT_ASSERT(tokena);
|
||||
@@ -468,7 +681,7 @@ DhtRunnerTester::testIdOps()
|
||||
};
|
||||
|
||||
node2.join();
|
||||
node2.run(42232, config2, std::move(context2));
|
||||
node2.run(0, config2, std::move(context2));
|
||||
auto bound = node1.getBound();
|
||||
if (bound.isUnspecified())
|
||||
bound.setLoopback();
|
||||
@@ -502,7 +715,7 @@ DhtRunnerTester::testIdOps()
|
||||
|
||||
config2.dht_config.id = dht::crypto::generateIdentity();
|
||||
node1.join();
|
||||
node1.run(42222, config2, std::move(context1));
|
||||
node1.run(0, config2, std::move(context1));
|
||||
bound = node2.getBound();
|
||||
if (bound.isUnspecified())
|
||||
bound.setLoopback();
|
||||
@@ -634,7 +847,7 @@ DhtRunnerTester::testListenLotOfBytes()
|
||||
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return valueCount == N; }));
|
||||
}
|
||||
|
||||
node3.cancelListen(foo, ftokenfoo.get());
|
||||
node3.cancelListen(foo, getFutureValue(std::move(ftokenfoo)));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -22,8 +22,11 @@ class DhtRunnerTester : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testIdOps);
|
||||
CPPUNIT_TEST(testImportValuesPreservesRemoteQuota);
|
||||
CPPUNIT_TEST(testImportValuesPreservesStoredExpiration);
|
||||
CPPUNIT_TEST(testImportPermanentValueExpires);
|
||||
CPPUNIT_TEST(testBootstrapSetsConnectingState);
|
||||
CPPUNIT_TEST(testBootstrapThenPutNoRace);
|
||||
CPPUNIT_TEST(testBootstrapMissingNodeThenPutFails);
|
||||
CPPUNIT_TEST(testShutdownCompletesWithPendingPut);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
dht::DhtRunner node1 {};
|
||||
@@ -64,8 +67,11 @@ public:
|
||||
void testIdOps();
|
||||
void testImportValuesPreservesRemoteQuota();
|
||||
void testImportValuesPreservesStoredExpiration();
|
||||
void testImportPermanentValueExpires();
|
||||
void testBootstrapSetsConnectingState();
|
||||
void testBootstrapThenPutNoRace();
|
||||
void testBootstrapMissingNodeThenPutFails();
|
||||
void testShutdownCompletesWithPendingPut();
|
||||
/**
|
||||
* Test listen method with lot of datas
|
||||
*/
|
||||
|
||||
+5
-5
@@ -338,7 +338,7 @@ HttpTester::test_send_json()
|
||||
// Arrange
|
||||
std::condition_variable cv;
|
||||
std::mutex cv_m;
|
||||
std::unique_lock<std::mutex> lk(cv_m);
|
||||
std::unique_lock lk(cv_m);
|
||||
bool done = false;
|
||||
unsigned int status = 0;
|
||||
|
||||
@@ -350,7 +350,7 @@ HttpTester::test_send_json()
|
||||
"http://127.0.0.1:8080/key/key",
|
||||
json,
|
||||
[&](Json::Value value, const dht::http::Response& response) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
resp_val = std::move(value);
|
||||
status = response.status_code;
|
||||
done = true;
|
||||
@@ -368,7 +368,7 @@ HttpTester::test_send_json()
|
||||
request = std::make_shared<dht::http::Request>(serverProxy->io_context(),
|
||||
"http://google.ca",
|
||||
[&](const dht::http::Response& response) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
status = response.status_code;
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
@@ -382,7 +382,7 @@ HttpTester::test_send_json()
|
||||
request = std::make_shared<dht::http::Request>(serverProxy->io_context(),
|
||||
"https://google.ca",
|
||||
[&](const dht::http::Response& response) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
status = response.status_code;
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
@@ -396,7 +396,7 @@ HttpTester::test_send_json()
|
||||
request = std::make_shared<dht::http::Request>(serverProxy->io_context(),
|
||||
"https://google.ca/sdbjklwGBIP",
|
||||
[&](const dht::http::Response& response) {
|
||||
std::lock_guard<std::mutex> lk(cv_m);
|
||||
std::lock_guard lk(cv_m);
|
||||
status = response.status_code;
|
||||
done = true;
|
||||
cv.notify_all();
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
|
||||
#include "test_networkengine.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
namespace test {
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(NetworkEngineTester);
|
||||
|
||||
void
|
||||
NetworkEngineTester::setUp()
|
||||
{}
|
||||
|
||||
void
|
||||
NetworkEngineTester::tearDown()
|
||||
{}
|
||||
|
||||
void
|
||||
NetworkEngineTester::testDisabledOnMsvc()
|
||||
{
|
||||
CPPUNIT_ASSERT(true);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
#else
|
||||
|
||||
#include <any>
|
||||
#include <mutex>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef opendht_EXPORTS
|
||||
#undef opendht_EXPORTS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "opendht/node.h"
|
||||
#include "opendht/network_engine.h"
|
||||
#include "opendht/network_utils.h"
|
||||
@@ -29,6 +61,9 @@
|
||||
#include "../src/search.h"
|
||||
|
||||
// Hack to test internal classes
|
||||
#include "../src/op_cache.cpp"
|
||||
#include "../src/routing_table.cpp"
|
||||
#include "../src/dht.cpp"
|
||||
#include "../src/node.cpp"
|
||||
#include "../src/node_cache.cpp"
|
||||
#include "../src/network_engine.cpp"
|
||||
@@ -352,6 +387,53 @@ NetworkEngineTester::testListenConfirmationCarriesToken()
|
||||
CPPUNIT_ASSERT(reply.token == responseToken);
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngineTester::testListenConfirmationUpdatesSearchNodeToken()
|
||||
{
|
||||
Config config {};
|
||||
config.max_req_per_sec = -1;
|
||||
config.max_peer_req_per_sec = -1;
|
||||
|
||||
auto rd = std::make_unique<std::mt19937_64>(6);
|
||||
Dht localDht(std::make_unique<TestDatagramSocket>(), config, {}, std::move(rd));
|
||||
|
||||
auto node = std::make_shared<Node>(InfoHash::getRandom(localDht.rd),
|
||||
makeIPv4("127.0.0.2", 5006),
|
||||
localDht.rd,
|
||||
false);
|
||||
auto sr = std::make_shared<Dht::Search>();
|
||||
auto query = std::make_shared<Query>();
|
||||
ValueCallback valueCallback = [](const std::vector<std::shared_ptr<Value>>&, bool) {
|
||||
return true;
|
||||
};
|
||||
|
||||
sr->id = InfoHash::getRandom(localDht.rd);
|
||||
sr->af = AF_INET;
|
||||
sr->nextSearchStep = localDht.scheduler.add(time_point::max(), [] {});
|
||||
sr->listeners.emplace(1, Dht::Search::SearchListener {query, valueCallback, {}});
|
||||
|
||||
auto searchNode = std::make_unique<Dht::SearchNode>(node);
|
||||
auto socketId = node->openSocket([](const Sp<Node>&, net::RequestAnswer&&) {});
|
||||
searchNode->listenStatus.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(query),
|
||||
std::forward_as_tuple(valueCallback, dht::SyncCallback {}, socketId));
|
||||
auto* searchNodePtr = sr->nodes.emplace_back(std::move(searchNode)).get();
|
||||
|
||||
CPPUNIT_ASSERT(searchNodePtr->token.empty());
|
||||
CPPUNIT_ASSERT(!searchNodePtr->isSynced(localDht.scheduler.time()));
|
||||
|
||||
net::RequestAnswer answer {};
|
||||
answer.ntoken = Blob {0xaa, 0xbb, 0xcc, 0xdd};
|
||||
|
||||
localDht.onListenDone(node, answer, sr);
|
||||
|
||||
CPPUNIT_ASSERT(searchNodePtr->token == answer.ntoken);
|
||||
/* last_get_reply should NOT be updated by listen confirmation,
|
||||
so that periodic find_node requests still refresh the search table. */
|
||||
CPPUNIT_ASSERT(searchNodePtr->last_get_reply == time_point::min());
|
||||
CPPUNIT_ASSERT(!searchNodePtr->isSynced(localDht.scheduler.time()));
|
||||
}
|
||||
|
||||
void
|
||||
NetworkEngineTester::testListenReopensSocketAfterNodeExpiration()
|
||||
{
|
||||
@@ -404,4 +486,66 @@ NetworkEngineTester::testListenReopensSocketAfterNodeExpiration()
|
||||
CPPUNIT_ASSERT(node->getSocket(listenIt->second.socketId));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
void
|
||||
NetworkEngineTester::testUnauthorizedListenFlushClearsListenState()
|
||||
{
|
||||
Config config {};
|
||||
config.max_req_per_sec = -1;
|
||||
config.max_peer_req_per_sec = -1;
|
||||
|
||||
auto rd = std::make_unique<std::mt19937_64>(5);
|
||||
Dht localDht(std::make_unique<TestDatagramSocket>(), config, {}, std::move(rd));
|
||||
|
||||
auto node = std::make_shared<Node>(InfoHash::getRandom(localDht.rd),
|
||||
makeIPv4("127.0.0.2", 5005),
|
||||
localDht.rd,
|
||||
false);
|
||||
auto sr = std::make_shared<Dht::Search>();
|
||||
auto query = std::make_shared<Query>();
|
||||
ValueCallback valueCallback = [](const std::vector<std::shared_ptr<Value>>&, bool) {
|
||||
return true;
|
||||
};
|
||||
dht::SyncCallback syncCallback {};
|
||||
|
||||
sr->id = InfoHash::getRandom(localDht.rd);
|
||||
sr->af = AF_INET;
|
||||
|
||||
auto searchNode = std::make_unique<Dht::SearchNode>(node);
|
||||
auto socketId = node->openSocket([](const Sp<Node>&, net::RequestAnswer&&) {});
|
||||
auto listenIt = searchNode->listenStatus
|
||||
.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(query),
|
||||
std::forward_as_tuple(valueCallback, syncCallback, socketId))
|
||||
.first;
|
||||
listenIt->second.req = std::make_shared<net::Request>();
|
||||
listenIt->second.refresh = localDht.scheduler.add(localDht.scheduler.time() + std::chrono::seconds(1), [] {});
|
||||
searchNode->token = Blob {0x10, 0x11, 0x12};
|
||||
searchNode->last_get_reply = localDht.scheduler.time();
|
||||
auto* searchNodePtr = sr->nodes.emplace_back(std::move(searchNode)).get();
|
||||
|
||||
localDht.searches(AF_INET).emplace(sr->id, sr);
|
||||
|
||||
auto failingReq = std::make_shared<net::Request>(
|
||||
MessageType::Listen,
|
||||
node->getNewTid(),
|
||||
node,
|
||||
Blob {},
|
||||
[](const net::Request&, ParsedMessage&&) {},
|
||||
[](const net::Request&, bool) {});
|
||||
|
||||
localDht.onError(failingReq,
|
||||
net::DhtProtocolException {net::DhtProtocolException::UNAUTHORIZED,
|
||||
net::DhtProtocolException::LISTEN_WRONG_TOKEN});
|
||||
|
||||
CPPUNIT_ASSERT(searchNodePtr->token.empty());
|
||||
CPPUNIT_ASSERT(searchNodePtr->last_get_reply == time_point::min());
|
||||
|
||||
auto listenStatusIt = searchNodePtr->listenStatus.find(query);
|
||||
CPPUNIT_ASSERT(listenStatusIt != searchNodePtr->listenStatus.end());
|
||||
CPPUNIT_ASSERT(!listenStatusIt->second.req);
|
||||
CPPUNIT_ASSERT(!listenStatusIt->second.refresh);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
#endif
|
||||
@@ -10,22 +10,34 @@ namespace test {
|
||||
class NetworkEngineTester : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(NetworkEngineTester);
|
||||
#ifdef _MSC_VER
|
||||
CPPUNIT_TEST(testDisabledOnMsvc);
|
||||
#else
|
||||
CPPUNIT_TEST(testIgnoresUnknownPartialData);
|
||||
CPPUNIT_TEST(testCompletesPartialSessionFromSameSource);
|
||||
CPPUNIT_TEST(testKeepsSessionForWrongSourceFragment);
|
||||
CPPUNIT_TEST(testListenConfirmationCarriesToken);
|
||||
CPPUNIT_TEST(testListenConfirmationUpdatesSearchNodeToken);
|
||||
CPPUNIT_TEST(testListenReopensSocketAfterNodeExpiration);
|
||||
CPPUNIT_TEST(testUnauthorizedListenFlushClearsListenState);
|
||||
#endif
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void testDisabledOnMsvc();
|
||||
#else
|
||||
void testIgnoresUnknownPartialData();
|
||||
void testCompletesPartialSessionFromSameSource();
|
||||
void testKeepsSessionForWrongSourceFragment();
|
||||
void testListenConfirmationCarriesToken();
|
||||
void testListenConfirmationUpdatesSearchNodeToken();
|
||||
void testListenReopensSocketAfterNodeExpiration();
|
||||
void testUnauthorizedListenFlushClearsListenState();
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -54,7 +54,7 @@ PeerDiscoveryTester::testMulticastToTwoNodes()
|
||||
unsigned countDht {0};
|
||||
unsigned countJami {0};
|
||||
{
|
||||
std::unique_lock<std::mutex> l(lock);
|
||||
std::unique_lock l(lock);
|
||||
dht::PeerDiscovery testDht(MULTICAST_PORT);
|
||||
dht::PeerDiscovery testJami(MULTICAST_PORT);
|
||||
|
||||
@@ -63,7 +63,7 @@ PeerDiscoveryTester::testMulticastToTwoNodes()
|
||||
CPPUNIT_ASSERT_EQUAL(dhtNode.nodeid, v.nodeid);
|
||||
CPPUNIT_ASSERT_EQUAL(dhtNode.nid, v.nid);
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lock);
|
||||
std::lock_guard l(lock);
|
||||
countDht++;
|
||||
}
|
||||
cv.notify_all();
|
||||
@@ -75,7 +75,7 @@ PeerDiscoveryTester::testMulticastToTwoNodes()
|
||||
CPPUNIT_ASSERT_EQUAL(jamiNode.cha, v.cha);
|
||||
CPPUNIT_ASSERT_EQUAL(jamiNode.str, v.str);
|
||||
{
|
||||
std::lock_guard<std::mutex> l(lock);
|
||||
std::lock_guard l(lock);
|
||||
countJami++;
|
||||
}
|
||||
cv.notify_all();
|
||||
|
||||
@@ -80,6 +80,46 @@ ThreadPoolTester::testContext()
|
||||
CPPUNIT_ASSERT_EQUAL(N, count.load());
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::testJoinNonEmptyTaskQueue()
|
||||
{
|
||||
dht::ThreadPool pool(2);
|
||||
|
||||
constexpr unsigned N = 128;
|
||||
std::atomic_uint count {0};
|
||||
|
||||
// Schedule enough work so that the task queue is non-empty when calling
|
||||
// pool.join() below.
|
||||
for (unsigned i = 0; i < N; i++)
|
||||
pool.run([&] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
count++;
|
||||
});
|
||||
|
||||
std::atomic_bool joined {false};
|
||||
std::condition_variable cv;
|
||||
std::thread joinThread([&] {
|
||||
CPPUNIT_ASSERT(count.load() < N);
|
||||
pool.join();
|
||||
joined = true;
|
||||
cv.notify_one();
|
||||
});
|
||||
|
||||
// After calling join(), all pending tasks should complete, and then all
|
||||
// threads in the pool should join.
|
||||
std::mutex mtx;
|
||||
std::unique_lock lock(mtx);
|
||||
bool poolJoined = cv.wait_for(lock, std::chrono::seconds(10), [&] { return joined.load(); });
|
||||
if (!poolJoined) {
|
||||
// Detach joinThread if we timed out, otherwise the test can crash.
|
||||
joinThread.detach();
|
||||
} else {
|
||||
joinThread.join();
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE("Some tasks were not completed", N, count.load());
|
||||
CPPUNIT_ASSERT_MESSAGE("Thread pool failed to join before timeout", poolJoined);
|
||||
}
|
||||
|
||||
void
|
||||
ThreadPoolTester::tearDown()
|
||||
{}
|
||||
|
||||
@@ -14,6 +14,7 @@ class ThreadPoolTester : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testThreadPool);
|
||||
CPPUNIT_TEST(testExecutor);
|
||||
CPPUNIT_TEST(testContext);
|
||||
CPPUNIT_TEST(testJoinNonEmptyTaskQueue);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -29,6 +30,7 @@ public:
|
||||
void testThreadPool();
|
||||
void testExecutor();
|
||||
void testContext();
|
||||
void testJoinNonEmptyTaskQueue();
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
// opendht
|
||||
#include "opendht/value.h"
|
||||
#include "opendht/crypto.h"
|
||||
#include <msgpack.hpp>
|
||||
|
||||
namespace test {
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(ValueTester);
|
||||
@@ -59,4 +61,80 @@ ValueTester::testFilter()
|
||||
void
|
||||
ValueTester::tearDown()
|
||||
{}
|
||||
|
||||
void
|
||||
ValueTester::testPushTypeMsgpackRoundTrip()
|
||||
{
|
||||
dht::Value original {(const uint8_t*) "hello", 5};
|
||||
original.id = 42;
|
||||
original.priority = 3;
|
||||
original.pushType = "audioCall";
|
||||
|
||||
msgpack::sbuffer buffer;
|
||||
msgpack::packer<msgpack::sbuffer> pk(&buffer);
|
||||
original.msgpack_pack(pk);
|
||||
|
||||
msgpack::unpacked msg;
|
||||
msgpack::unpack(msg, buffer.data(), buffer.size());
|
||||
dht::Value restored(msg.get());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(original.id, restored.id);
|
||||
CPPUNIT_ASSERT_EQUAL(original.priority, restored.priority);
|
||||
CPPUNIT_ASSERT_EQUAL(original.pushType, restored.pushType);
|
||||
}
|
||||
|
||||
void
|
||||
ValueTester::testPushTypeAbsentAfterUnpack()
|
||||
{
|
||||
dht::Value withPt {(const uint8_t*) "data", 4};
|
||||
withPt.id = 1;
|
||||
withPt.pushType = "videoCall";
|
||||
withPt.priority = 2;
|
||||
|
||||
msgpack::sbuffer buf1;
|
||||
msgpack::packer<msgpack::sbuffer> pk1(&buf1);
|
||||
withPt.msgpack_pack(pk1);
|
||||
|
||||
msgpack::unpacked msg1;
|
||||
msgpack::unpack(msg1, buf1.data(), buf1.size());
|
||||
|
||||
dht::Value reused;
|
||||
reused.msgpack_unpack(msg1.get());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("videoCall"), reused.pushType);
|
||||
CPPUNIT_ASSERT_EQUAL(2u, reused.priority);
|
||||
|
||||
dht::Value plain {(const uint8_t*) "data", 4};
|
||||
plain.id = 2;
|
||||
|
||||
msgpack::sbuffer buf2;
|
||||
msgpack::packer<msgpack::sbuffer> pk2(&buf2);
|
||||
plain.msgpack_pack(pk2);
|
||||
|
||||
msgpack::unpacked msg2;
|
||||
msgpack::unpack(msg2, buf2.data(), buf2.size());
|
||||
|
||||
reused.msgpack_unpack(msg2.get());
|
||||
CPPUNIT_ASSERT_EQUAL(std::string(), reused.pushType);
|
||||
CPPUNIT_ASSERT_EQUAL(0u, reused.priority);
|
||||
}
|
||||
|
||||
void
|
||||
ValueTester::testPushTypePreservedAfterEncrypt()
|
||||
{
|
||||
auto key = dht::crypto::PrivateKey::generate();
|
||||
const auto& pubkey = key.getPublicKey();
|
||||
|
||||
dht::Value original {(const uint8_t*) "secret", 6};
|
||||
original.id = 99;
|
||||
original.priority = 1;
|
||||
original.pushType = "audioCall";
|
||||
|
||||
auto encrypted = original.encrypt(key, pubkey);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(original.pushType, encrypted.pushType);
|
||||
CPPUNIT_ASSERT_EQUAL(original.priority, encrypted.priority);
|
||||
CPPUNIT_ASSERT_EQUAL(original.id, encrypted.id);
|
||||
CPPUNIT_ASSERT(encrypted.isEncrypted());
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
@@ -13,6 +13,9 @@ class ValueTester : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST_SUITE(ValueTester);
|
||||
CPPUNIT_TEST(testConstructors);
|
||||
CPPUNIT_TEST(testFilter);
|
||||
CPPUNIT_TEST(testPushTypeMsgpackRoundTrip);
|
||||
CPPUNIT_TEST(testPushTypeAbsentAfterUnpack);
|
||||
CPPUNIT_TEST(testPushTypePreservedAfterEncrypt);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -32,6 +35,9 @@ public:
|
||||
* Test compare operators
|
||||
*/
|
||||
void testFilter();
|
||||
void testPushTypeMsgpackRoundTrip();
|
||||
void testPushTypeAbsentAfterUnpack();
|
||||
void testPushTypePreservedAfterEncrypt();
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
+1
-1
@@ -123,7 +123,7 @@ main(int argc, char** argv)
|
||||
iss >> idstr;
|
||||
std::getline(iss, line);
|
||||
dht.putEncrypted(room,
|
||||
InfoHash(idstr),
|
||||
PkId(idstr),
|
||||
dht::ImMessage(IdDist()(tools::rd), std::move(line), now),
|
||||
[](bool ok) {
|
||||
// dht.cancelPut(room, id);
|
||||
|
||||
+2
-2
@@ -481,7 +481,7 @@ cmd_loop(std::shared_ptr<DhtRunner>& node,
|
||||
auto value = std::make_shared<dht::Value>(dht::ValueType::USER_DATA.id,
|
||||
std::vector<uint8_t> {v.begin(), v.end()});
|
||||
value->user_type = "text/plain";
|
||||
node->putEncrypted(id, InfoHash(tostr), std::move(value), [start](bool ok) {
|
||||
node->putEncrypted(id, PkId(tostr), std::move(value), [start](bool ok) {
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Put encrypted: " << (ok ? "success" : "failure") << " (took "
|
||||
<< print_duration(end - start) << ')' << std::endl;
|
||||
@@ -649,7 +649,7 @@ main(int argc, char** argv)
|
||||
});
|
||||
|
||||
// wait for shutdown
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
std::unique_lock lk(m);
|
||||
cv.wait(lk, [&]() { return done; });
|
||||
|
||||
node->join();
|
||||
|
||||
@@ -126,7 +126,7 @@ main(int argc, char** argv)
|
||||
|
||||
{
|
||||
std::mutex m;
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
std::unique_lock lk(m);
|
||||
cv.wait(lk, [&]() { return done.load() == 0; });
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ benchPingPong(unsigned netSize, unsigned n_parallel)
|
||||
unsigned max = PINGPONG_MAX * n_parallel;
|
||||
|
||||
auto ping = [&](DhtRunner& node, InfoHash h) {
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
std::lock_guard lk(m);
|
||||
if (i < max) {
|
||||
i++;
|
||||
node.put(h, Value("hey"));
|
||||
@@ -93,7 +93,7 @@ benchPingPong(unsigned netSize, unsigned n_parallel)
|
||||
ping(pong_node, locs[i].first);
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m);
|
||||
std::unique_lock lk(m);
|
||||
if (not cv.wait_for(lk, std::chrono::minutes(1), [&]() { return i == max; })) {
|
||||
throw std::runtime_error(std::string("Timeout: ") + std::to_string(i));
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ struct ServiceRunner
|
||||
{
|
||||
bool wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m);
|
||||
std::unique_lock lock(m);
|
||||
cv.wait(lock, [&] { return terminate.load(); });
|
||||
return !terminate;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "opendht",
|
||||
"version-string": "3.7.3",
|
||||
"version-string": "4.0.0",
|
||||
"port-version": 1,
|
||||
"description": "OpenDHT: A lightweight C++17 Distributed Hash Table library.",
|
||||
"homepage": "https://opendht.net",
|
||||
|
||||
Reference in new issue
Block a user