Compare commits

...
2783 Commits
Author SHA1 Message Date
Adrien Beraud bb66dded17 build/cmake: set SIMDUTF_CXX_STANDARD to match CMAKE_CXX_STANDARD 2026-03-14 11:21:13 -04:00
Adrien Beraud 91d54d09d1 tests: unlock mutex before join 2026-03-14 11:20:44 -04:00
Adrien Béraud 4d0ecb8075 dht: expire requests on shutdown 2026-03-14 00:31:47 -04:00
Adrien Béraud b0f8526872 tests: add testShutdownCompletesWithPendingPut 2026-03-14 00:31:17 -04:00
Adrien Béraud 6dc004c338 net: forward length in write() on windows 2026-03-13 23:01:22 -04:00
Adrien Béraud 7183847e44 tests: use random ports 2026-03-13 22:59:41 -04:00
Adrien Béraud 884cb09220 tests: bound dhtrunner async waits 2026-03-13 22:00:09 -04:00
Adrien Béraud 04edaafa57 dht: simplify bootstrap logic 2026-03-13 20:59:24 -04:00
Adrien Béraud 6be58884aa tests: set timout for test_crypto to 60s 2026-03-13 20:58:53 -04:00
Adrien Béraud d50d3d4f32 tests: set timout for test_dhtrunner to 60s 2026-03-13 20:52:56 -04:00
Adrien Béraud 8acafe844d dht: release pending bootstrap after first attempt 2026-03-13 20:39:40 -04:00
Adrien Béraud 688b713c09 tests: cover bootstrap put failure after disconnect 2026-03-13 20:39:37 -04:00
Adrien Béraud 017df59dde update version to 3.7.6 2026-03-13 18:30:43 -04:00
Adrien Béraud 964800a506 tests: disable test_networkengine on MSVC 2026-03-13 16:30:36 -04:00
Adrien Béraud 4f423d066f tests: attempt to fix test_networkengine on MSVC 2026-03-13 16:09:49 -04:00
Adrien Béraud ae49b96c2d tests: attempt to fix test_networkengine on MSVC 2026-03-13 16:02:33 -04:00
Adrien Béraud 3701b21425 tests: attempt to fix test_networkengine on MSVC 2026-03-13 15:49:52 -04:00
Adrien Béraud 55af602026 tests: fix build with GCC 14 2026-03-13 15:32:45 -04:00
Adrien Béraud eda121297b proxy client: protect searches when updating push token 2026-03-13 15:10:12 -04:00
Adrien Béraud 603e777c9e dht: refresh token on listen confirmation 2026-03-13 15:10:12 -04:00
Adrien Béraud bef4e61fc6 tests: add test for update of listen token 2026-03-13 15:10:12 -04:00
Adrien Béraud 42971d9587 tests: add test for proxy client token change 2026-03-13 15:10:12 -04:00
Adrien Béraud 4a43326de1 tests: add more proxy tests 2026-03-13 13:06:36 -04:00
Adrien Béraud 8fcb19627d dht: mark listen as non-synced on auth failure 2026-03-13 13:06:08 -04:00
Adrien Béraud b6ea2ed8e2 proxy client: resubscribe on new endpoint 2026-03-13 13:05:34 -04:00
Adrien Béraud ac520bd587 tests: make sure bootstrap then put always succeed 2026-03-13 12:03:09 -04:00
Adrien Béraud 4bd796cddd dht: state is connecting if bootstrap is pending 2026-03-13 11:53:32 -04:00
Adrien Béraud ad372bf232 dht: restart searches on connect 2026-03-13 11:52:57 -04:00
Adrien Béraud 299b4510f5 AGENTS.md: add commit instructions 2026-03-13 11:07:01 -04:00
Adrien Béraud ae44ac98fb dht: open new socket if previous was closed 2026-03-13 11:06:50 -04:00
Adrien Béraud c37ff1b167 tests: add test for reopens socket after node expiration 2026-03-13 11:06:30 -04:00
Adrien Béraud f94f072ad6 dht: send token in listen confirmation 2026-03-13 00:53:05 -04:00
Adrien Béraud c51beca374 dht: properly persist expiration time 2026-03-13 00:38:31 -04:00
Adrien Béraud 4b9a6489c3 dht: persist storage usage 2026-03-13 00:28:38 -04:00
Adrien Béraud 34722cab7a dht: clarify storage log 2026-03-13 00:04:49 -04:00
Adrien Béraud 9e1dc3f793 dht: log stats about imported values 2026-03-13 00:04:49 -04:00
Adrien Béraud 0eacd7fe6c tools: move to dht::tools namespace 2026-03-13 00:04:49 -04:00
Adrien Béraud 37f4469961 update version to 3.7.3 2026-03-09 16:08:26 -04:00
Adrien Béraud e9c4a31949 Support listing tests and running a single test by name 2026-03-09 13:57:56 -04:00
dependabot[bot] 1b5d9569ec build(deps): bump pypa/cibuildwheel from 3.3.1 to 3.4.0
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.3.1...v3.4.0)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 10:35:40 -04:00
dependabot[bot] e70f76f7f9 build(deps): bump docker/setup-buildx-action from 3 to 4
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 10:34:43 -04:00
dependabot[bot] 0f25da371e build(deps): bump docker/setup-qemu-action from 3 to 4
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 10:33:43 -04:00
dependabot[bot] f33f66c038 build(deps): bump docker/login-action from 3 to 4
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 10:33:06 -04:00
dependabot[bot] 1d08ff1489 build(deps): bump docker/metadata-action from 5 to 6
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 10:32:35 -04:00
Adrien Béraud b892be092a infohash: make core APIs constexpr
Make Hash default constructor, hex constructor, data(), const
operator[] and fromString constexpr. Change fromString to be
non-throwing: it now uses a validity flag and fills the hash with zeros
on parse error instead of throwing. Add a constexpr toHexArray helper
that returns a std::array<char, N*2> for compile-time hex conversion.
Update tests to include <string_view>, use std::string_view, add
constexpr InfoHash usage and a static_assert for the hex array.
2026-03-08 23:34:50 -04:00
Adrien Béraud 9a902fa80c dht: fix incorrect id in log 2026-03-08 12:27:00 -04:00
Adrien Béraud 984d720fac meson: export opendht_EXPORTS 2026-03-08 12:26:23 -04:00
Adrien Béraud 931d79b701 dht: handle out-of-order partial messages 2026-03-08 12:26:23 -04:00
Adrien Béraud 58a5791063 ci: fix ccpp.yml syntax 2026-03-07 14:52:14 -05:00
Adrien Béraud 33b2bf12fa dht: fix recycling of existing search 2026-03-06 23:19:51 -05:00
Adrien Béraud 08e9f0b763 network_engine: always erase partial message after processing 2026-03-06 23:19:51 -05:00
Adrien Béraud 12cb93f9cf AGENTS.md: update 2026-03-06 23:19:51 -05:00
Adrien Béraud 71d14bb0fe proxy stats: use localhost by default 2026-03-02 16:32:38 -05:00
Adrien Béraud 635a73141a build/cmake: use three dots as policy_max separator 2026-03-01 21:39:53 -05:00
Adrien Béraud de4327c056 proxy stats: add storage stats 2026-02-27 16:52:07 -05:00
Adrien Béraud 348d6be920 proxy stats: add storage stats 2026-02-27 16:00:16 -05:00
Adrien Béraud dbdf2ba94d update version to 3.7.2 2026-02-27 15:27:44 -05:00
Adrien Béraud ef7505baaa tests/dhtrunner: adapt to use longId 2026-02-27 15:12:31 -05:00
Adrien Béraud 9ad6b3a608 dhtrunner, securedht: mark findCertificate(InfoHash hash) as deprecated 2026-02-27 14:26:39 -05:00
Adrien Béraud a32d76d312 securedht: cleanup 2026-02-27 00:18:20 -05:00
Adrien Béraud 8ebecfa25a securedht: stop storing certificate at sha1(publicKey) 2026-02-27 00:12:40 -05:00
Adrien Béraud ae3c2ae0d3 build/meson: use c++20 by default 2026-02-26 22:53:06 -05:00
Adrien Béraud 808ef0c51e rename tests to test_x format 2026-02-26 22:52:48 -05:00
Adrien Béraud 6cf6892767 add AGENTS.md 2026-02-26 22:51:41 -05:00
Adrien Béraud 9ebe6e8bb6 tools: pretty print byte count 2026-02-24 00:15:47 -05:00
Adrien Béraud a5455c19a6 update version to 3.7.1 2026-02-22 23:34:54 -05:00
Adrien Béraud 166566dbf4 remove automake files 2026-02-22 23:34:16 -05:00
Adrien Béraud 9b1534e6fe update README.md 2026-02-22 21:42:24 -05:00
Adrien Béraud 0263104373 proxy client: implement getLocalStoreSize 2026-02-22 18:55:02 -05:00
Adrien Béraud 0fc7e451e6 dhtrunner: move getNodeInfo implementation to securedht 2026-02-22 17:16:28 -05:00
Adrien Béraud 85cbee0f1a dht: add local storage stats in NodeInfo 2026-02-22 16:27:35 -05:00
Adrien Béraud 724b5e592e dht: use independent storage quota for local values 2026-02-22 16:27:35 -05:00
Adrien Béraud 28001840fa dht: avoid infinite loop when largest quota empty
Ensure the selected store_quota entry is non-empty before entering the
expiry loop. If an empty entry is encountered, log a warning and break
out to prevent repeatedly attempting to expire from an empty quota
(which could hang the expiry routine).
2026-02-21 18:34:07 -05:00
Adrien Béraud 047c10cf85 dht: handle empty values when updating storage quota 2026-02-21 18:34:00 -05:00
Adrien Béraud 152f9a2f54 dht: take shared_ptr by const-ref in sortedBucketInsert 2026-02-19 22:02:32 -05:00
Adrien Béraud 62243fb4f6 query: optimize msgpack_pack 2026-02-19 21:50:07 -05:00
Adrien Béraud 01eab83a7b value: move filter 2026-02-19 21:44:43 -05:00
Adrien Béraud 2c71662af7 dht_proxy_client: prevent disconnect on local ip change 2026-02-09 15:05:43 -05:00
Adrien Béraud 64032eb6d2 utils: use fmt::format for getaddrinfo error
Use fmt::format to build the std::invalid_argument message in
SockAddr::resolve
instead of manual std::string concatenation when getaddrinfo fails.
2026-02-09 13:26:02 -05:00
Adrien Béraud d91f3bdbbd dhtrunner: implement getStorageLimit 2026-02-09 13:26:00 -05:00
Adrien Béraud 1abaddba3e ci: bump VCPKG_VERSION to 2026.01.16
Bump VCPKG_VERSION in .github/workflows/windows-build.yml from
2025.07.25 to 2026.01.16 so the Windows CI workflow uses the newer
vcpkg release.
2026-02-05 21:53:28 -05:00
Adrien Béraud 65b537f6e9 ci: test builds with C++17/20/23
Add a cxx_standard matrix (17, 20, 23) to the Ubuntu and macOS CI jobs
and pass
-DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} and
-DCMAKE_CXX_STANDARD_REQUIRED=ON to CMake so the builds are exercised
across
C++17, C++20 and C++23.
2026-02-05 21:53:14 -05:00
Adrien Béraud f44646ff82 ci(windows): test builds with C++17/20/23 standards
Add a cxx_standard matrix axis to the Windows build jobs and pass
-DCMAKE_CXX_STANDARD and -DCMAKE_CXX_STANDARD_REQUIRED=ON to CMake so
builds are produced for C++17, C++20 and C++23. Include the chosen
standard in the uploaded artifact names for both shared and static
builds.
2026-02-05 21:34:44 -05:00
Adrien Béraud 73dc55155e utils: make unpackMsg take const Blob& and inline
Change the template unpackMsg to accept a const Blob& to avoid an
unnecessary copy of the Blob argument. Move the non-template unpackMsg
(returning msgpack::unpacked) into the header as an inline function and
remove its out-of-line definition from src/utils.cpp. Update
declarations accordingly.
2026-02-05 21:31:42 -05:00
Adrien Béraud aa000ee586 http: cleanup 2026-02-05 21:31:42 -05:00
Adrien Béraud ec4c3e343c dht: format request targets with fmt 2026-02-05 21:31:42 -05:00
copilot-swe-agent[bot]andaberaud 4b24f1da38 Replace deprecated systemd directives with current alternatives
Replace ReadOnlyDirectories with ReadOnlyPaths and ReadWriteDirectories with ReadWritePaths as per modern systemd.exec(5) documentation

Co-authored-by: aberaud <101827+aberaud@users.noreply.github.com>
2026-02-03 16:35:58 -05:00
dependabot[bot] c47048121b build(deps): bump https://github.com/microsoft/vcpkg
Bumps [https://github.com/microsoft/vcpkg](https://github.com/microsoft/vcpkg) from HEAD to 2026.01.16. This release includes the previously tagged commit.
- [Release notes](https://github.com/microsoft/vcpkg/releases)
- [Commits](https://github.com/microsoft/vcpkg/compare/dd3097e305afa53f7b4312371f62058d2e665320...66c0373dc7fca549e5803087b9487edfe3aca0a1)

---
updated-dependencies:
- dependency-name: https://github.com/microsoft/vcpkg
  dependency-version: 2026.01.16
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-02 09:33:51 -05:00
Adrien Béraud 638ffdc669 logger: add missing header 2026-01-29 22:55:47 -05:00
Adrien Béraud 40ffafa756 logger: use file and line number 2026-01-29 22:38:57 -05:00
Adrien Béraud e6836f076f logger: protect children with mutex 2026-01-29 22:38:31 -05:00
Adrien Béraud 03c1158d7e build: use /Zc:__cplusplus on MSVC 2026-01-27 16:09:07 -05:00
Adrien Béraud 0018e577d9 build: add simdutf to opendht.pc when downloaded 2026-01-27 15:07:15 -05:00
Adrien Béraud eb7d94ee79 Revert "build: add private link to simdutf static to pkgconfig"
This reverts commit ea6ca025fc.
2026-01-27 15:06:23 -05:00
Adrien Béraud ea6ca025fc build: add private link to simdutf static to pkgconfig 2026-01-27 14:45:07 -05:00
Adrien Béraud 1105a68f93 build: update simdutf to 8.0.0 2026-01-27 14:31:41 -05:00
Adrien Béraud 76ae1cd6f2 logger: make setFilter match substrings
Allow to filter based on partial tag match
2026-01-27 14:29:43 -05:00
Adrien Béraud c59c0ef64d log: add tag and filter mechanism 2026-01-26 17:31:37 -05:00
Adrien Béraud 1011d82b35 update version to 3.7.0 2026-01-21 15:41:12 -05:00
Adrien Béraud 29f87169f8 proxy server: use TLS 1.3 2026-01-21 15:29:25 -05:00
ovari 435ee9cbbc Create FUNDING.yml 2026-01-18 09:17:19 -05:00
Adrien Béraud 6f111bcc0c build/cmake: cleanup 2026-01-17 22:30:10 -05:00
Adrien Béraud f9cba71d51 Switch project license from GPL-3.0-or-later to MIT 2026-01-17 22:25:43 -05:00
Adrien Béraud 4fd4745647 update copyright to 2026 2026-01-17 17:09:06 -05:00
dependabot[bot] 7165a02aaf build(deps): bump pypa/cibuildwheel from 3.3.0 to 3.3.1
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.3.0...v3.3.1)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-13 21:43:51 -05:00
Andreas Hatziiliou fb34682e78 cleanup: deprecate autotools 2026-01-13 21:41:57 -05:00
Adrien Béraud db8ca78943 securedht: refactor lambda captures 2026-01-07 00:30:56 -05:00
Adrien Béraud da9360143d dht: fix typo in comment 2026-01-07 00:14:25 -05:00
Adrien Béraud f55884b7d3 utils: cleanup 2026-01-07 00:14:25 -05:00
Adrien Béraud d978b471a3 thread pool: cleanup 2026-01-07 00:14:25 -05:00
Maxim Cournoyer 4a6a7e3827 meson: Install headers.
Fixes: #820
2026-01-03 11:38:40 -05:00
Maxim Cournoyer d3e6788dc0 meson: Fix durl tool dependency on liburing.
Fixes: #819
2026-01-03 11:38:40 -05:00
dependabot[bot] e355e1fd5c build(deps): bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-29 14:28:28 -05:00
dependabot[bot] 5890971e1d build(deps): bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-29 14:28:01 -05:00
dependabot[bot] 512d81e0c0 build(deps): bump actions/download-artifact from 6 to 7
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-29 14:27:21 -05:00
Adrien Béraud c433fbe460 docker: don't build unit tests 2025-12-15 00:26:10 -05:00
Adrien Béraud 7f5d39ad36 ci/docker: add dependencies between jobs 2025-12-15 00:06:29 -05:00
Adrien Béraud 8c6dd935a9 ci: correct syntax error in clang-analyzer 2025-12-14 23:48:29 -05:00
Adrien Béraud 79d51e10ab ci: update dependencies 2025-12-14 23:29:08 -05:00
Adrien Béraud b582ced6da docker: update dependencies 2025-12-14 23:29:08 -05:00
copilot-swe-agent[bot]andaberaud c7079c7200 Add ARM64 support to Docker image builds
Co-authored-by: aberaud <101827+aberaud@users.noreply.github.com>
2025-12-14 23:28:58 -05:00
Adrien Beraud c60c6b8af2 update version to 3.6.2 2025-12-10 12:13:28 -05:00
Adrien Beraud 9f7e4aaa96 Revert "log: add tag and filter mechanism"
This reverts commit afce0fb0b4.
2025-12-10 12:12:05 -05:00
Adrien Béraud 0bfd3cd9fc network engine: check on_expired 2025-12-09 15:46:57 -05:00
Adrien Béraud 442e5501d8 build/meson: update 2025-12-09 15:22:45 -05:00
dependabot[bot] 0203bd8318 build(deps): bump alpine from 3.22 to 3.23 in /docker
Bumps alpine from 3.22 to 3.23.

---
updated-dependencies:
- dependency-name: alpine
  dependency-version: '3.23'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 10:44:45 -05:00
Adrien Béraud cd07d68bef crypto: only support webPush with GnuTLS 3.8.2+ 2025-12-09 10:39:58 -05:00
Adrien Béraud 88f3870f20 dhtrunner: add registerInsecureType method and header file 2025-12-09 09:43:30 -05:00
Adrien Béraud d9d2c44e0f format 2025-12-09 09:43:19 -05:00
Adrien Béraud f427f36d9c Add exceptions for missing owner or recipient in unpackValue methods 2025-12-09 09:43:19 -05:00
Adrien Béraud a1c881d914 network engine: replace lambda with direct on_expired callback 2025-12-09 09:42:52 -05:00
Adrien Béraud fbc489863f http: use string_view for resolver, url 2025-12-02 22:28:32 -05:00
Adrien Béraud 504a3638d9 proxy server: add support for encrypted WebPush 2025-12-02 22:28:32 -05:00
Adrien Béraud a85abccd62 proxy server: improve unifiedpush support 2025-12-01 22:20:37 -05:00
Adrien Béraud afce0fb0b4 log: add tag and filter mechanism 2025-12-01 22:20:37 -05:00
Adrien Béraud 99f0334229 http: improve Url parsing 2025-11-30 12:40:17 -05:00
Lucas Fryzek 55ac11bf5c Modify UnifiedPush post request to be AND_3 compliant 2025-11-30 10:54:18 -05:00
Adrien Béraud e028c1be8c update version to 3.6.0 2025-11-26 14:03:56 -05:00
Adrien Béraud 3e8d9835d4 utils: various fixes to build with c++23 2025-11-26 14:03:56 -05:00
Adrien Béraud 18df23bd50 build/cmake: support c++ other than 17 2025-11-26 14:03:56 -05:00
Adrien Béraud 6b8c3ea581 base64: use simdutf 2025-11-26 14:01:45 -05:00
dependabot[bot] 7645f284e4 build(deps): bump pypa/cibuildwheel from 3.2.1 to 3.3.0
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.2.1 to 3.3.0.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-25 10:54:55 -05:00
dependabot[bot] 2cec478dfc build(deps): bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-25 10:54:00 -05:00
Adrien Béraud 54f07e449c pkgconfig: link with fmt 2025-11-19 11:20:40 -05:00
Adrien Béraud 09308321f8 network_utils: cleanup 2025-11-19 11:20:02 -05:00
Adrien Béraud e4b333b672 add clang-format 2025-11-19 11:20:02 -05:00
Adrien Béraud 69f382449d add .vscode settings 2025-11-19 11:19:55 -05:00
Adrien Beraud 47d2f41930 proxy client: check for null resolver 2025-11-17 12:56:36 -05:00
ovari d6b124eec0 Update BUILD.md 2025-11-16 17:35:19 -05:00
ovari 0330ee6683 Update BUILD.md 2025-11-16 17:35:19 -05:00
Jean-Charles de Longueville 1b854b8a09 Update BUILD.md from reviewer's comments 2025-11-16 16:50:04 -05:00
Jean-Charles de Longueville 4f6c561540 Update BUILD.md: typo 2025-11-16 16:50:04 -05:00
Jean-Charles de Longueville 79ffe663f6 Update BUILD.md: add debian 13 trixie instructions 2025-11-16 16:50:04 -05:00
dependabot[bot] a14a97e3a2 build(deps): bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-28 10:20:24 -04:00
dependabot[bot] bddc34d47b build(deps): bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-28 10:19:46 -04:00
kestrel de6ea1d632 Add support for io_uring for Autotools builds.
* configure.ac (liburing): Add --with-liburing option, tests for liburing.
* src/Makefile.am (libopendht_la_CPPFLAGS, libopendht_la_LIBS): Add relevant compiler and linker flags.
2025-10-15 15:13:19 -04:00
kestrel 1d2fd80fad Use pkg-config to test for llhttp for Autotools builds.
* configure.ac (llhttp_lib): Replaces existing tests with PKG_CHECK_MODULES.
* src/Makefile.am (libopendht_la_CPPFLAGS, libopendht_la_LIBS): Add relevant compiler and linker flags.
2025-10-15 15:13:19 -04:00
SASANO Takayoshi f7df3413e1 CMakeLists.txt: revise libreadline check on OpenBSD 2025-10-15 15:12:17 -04:00
SASANO Takayoshi 4cb67002e3 CMakeLists.txt: fix -lreadline not found error 2025-10-15 15:12:17 -04:00
SASANO Takayoshi 197a9a6bcd CMakeLists.txt: fix 'install TARGETS RUNTIME_DEPENDENCY_SET is not supported' 2025-10-15 15:12:17 -04:00
SASANO Takayoshi 8641de139d CMakeLists.txt: avoid libreadline check on OpenBSD 2025-10-15 15:12:17 -04:00
dependabot[bot] adcb61bbf9 build(deps): bump pypa/cibuildwheel from 3.2.0 to 3.2.1
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.2.0 to 3.2.1.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.2.0...v3.2.1)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-15 15:11:09 -04:00
dependabot[bot] 70709c9a68 build(deps): bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-15 15:10:42 -04:00
kestrel bf930de9e4 configure.ac: Fix llhttplib substituion.
* configure.ac (@http_lib@): Rename to llhttp_lib, replace the substituted value for a pkg-config module name.
2025-10-13 14:35:28 -04:00
Adrien Beraud bb4e716fc7 README: add pypi badge 2025-10-10 13:59:44 -04:00
Adrien Beraud 54fd6cf64f securedht: avoid calling identity announced callback multiple times 2025-10-10 13:59:44 -04:00
dependabot[bot] d905a02b32 build(deps): bump pypa/cibuildwheel from 3.1.4 to 3.2.0
Bumps [pypa/cibuildwheel](https://github.com/pypa/cibuildwheel) from 3.1.4 to 3.2.0.
- [Release notes](https://github.com/pypa/cibuildwheel/releases)
- [Changelog](https://github.com/pypa/cibuildwheel/blob/main/docs/changelog.md)
- [Commits](https://github.com/pypa/cibuildwheel/compare/v3.1.4...v3.2.0)

---
updated-dependencies:
- dependency-name: pypa/cibuildwheel
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-10 11:11:56 -04:00
Adrien Béraud d12f9271b8 pht: use const reference for IndexEntry::TYPE
Prevents static initialization order issue
2025-09-22 14:41:22 -04:00
Adrien Béraud 3639d651a2 docker: add alpine edge container 2025-09-22 14:41:22 -04:00
Adrien Béraud 07824391a2 update version to 3.5.5 2025-09-22 14:41:22 -04:00
Adrien Béraud c855f495d0 ci/release: remove reference to removed artifact 2025-09-19 00:59:28 -04:00
Adrien Béraud cc5c148fc1 python: repair python installation with cmake 2025-09-19 00:41:18 -04:00
Adrien Béraud 949751f632 crypto: disable Oaep test for win32 2025-09-18 23:39:38 -04:00
Adrien Béraud 6dfc4e4ba1 ci: don't build with documentation on Windows/MSVC 2025-09-18 23:19:35 -04:00
Adrien Béraud db8d62e17b ci: don't build with documentation on Windows/MSVC 2025-09-18 23:02:22 -04:00
Adrien Béraud 7226775987 crypto: disable Oaep test for win32 2025-09-18 22:26:50 -04:00
Adrien Béraud 9c264e1cad python: add debug information for python install 2025-09-18 22:19:41 -04:00
Adrien Béraud deee57b6dd ci/github: call ctest directly 2025-09-14 18:27:19 -04:00
Adrien Béraud 95f0b27eae cmake: build tests as separate executables 2025-09-14 17:55:59 -04:00
ovari b6f98a8488 Update crypto.cpp 2025-09-14 13:38:35 -04:00
ovari 73acc27a11 Update CheckAtomic.cmake 2025-09-14 13:38:35 -04:00
ovari d46e302b3f Update network_engine.h 2025-09-14 13:38:35 -04:00
ovari 6f57e03b48 Update network_engine.h 2025-09-14 13:38:35 -04:00
ovari a5e39768e4 Update securedht.cpp 2025-09-14 13:38:35 -04:00
ovari 6f6fdba8dd Update value.cpp 2025-09-14 13:38:35 -04:00
ovari e5ef0a8900 Update dhtrunner.h 2025-09-14 13:38:35 -04:00
ovari b6f21933ab Update securedht.h 2025-09-14 13:38:35 -04:00
ovari e4b8b0259d Update http.cpp 2025-09-14 13:38:35 -04:00
ovari 8134d6201a Update network_engine.cpp 2025-09-14 13:38:35 -04:00
ovari db4cd7dcc1 Update peer_discovery.cpp 2025-09-14 13:38:35 -04:00
ovari 9d6107c01c Update storage.h 2025-09-14 13:38:35 -04:00
ovari de46d55b13 Update crypto.cpp
“ !” → “.”
bits → bit
can’t → unable to
wrong → incorrect
2025-09-14 13:38:35 -04:00
Adrien Béraud 75afd9d9dc ci/msvc: build without documentation 2025-09-14 13:36:45 -04:00
Adrien Beraud 99c56d13bb crypto: fix build on GnuTLS 3.8.3 and bellow 2025-09-08 16:38:25 -04:00
Adrien Béraud 95fa29d2ec securedht: add CertificateStoreQuery by PkId 2025-09-08 00:14:44 -04:00
Adrien Béraud f3d9d8414d crypto: add test for RSA OAEP 2025-09-07 23:45:40 -04:00
Adrien Béraud 0c9d715d6d crypto: allow to generate RSA OAEP private keys 2025-09-07 23:44:47 -04:00
Adrien Béraud cfff247e06 crypto: support RSA OAEP encryption and decryption 2025-09-07 22:15:00 -04:00
Adrien Béraud 04edc70fee dhtrunner: update documentation for join() 2025-09-06 17:14:10 -04:00
Adrien Béraud fdc4bdee68 ci: install cmake on Debian 12 2025-09-06 16:35:34 -04:00
Adrien Béraud 69bf7afe31 BUILD.md: add pkg-config and support for Debian 12 2025-09-06 16:33:48 -04:00
Adrien Béraud 7b3ee44175 ci: add proxy dependencies for Debian 12 2025-09-06 16:33:21 -04:00
Adrien Béraud 122c30cce8 ci: add Debian 12 2025-09-06 16:08:03 -04:00
Adrien Béraud 957e05319f BUILD.md: cleanup 2025-09-05 00:35:46 -04:00
Adrien Béraud 58f83ab3c6 build/cmake: python cleanup 2025-09-05 00:35:28 -04:00
Adrien Béraud 6151ee8c0b pyproject: remove unneeded install command 2025-09-04 23:23:27 -04:00
Adrien Béraud c08b6a7f5d add support for version 2025-09-04 23:22:34 -04:00
Adrien Béraud 0139e7a2d4 update README.md 2025-09-04 23:22:10 -04:00
Adrien Béraud 416de4b4f8 update version to 3.5.4 2025-09-02 23:52:56 -04:00
Adrien Béraud b45f32e8f8 README: update for new Python API 2025-09-02 23:51:36 -04:00
Adrien Béraud cda5b0afa2 python: update pingpong example for asyncio 2025-09-02 23:48:43 -04:00
Adrien Béraud f66a57b033 python: cleanup asynio layer 2025-09-02 23:48:34 -04:00
Adrien Béraud 72a688cd14 ci/release-package: remove deprecated python wheels build 2025-09-02 23:07:48 -04:00
Adrien Béraud e882efe89e build/cmake: use VCPKG_INSTALLED_DIR for python 2025-09-02 21:49:30 -04:00
Adrien Beraud 7b49ed873c build/python: install build for ci job 2025-09-02 19:49:02 -04:00
Adrien Béraud 3fec6e7636 pht: don't export IndexEntry::ValueType 2025-09-02 09:22:40 -04:00
Adrien Béraud 67ac7a4d86 python: update pingpong example for asyncio 2025-09-02 01:57:09 -04:00
Adrien Béraud 615534fa0f python: add initial asyncio implementation 2025-09-02 01:45:29 -04:00
Adrien Béraud 4250336951 .gitignore: add cmake files 2025-09-02 01:45:29 -04:00
Adrien Béraud 932cacbda3 python: use single to argument for putEncrypted 2025-09-02 01:40:28 -04:00
Adrien Béraud 3b254663ca build/python: install delvewheel from ci job 2025-09-02 01:37:59 -04:00
Adrien Béraud 18f74693e9 ci/github: merge windows python wheels 2025-09-01 21:06:11 -04:00
Adrien Béraud e0cc973aa4 build/cmake: enable python in full vcpkg preset 2025-09-01 20:17:42 -04:00
Adrien Béraud c866d46798 build/cmake: filter more windows dlls 2025-09-01 20:17:42 -04:00
Adrien Béraud c762e4e43f build/cmake: remove python from all taregts 2025-09-01 20:17:42 -04:00
Adrien Béraud 3eed83c22d ci/github: build windows python wheel 2025-09-01 20:17:42 -04:00
Adrien Béraud 234f47a018 python/setup.py: use appropriate flags for windows build 2025-09-01 20:17:42 -04:00
Adrien Béraud 615463e103 ci/python: add support for windows/msvc wheel build 2025-09-01 20:17:42 -04:00
Adrien Béraud d50585188d utils: add missing header 2025-09-01 19:42:41 -04:00
Adrien Béraud dd247d15ba python: call gnutls_global_init/gnutls_global_deinit on module load/unload 2025-09-01 19:40:20 -04:00
Adrien Béraud 4a34045c0f python/setup.py: add appropriate build definitions 2025-09-01 19:33:18 -04:00
Adrien Béraud edfdb39970 vcpkg: update description 2025-09-01 19:27:59 -04:00
Adrien Béraud 89551496c7 python: update readme 2025-08-31 00:21:46 -04:00
Adrien Beraud becb878f5f python: add bindings for sign, checkSignature 2025-08-31 00:04:00 -04:00
Adrien Beraud a94f99dcd2 python: add annotations and checks 2025-08-30 23:52:40 -04:00
Adrien Beraud 8de9584b72 dhtrunner: mark getId() deprecated 2025-08-30 22:20:32 -04:00
Adrien Beraud 303a3c2c5a python: unify putEncrypted 2025-08-30 22:18:49 -04:00
Adrien Beraud e6dcc3226d python: cleanup 2025-08-30 19:54:33 -04:00
Adrien Beraud ab71e5a59e python: add support for putEncrypted with PkId 2025-08-30 19:30:20 -04:00
Adrien Beraud bf9561c4af python: add binding for getLongId, getPublicKey 2025-08-30 19:27:57 -04:00
Adrien Beraud c139fc9791 python: add binding for PkId 2025-08-30 19:13:59 -04:00
dependabot[bot] 31ddf3cc27 build(deps): bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 10:50:51 -04:00
Adrien Béraud 1bbdc3e673 add BUILD.md 2025-08-24 20:05:55 -04:00
Adrien Béraud 60ecb95cf6 build/python: copy README.md to build dir 2025-08-24 16:01:29 -04:00
Adrien Béraud 075ea59244 build/cmake: fix including jsoncpp on linux 2025-08-24 15:52:39 -04:00
Adrien Béraud 2f98f1f987 ci/pipy: build for Python 13 2025-08-24 11:22:49 -04:00
Adrien Béraud 2b22fe9055 setup.py: update metadata 2025-08-24 11:22:32 -04:00
Adrien BéraudandCopilot Autofix powered by AI e144460869 Potential fix for code scanning alert no. 17: Workflow does not contain permissions
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-08-24 01:47:50 -04:00
Adrien Béraud 6b54c42fdb build python with appropriate flags for public dependencies 2025-08-24 01:47:50 -04:00
Adrien Béraud 57587b6cd8 build/cmake: improve msgpack lookup logic 2025-08-24 01:47:50 -04:00
Adrien Béraud 0fd642f92d ci: add python-wheels.yml 2025-08-24 01:47:50 -04:00
Adrien Béraud 91310c83a7 setup.py.in: remove unneeded cythonize 2025-08-24 01:47:50 -04:00
Adrien Béraud daf2f8edaf value: add OPENDHT_PUBLIC to default store policy 2025-08-24 01:25:47 -04:00
Adrien Béraud a957cdba86 python: update copyright 2025-08-18 09:58:54 -04:00
Adrien Béraud 5a9a8dc67a dependabot: add cargo ecosystem for rust 2025-08-18 09:58:52 -04:00
Adrien Béraud 5fe0dad574 build/python: replace calls to setup.py 2025-08-17 22:08:13 -04:00
Adrien Béraud a051b391a8 python: update setup.py to use a SPDX license expression 2025-08-17 00:17:14 -04:00
Adrien Béraud ec27ff6c49 docker: update for Ubuntu 24.04 2025-08-17 00:00:09 -04:00
Adrien Béraud 0e1042124e docker: update to Ubuntu 24.04, drop Ubuntu 18.04 2025-08-16 23:45:42 -04:00
dependabot[bot] f7e7101abc build(deps): bump alpine from 3.19 to 3.22 in /docker
Bumps alpine from 3.19 to 3.22.

---
updated-dependencies:
- dependency-name: alpine
  dependency-version: '3.22'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-16 23:30:13 -04:00
dependabot[bot] 26957ee632 build(deps): bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-16 23:29:14 -04:00
dependabot[bot] 04fa07edfe build(deps): bump actions/download-artifact from 4 to 5
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-16 23:28:15 -04:00
dependabot[bot] 6cf763dfa4 build(deps): bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-16 23:27:13 -04:00
Adrien Béraud c41e42e58c Create dependabot.yml 2025-08-16 23:20:39 -04:00
Adrien BéraudandCopilot Autofix powered by AI 1b238083d3 Potential fix for code scanning alert no. 7: Workflow does not contain permissions
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2025-08-16 22:12:56 -04:00
Adrien Béraud 0784270c2e ci/github: use codeql for github actions 2025-08-16 21:49:02 -04:00
Adrien Béraud e675bb62fd update version to 3.5.1 2025-08-16 21:34:13 -04:00
Adrien Béraud 43ac0e14e0 python: fix syntax error in setup.py.in 2025-08-16 21:22:57 -04:00
Adrien Béraud f4d494cb3d python: build inplace in build directory 2025-08-16 21:22:57 -04:00
Adrien Béraud b3dfbf13d8 tools: header cleanup 2025-08-16 21:22:57 -04:00
Adrien Béraud 93538e89c6 build/cmake: add appropriate llhttp flags to opendht.pc 2025-08-16 21:22:57 -04:00
Adrien Béraud 947e845dcd meson: require meson 1.1 2025-08-16 21:22:57 -04:00
Adrien Béraud 6b49de7e4b build/cmake: update presets 2025-08-16 21:22:57 -04:00
Adrien Béraud f6191fa2a5 devcontainer: update 2025-08-16 21:22:57 -04:00
Adrien Béraud b167887d51 build/cmake: move WIN32_WINNT version detection to dedicated script 2025-08-05 20:25:12 -04:00
Adrien Béraud 77769898ea ci/release: install wix 2025-08-04 09:45:43 -04:00
Adrien Béraud 42189e3cf7 build/cmake: cleanup 2025-08-04 09:45:29 -04:00
Adrien Béraud 73f8000e49 ci/release: build with cpack 2025-08-04 09:25:46 -04:00
Adrien Béraud 298e334482 build/cmake: always find asio by header 2025-08-04 09:25:32 -04:00
Adrien Béraud bb982b8cf9 build/cmake: always find asio by header 2025-08-04 09:15:40 -04:00
Adrien Béraud 80145c37bb build/cmake: enable OPENDHT_DOWNLOAD_DEPS by default 2025-08-04 09:15:19 -04:00
Adrien Béraud bc8503a21e ci/release: create vcpkg directories before install 2025-08-03 23:31:50 -04:00
Adrien Béraud 2947dbfe5f update version to 3.5.0 2025-08-03 23:25:57 -04:00
Adrien Béraud bf9ddfc72f build/cmake: add build presets 2025-08-03 23:25:43 -04:00
Adrien Béraud c848a7e70b ci/release: build static dhtnode 2025-08-03 22:53:00 -04:00
Adrien Béraud e7c5b0e36f ci/windows: use dependency cache 2025-08-03 22:48:48 -04:00
Adrien Béraud 41282c99f9 build/cmake: dhtscanner, dhtchat are examples 2025-08-03 22:31:43 -04:00
Adrien Béraud e25f6f131a build/vcpkg: update to 2025.07.25 2025-08-03 21:37:39 -04:00
Adrien Béraud e69f0fd01e ci/vcpkg: cache vcpkg binary output 2025-08-02 10:19:04 -04:00
Adrien Béraud 30c9534bc5 build/vcpkg: link to appropriate target for jsoncpp 2025-08-02 10:19:04 -04:00
Adrien Béraud 6d56fb7510 build/cmake: add vcpkg_manifest_static 2025-08-02 10:19:04 -04:00
Adrien Beraud e46d03b440 ci: enable back OPENDHT_DOWNLOAD_DEPS in CI 2025-07-21 16:30:57 -04:00
Adrien Beraud 8255596171 cmake: various fixes on Linux 2025-07-21 15:49:34 -04:00
Adrien Beraud baae3ba701 cmake/presets: build ninja with proxy 2025-07-21 13:28:36 -04:00
Maxim Cournoyer 6c43be2a03 configure.ac: Improve the error message when readline is missing.
* configure.ac[tools]: Mention that the requirement is due to the
tools.
2025-07-21 08:24:03 -04:00
Maxim Cournoyer ee4c8a19d6 configure.ac: Error out when doc is requested but Doxygen is missing.
Previously, documentation would be automatically disabled when Doxygen
was found missing.

* configure.ac: Change AC_MSG_WARN into AC_MSG_ERROR and adjust error
message.
2025-07-21 08:24:03 -04:00
Maxim Cournoyer e8cf9dd25f configure.ac: Make the Python option depend on the indexation option.
Mimic what is done already in the CMakeLists.txt file, with one
distinction: do not automagically turn on indexation when Python is
selected; rather, stop and tell the user that it is required for
Python support.  Remove the automatic downgrade to --disable-python
when Cython is not found.

* configure.ac: Enforce dependencies on indexation and Cython when
Python support is requested.
2025-07-21 08:24:03 -04:00
Maxim Cournoyer df21c4524c configure.ac: Fix the description of the '--without-openssl' option. 2025-07-21 08:24:03 -04:00
Maxim Cournoyer ccec6c2f67 replace usleep with nanosleep
* src/compat/msvc/unistd.h (usleep): Delete.
* tools/dhtcnode.c (main) <usleep>: Replace with nanosleep on non
Windows platform, or Sleep on Windows.

Fixes: #607
2025-07-20 22:25:28 -04:00
Adrien Béraud 5ab450491c Merge remote-tracking branch 'origin/master' into pulls/1772757862/750 2025-07-20 11:59:30 -04:00
Adrien Béraud 3b0cce8c25 Added and tested build scenarios for Windows (MSYS2, MSVC) 2025-07-20 11:55:40 -04:00
copilot-swe-agent[bot]andaberaud d6b6f30275 Replace hardcoded documentation path with CMAKE_INSTALL_DOCDIR
Co-authored-by: aberaud <101827+aberaud@users.noreply.github.com>
2025-07-19 23:08:08 -04:00
Adrien Béraud c9f18c8349 Pull Request #750: Added and tested build scenarios for Windows (MSYS2, MSVC) 2025-07-19 14:36:26 -04:00
Adrien Beraud df3186ad95 proxy server: export ServerStats 2025-07-16 11:29:18 -04:00
Andrey Vukolov 58956549b8 Merge branch 'savoirfairelinux:master' into winbuild 2025-07-15 16:47:24 +02:00
Adrien Beraud 74ed041791 tests/dhtrunner: create value as shared_ptr 2025-07-10 13:50:42 -04:00
Adrien Beraud 312f883387 proxy server: move ServerStats impl to cpp 2025-07-10 13:46:17 -04:00
Andrey Vukolov fad4093183 CI fix (squashed 17 commits) 2025-06-27 14:27:48 +02:00
Andrey Vukolov 5c005e097e Harmonizing CMakeLists 2025-06-26 16:20:27 +02:00
Andrey Vukolov 69f23e49c4 Preparing for rebase and merge #750
Addresses:
        - https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2157723135
        - https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2157794234
        - https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2157795386
        - https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2161542551
        - https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2161546768
2025-06-24 18:06:52 +02:00
Andrey Vukolov f53976dc2f Merge branch 'savoirfairelinux:master' into winbuild 2025-06-23 10:34:11 +02:00
Adrien Béraud 1d80a77e55 build/cmake: avoid overriding "" for CMAKE_MSVC_RUNTIME_LIBRARY 2025-06-20 19:06:08 -04:00
Adrien Béraud fb8734c448 c: use c++ linkage for some non-exported functions 2025-06-20 19:04:59 -04:00
Andrey Vukolov 090fe75b7f OpenSSL link MSVC workflow workaround 2025-06-19 12:56:44 +02:00
Andrey Vukolov 173ca3d923 OpenSSL link Clang workflow workaround 2025-06-19 12:52:30 +02:00
Andrey Vukolov f5c875a19d OpenSSL link CMake workflow check 2025-06-19 12:46:20 +02:00
Andrey Vukolov 6780013f50 Unit tests workaround for possible issue with OpenSSL link 2025-06-19 12:17:10 +02:00
Andrey Vukolov 2f21a6e35a Unit tests workaround for possible issue with OpenSSL link 2025-06-19 12:07:36 +02:00
Andrey Vukolov 9e9e364048 C tools CFLAGS workaround for STATIC builds 2025-06-19 11:59:50 +02:00
Andrey Vukolov 2c3296542b Crypt32.dll fix 2025-06-18 17:14:05 +02:00
Andrey Vukolov 72988cca28 Regression fix 2025-06-18 16:53:54 +02:00
Andrey Vukolov a105513750 Attempt to fix OpenSSL for MSYS2 builds on CI 2025-06-18 16:48:05 +02:00
Andrey Vukolov bece03eab8 Attempt to fix llhttp for MSYS2 builds on CI 2025-06-18 16:32:28 +02:00
Andrey Vukolov 0fdb6979dd Attempt to fix OpenSSL for MSYS2 builds on CI 2025-06-18 16:21:57 +02:00
Andrey Vukolov a77c1d9538 Attempt to fix llhttp for MSYS2 builds on CI 2025-06-18 16:13:10 +02:00
Andrey Vukolov 4a7e1aba15 Attempt to fix llhttp for MSYS2 builds on CI 2025-06-18 16:08:38 +02:00
Andrey Vukolov a4263b9b54 Attempt to fix llhttp for MSYS2 builds on CI 2025-06-18 15:59:41 +02:00
Andrey Vukolov e26ed26e05 Attempt to fix restinio for MSYS2 builds on CI 2025-06-18 15:47:31 +02:00
Andrey Vukolov 526b11f973 C binding fixes, libreadline support for MSVC 2025-06-18 15:30:51 +02:00
Andrey Vukolov 627af36085 MSYS2 Crypto library fix 2025-06-18 12:07:51 +02:00
Andrey Vukolov a22c84d013 MSVC static runtime fix 2025-06-18 11:41:52 +02:00
Andrey Vukolov 3707f6294e libreadline fix for C tools 2025-06-18 11:29:26 +02:00
Andrey Vukolov 94cb17ef63 libreadline fix, WINVER typo fix 2025-06-18 11:22:55 +02:00
Andrey Vukolov 9bb08fa194 Merge branch 'master' into winbuild 2025-06-18 10:40:02 +02:00
Adrien Béraud 425cd58ea6 ci: build a static windows release 2025-06-17 20:49:05 -04:00
Adrien Béraud 43eb062ac5 build/cmake: use appropriate definitions for shared c lib 2025-06-17 20:25:56 -04:00
Adrien Béraud 29d878fad7 build/cmake: inherit build dir for msvc 2025-06-17 20:22:22 -04:00
Adrien Béraud a3a95a8f59 build/cmake: use appropriate definitions for shared c lib 2025-06-17 20:22:22 -04:00
Adrien Béraud 550721e233 build/cmake: use global MSVC_RUNTIME_LIBRARY 2025-06-17 20:22:22 -04:00
Adrien Béraud fa11d60672 c: use OPENDHT_C_PUBLIC for all symbols 2025-06-17 20:22:22 -04:00
Andrey Vukolov 6f8c681b26 Boost fix 2025-06-17 20:23:45 +02:00
Andrey Vukolov 718e445370 typo fix 2025-06-17 19:37:05 +02:00
Andrey Vukolov 5e469cba0f Boost fetcher (MSYS2/MinGW dependency) 2025-06-17 19:26:40 +02:00
Andrey Vukolov a05479e2dc Merge branch 'master' into winbuild
- Built and tested on MSVC for static and dynamic builds, tested.
2025-06-17 18:59:51 +02:00
Andrey Vukolov 7f6e47c7aa Fixed OPENDHT_C to avoid compatibility warnings 2025-06-16 14:16:04 -04:00
Andrey Vukolov 2e7c1a7272 Generalization of CMake build presets
- Generalized MSVC build with root presets
    - Separated build pipelines into 'minimal' and
      'full' variants
    - Added VCPKG_MANIFEST_MODE to handle local vcpkg
    - Inspected VCPKG_TARGET_TRIPLET and added
      VCPKG_OVERLAY_TRIPLETS as fallback options
2025-06-16 14:16:04 -04:00
Adrien Béraud 0f69153900 build/cmake: set appropriate CRT linkage for windows 2025-06-16 09:07:37 -04:00
Adrien Béraud e1885a17d9 Revert "ci: enable tests on mingw"
This reverts commit 87a9df28c6.
2025-06-15 15:16:08 -04:00
Adrien Béraud 87a9df28c6 ci: enable tests on mingw 2025-06-15 15:07:48 -04:00
Adrien Béraud bf7cb5a848 ci: only run tests for the release job for now 2025-06-15 13:55:11 -04:00
Adrien Béraud d24ffb8a1d build/cmake: use release/static triplets as needed 2025-06-15 12:47:54 -04:00
Adrien Béraud 962aed25fe build/cmake: add cpack support for wix 2025-06-15 12:47:16 -04:00
Adrien Béraud a1582220d6 tests: bind connect to loopback address on Windows 2025-06-15 12:46:36 -04:00
Andrei Vukolov a3bd1416d4 Removed OPENDHT_PUBLIC specifier from templatized classes 2025-06-14 17:45:41 -04:00
Adrien Béraud f49dabaadc build/cmake: add MSVC_RUNTIME_LIBRARY for dhtcnode 2025-06-14 14:03:21 -04:00
Adrien Béraud 2e38ec093d tools/dhtscanner: use client mode 2025-06-14 14:03:21 -04:00
Adrien Béraud 7995c2283d Workaround for MSVC runtime mismatch on STATIC builds 2025-06-12 20:04:13 -04:00
Adrien Béraud 7bb457d851 Pull Request #762: Workaround for MSVC runtime mismatch on STATIC builds 2025-06-12 20:00:59 -04:00
Adrien Béraud 80d0648d6d tools/dhtnode: use utf-8 for console output on Windows 2025-06-12 19:14:56 -04:00
Adrien Béraud 44508cd040 build/cmake: use relative install directories 2025-06-12 10:37:16 -04:00
Andrey Vukolov e5cc48c068 Merge branch 'master' into msvc-runtime-static 2025-06-12 16:35:29 +02:00
Adrien Beraud 520a15118c ci: add release job for Windows 2025-06-12 10:32:20 -04:00
Adrien Béraud 81931a211f ci: add github workflow for windows 2025-06-12 10:32:20 -04:00
Adrien Béraud 9a895d71d9 tools/dhtscanner: cleanup 2025-06-12 10:32:20 -04:00
Adrien Béraud 9d2b3e0b35 build/dev: use build directory 2025-06-12 10:32:20 -04:00
Adrien Béraud 14dbd3341c build/cmake: enable test feature for vcpkg 2025-06-12 10:32:20 -04:00
Adrien Béraud f032c7a52b build/vcpkg: add host tools 2025-06-12 10:32:20 -04:00
Adrien Béraud cee24974d6 build/vcpkg: add support for tests 2025-06-12 10:32:20 -04:00
Adrien Béraud d3e2fd1099 fixes for msvc 2025-06-12 10:32:20 -04:00
Adrien Béraud dd9d74e227 fixes for mingw 2025-06-12 10:32:20 -04:00
Adrien Béraud e1744ef950 build/cmake: add preset for Unix Makefiles 2025-06-12 10:32:20 -04:00
Adrien Béraud 3f64c32b7a build/cmake: define WINVER and _WIN32_WINNT on Windows 2025-06-12 10:32:20 -04:00
Adrien Béraud 6b0e154bd5 build/cmake: add vcpkg support for msvc 2025-06-12 10:32:20 -04:00
Andrey Vukolov 11bca9e307 Workaround for MSVC runtime mismatch on STATIC builds
- Added CMP0091 policy handler
	- Added generator expression for MSVC_RUNTIME_LIBRARY property
	  to avoid "Runtime Mismatch" linker error on MSVC STATIC builds
2025-06-12 09:36:53 +02:00
Andrey Vukolov fb630e29b9 Merge branch 'savoirfairelinux:master' into winbuild 2025-06-12 09:28:10 +02:00
Andrey Vukolov 3a0b09816b Merge remote-tracking branch 'refs/remotes/twdragon/winbuild' into winbuild 2025-06-12 09:23:14 +02:00
Andrey Vukolov 8ab6b5b06e Fixes for current MSVC build, presets deleted 2025-06-12 09:22:30 +02:00
Adrien Beraud 28ea18671f http: use appropriate log level for DNS result 2025-06-11 16:08:36 -04:00
Adrien Béraud 01e9c341df tests: use loopback address if peer bound any
fixes some tests on Windows
2025-06-10 18:37:19 -04:00
Adrien Béraud 94006f2fe1 sockaddr: add setLoopback() 2025-06-10 18:35:48 -04:00
Andrey Vukolov 9ca1c45ae7 CMakeLists.txt - remove occasional regression to cjson 2025-06-10 14:01:14 +02:00
Andrey Vukolov b9a6b1001c Merge branch 'master' into winbuild 2025-06-10 09:31:47 +02:00
Andrey Vukolov cc7c48a07e .gitignore for vcpkg in MANIFEST mode 2025-06-09 11:29:00 -04:00
Andrey Vukolov 798adefcde Fixes for MSYS2
- Set populated only for msgpack-cxx that does not exist for
      MinGW GCC x86_64
      https://packages.msys2.org/base/mingw-w64-msgpack-cxx
    - .gitignore fix for vcpkg (incorporated #760)
    - GnuTLS version handler fix (#755, #758)
2025-06-09 15:31:38 +02:00
Andrey Vukolov 72afb61079 Merge branch 'savoirfairelinux:master' into winbuild 2025-06-09 09:40:26 +02:00
Adrien Béraud e6fc8b7586 dhtrunner: add putEncrypted with PkId 'to' argument 2025-06-09 00:52:05 -04:00
Adrien Béraud 09da6db5e7 securedht: add putEncrypted with PkId 'to' argument 2025-06-09 00:52:05 -04:00
Adrien Béraud e870c3b486 dhtrunner: allow to find certificates by PkId 2025-06-09 00:52:05 -04:00
Adrien Béraud dcf31b2c5f securedht: allow to find certificates by PkId 2025-06-09 00:52:05 -04:00
Adrien Béraud f2eb234fd9 securedht: put certificate at PkId 2025-06-09 00:52:05 -04:00
Adrien Béraud c3f120f8f1 build/cmake: build C binding with vcpkg preset 2025-06-08 18:51:14 -04:00
Adrien Béraud 305f437f74 c: use appropriate includes for Windows 2025-06-08 18:51:14 -04:00
Andrey Vukolov c27f0f8fdc Merge branch 'master' into winbuild 2025-06-07 22:32:26 +02:00
Adrien Béraud 701e8c89fb vcpkg: add support for tools 2025-06-07 16:23:59 -04:00
Adrien Béraud aa212c4b2d c/tools: use memset instead of bzero 2025-06-07 16:23:59 -04:00
Adrien Béraud 48254a6759 build/cmake: add opendht_EXPORTS as public definition 2025-06-07 16:23:59 -04:00
Adrien Béraud 37ccc2f3a2 build/meson: fix typo 2025-06-07 16:23:59 -04:00
Adrien Béraud 2819047649 build/cmake: define C standard used 2025-06-07 16:23:59 -04:00
Andrey Vukolov 8d8b082ae2 Temporary fix https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2129833074 2025-06-06 11:09:43 +02:00
Andrey Vukolov 5377a48074 Rebase regression fix in tools_common.h 2025-06-06 11:00:35 +02:00
Andrey Vukolov ca8998e62b Merge branch 'winbuild' of github.com:twdragon/opendht into winbuild 2025-06-05 18:38:49 +02:00
Andrey Vukolov 62359d9011 Edited CMakeLists.txt file for building over vcpkg only 2025-06-05 18:38:21 +02:00
Andrey Vukolov 3022c4b378 Merge branch 'savoirfairelinux:master' into winbuild 2025-06-05 17:52:47 +02:00
Adrien Béraud 03e4be3974 build/cmake: add presets for vcpkg and unix 2025-06-03 11:46:36 -04:00
Adrien Beraud 91b241599d build: add vcpkg file 2025-06-03 11:46:36 -04:00
Adrien Beraud fcf2e7f94e Create codeql.yml 2025-06-03 11:33:04 -04:00
Adrien Béraud f1ff618dc8 Create codeql.yml 2025-06-03 11:30:01 -04:00
Adrien Beraud 5dcb342308 ci/github: use autobuild mode 2025-06-03 11:29:07 -04:00
Adrien Beraud 2d9d0761c9 ci/github: use autobuild mode 2025-06-03 11:23:25 -04:00
Adrien Beraud 4df297df6c ci/github: use autobuild mode 2025-06-03 11:16:48 -04:00
Adrien Beraud 70e8f7efb5 ci/github: udpate CodeQL workflow 2025-06-03 10:58:33 -04:00
Andrey Vukolov de8b441dae Merge branch 'master' into winbuild 2025-06-02 16:37:57 +02:00
Andrey Vukolov 5c4997d07e Merge master branch changes
- Applies master branch changes from #753 #754 #755 #756
      and commits for version 3.4.0 by @aberaud to winbuild branch
      for #750
	- CMake version handler for MINIMUM requirement setup to 3.5
2025-06-02 16:26:45 +02:00
Andrey Vukolov 9b33ff8a15 Fix meson.build 2025-06-01 10:26:18 -04:00
Andrey Vukolov 5c21401728 constexpr fixes for preparation of MSVC build
- Addresses https://github.com/savoirfairelinux/opendht/pull/750/files#r2089281221 in #750
    - Adds infohash.cpp file for correct build of the DLL nametables in SHARED mode with MSVC
    - Reverted commits 352e36500c and 6a264d6f73
    - Fixes DLL build issues on Windows due to OPENDHT_PUBLIC definitions described in #750
    - Prepares the build system for merging changes from #750 (@aberaud)
2025-06-01 10:26:18 -04:00
Adrien Béraud acae4bc4ff peer_discovery: use string_view for service type 2025-05-31 19:28:30 -04:00
Andrey Vukolov 68dc6a64be Definitions fix for #756 2025-05-30 23:05:59 -04:00
Andrey Vukolov 54a8fef0ee Windows build fixed for tools (wingetopt, signals)
- Addresses https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2089286643
    - Structures wingetopt and win32 compatibility files for builds on Windows with MSVC
    - Adjusts opendht_EXPORTS definition when building tools on MSVC
2025-05-30 23:05:59 -04:00
Andrey Vukolov a722726196 GNUTLS_INTERNAL_BUILD fix
- Removed GNUTLS_INTERNAL_BUILD definition to avoid problems with gnutls_free()
      function (https://github.com/savoirfairelinux/opendht/pull/750#issuecomment-2832005765)
      https://github.com/ShiftMediaProject/gnutls/blob/f78e2e673e84601283fb5ec353bfdd53204becd2/SMP/gnutls/gnutls.h#L2286
2025-05-23 18:24:35 -04:00
Andrey Vukolov b9bd954dfd GnuTLS version handler routine for versions 3.8.7 and later
- Added GnuTLS version handler directives for versions 3.8.7 and later
      https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2089284896
2025-05-23 18:24:35 -04:00
Andrey Vukolov 49b1daec38 Indentation fix 2025-05-23 15:43:08 +02:00
Andrey Vukolov aeb0b163cf MS Visual Studio .gitignore fix for CMake implicit builds
- Addresses review https://github.com/savoirfairelinux/opendht/pull/750#discussion_r2089277264 in #750
    - Allows clean clone and build in MS Visual Studio with different settings
2025-05-23 08:59:14 -04:00
Andrey Vukolov 1eba919dbd Trailing newline fix 2025-05-23 14:42:43 +02:00
Adrien Béraud c4e75ae66c update copyright year 2025-05-22 19:07:32 -04:00
Adrien Beraud d9afd2631b update version to 3.4.0 2025-05-22 12:05:31 -04:00
Adrien Beraud 405220795b http: check for cb in async_read_until 2025-05-22 11:53:05 -04:00
Adrien Beraud 3e407e65fa storage: remove previous value size from quota when appropriate 2025-05-22 11:53:05 -04:00
Adrien Béraud a2dff6a123 dhtrunner: registerCertificate: take certificate by const ref 2025-05-20 21:55:04 -04:00
Adrien Béraud 8d030f75f6 valuetype: compare certificate using longId 2025-05-19 23:57:09 -04:00
Adrien Béraud 13af7a6002 dhtrunner: registerCertificate: take certificate by const ref 2025-05-19 23:57:09 -04:00
Adrien Béraud 2bc46e9657 build/cmake: search llhttp with pkg_search_module 2025-05-19 23:55:49 -04:00
Adrien Béraud b3b050ca26 build/cmake: declare support for cmake up to 3.31 2025-05-19 23:55:46 -04:00
Adrien Béraud 38b0b2248f crypto: add Certificate::getDN() to read RFC4514 distinguished name 2025-05-19 23:55:42 -04:00
Adrien Béraud 5cfb1c6c9c tests/dhtrunner: wait separately for two conditions 2025-05-19 23:55:37 -04:00
Adrien Béraud 7aad21b7ed value: cleanup 2025-05-19 23:55:31 -04:00
Andrey Vukolov 3cd5338890 opendht_EXPORTS fix for shared builds 2025-04-27 22:53:17 +02:00
Andrey Vukolov 2fc81ad2dd GnuTLS build fix for MSVC
- Removed GNUTLS_INTERNAL_BUILD definition to avoid
	  usage of POSIX free() function
	- Autotools build fix
2025-04-26 16:55:58 +02:00
Andrey Vukolov 63a49896bf Fix Meson build 2025-04-24 16:00:04 +02:00
Andrey Vukolov 80755e5f15 Fix Meson build 2025-04-24 15:55:06 +02:00
Andrey Vukolov ba25b8aeba Incorporated commits for version 3.3.1 + MSVC build fixes
- Incorporated code for version 3.3.1
	- Reverted constexpr commits for hex_map:
	  - 352e36500c
	  - 6a264d6f73
	  as they created a lot of problems during builds on
	  Windows/MSVC.
	- Tested binaried linked dynamically with:
	  - MSYS2 (production-ready)
	  - MSVC (only for testing) !!!danger of memory leaks!!!
	- Tested binaries linked statically on win32 x64 platform
	- Populated libasio for both MSYS2 and MSVC builds on Windows
	- Pipeline fixes to build on Windows using only:
	  - vcpkg for MSVC
	  - MSYS2 pacman for MinGW
	  and remove the external dependency directory

The reference Windows builds are accessible in the following IPFS directory:

https://bafybeihsrak7orgubrnl5lvpcyzb4xf6kc7cd4tfvctucftg6vfqdhphlq.ipfs.dweb.link/
2025-04-24 14:50:23 +02:00
Andrey Vukolov 279589fa78 Pre-master 2025-04-23 18:18:58 +02:00
Adrien Béraud c3669cfd36 ci/github: update restinio tag name 2025-04-22 22:37:39 -04:00
Adrien Béraud 45f04a7b6f ci/github: update restinio 2025-04-22 22:33:59 -04:00
Adrien Béraud 33f9570ecb adapt for Asio 1.34 2025-04-22 20:02:37 -04:00
Andrey Vukolov 1c1c99974a Added and tested build scenarios for Windows (MSYS2, MSVC static)
- Based on Windows build adjustment code from @novemus
	  (see his magnificient code merge request #716)
	- Determined full-static and dynamic link libraries for
	  Windows if built using MSYS2 or MSVC
	- Built without restinio and llhttp [TODO]
	- Set for automatic fetching and population from the network
	  the following libraries for MSYS2:
		- GnuTLS 3.8.4 for 64-bit Windows (tested for dynamic
		  and static builds)
			- Auto name adjustments for GnuTLS
		- GnuTLS 3.8.9 for 32-bit Windows (untested)
		- cJSON as a dependency for msgpack
		- msgpack 6.1.1
		- jsoncpp 1.9.5
		- libfmt 11.1.2
		- libasio 1.30.2
	  for MSVC:
		- cJSON (used by msgpack in dynamic builds)
		- jsoncpp 1.9.5
		- libfmt 11.1.2
	- Various build scenario fixes for MSVC dynamic builds
	- Added modular codebase for infohash.cpp to avoid header
	  treatment mismatches in MSVC when compiling DLL
	- Added convenience prints in the build scenario
	- Fixed inconvenient usage of pkgconfig in Windows, the
	  link scenarios adjusted accordingly
	- Fixed hardcoded find_library calls
	- Added standard CMake handler for Boost library using
	  BOOST_ROOT variable, including environmental definition
	- Fixed libreadline linkage on POSIX when the default link
	  point is turned off for OPENDHT_TOOLS (Mint Linux)
	- Added versioned handler for CMP0167 policy (from CMake 3.30)
	- Code fixes for compatibility headers in Windows (crypto.cpp,
	  network_utils.h, utils.h)
	- Urgent fix for improper redefinition of _WINNT_VERSION for
	  Windows 10/11
	  (https://github.com/savoirfairelinux/opendht/pull/716#issuecomment-2793129052)
	- Compile definitions fixed for opendht_EXPORTS and OPENDHT_BUILD
	  in build scenario for OPENDHT_TOOLS
	- Urgent fix for GnuTLS version handler in the code (type
	  redefinition in version 3.8.7 and later)
	  https://github.com/savoirfairelinux/opendht/pull/716#issuecomment-2792592951
	- Various fixes for proper dynamic linking in Windows
	- Built and tested in dynamic and static build scenarios under
	  MSYS2 in Windows 10 and Windows 11, proven working. The
	  static build does not seem fully static, the redevelopment
	  of the MSVC build scenario is proposed by @novemus
	- Built and tested in static mode under MSVC/Visual Studio 2022.
	  Proven working
	- Improper usage of the C's free() function is detected in GnuTLS
	  dynamically linked in Windows (shiftmedia-gnutls 3.7.2 to 3.8.7)
	- Added a MSVC-specific source hack to avoid using gnutls_free()
	  function when built in Windows using dynamic link.
	  !!! CAUTION !!!
	  This implementation should be considered as a dirty hack likely
	  leading to memory leaks! The code should be thoroughly tested
	  and refactored to avoid memory leaks, but the true origin of
	  errors is still not revealed [TODO]
	- My respect to @novemus and his works over #716
2025-04-22 14:46:41 +02:00
François-Simon Fauteux-Chapleau c2d8b19380 http: fix service name resolution failure 2025-04-14 22:12:56 -04:00
Adrien Béraud 9bd957da48 build/cmake: update CheckAtomic.cmake 2025-04-05 10:29:06 -04:00
Adrien Béraud 352e36500c utils: make HexMap constexpr 2025-04-05 09:49:58 -04:00
Adrien Béraud 7397bd615f infohash: always write end of string terminator 2025-03-24 23:37:07 -04:00
Adrien Béraud 6a264d6f73 infohash: constexpr HexMap constructor 2025-03-24 23:29:32 -04:00
François-Simon Fauteux-Chapleau b0fa19d6f8 Merge pull request #747 from savoirfairelinux/proxy_push_result
proxy client: provide result for pushNotificationReceived
2025-02-20 15:29:58 -05:00
Adrien Beraud b2860e1731 proxy client: provide result for pushNotificationReceived 2025-02-20 14:13:16 -05:00
Adrien Beraud ad65ce872b docker: update llvm image to Ubuntu 24.04 2025-02-14 12:03:55 -05:00
Adrien Beraud 0cdc828953 docker: update restinio 2025-02-14 11:50:46 -05:00
Adrien Beraud 65e13fff4e ci/github: update llhttp 2025-02-14 11:48:42 -05:00
Adrien Beraud 748247d660 ci/github: update actions 2025-02-14 11:46:05 -05:00
Adrien Beraud 456f266be3 update restinio 2025-02-14 11:41:16 -05:00
Adrien Beraud 2c26030108 build/cmake: accept both llhttp and libllhttp 2025-02-14 11:28:50 -05:00
Adrien Beraud efc26245ae update version to 3.3.0 2025-02-11 16:01:27 -05:00
Adrien Beraud b9e00c7a0f tools/cnode: show value ID when put completes 2025-02-11 15:48:59 -05:00
Simon Désaulniers 5bf19c875c c: dht_value_with_id_new for setting an ID
Necessary for cancelling put values. Otherwise, the user doesn't have
the value ID for asking to cancel the permanent put.
2025-02-04 13:24:54 -05:00
Simon Désaulniers 5c18c980aa c/opendht: check for server_ca null 2025-01-25 09:32:15 -05:00
Simon Désaulniers b8d6fdc8eb c/opendht: dht_runner_run_config, consider client_identity 2025-01-25 09:32:15 -05:00
Simon Désaulniers 27bfd547c5 c/opendht: dht_runner_run_config, consider server_ca 2025-01-25 09:32:15 -05:00
ovari 5237f0a3b3 Update dht.cpp 2025-01-05 10:01:40 -05:00
ovari 23af860532 Update pht.h 2024-12-19 15:29:21 -05:00
ovari 4c98f7c8f4 pht.h: cleanup 2024-12-19 15:29:21 -05:00
Adrien Beraud 2a4b357420 ci: update libargon2 on Ubuntu 2024-12-19 15:22:58 -05:00
Adrien Beraud a26ac441ba proxy: cleanup 2024-12-17 16:04:22 -05:00
Adrien Beraud 80cfed38a1 build/cmake: make using io_uring optional 2024-12-17 16:04:22 -05:00
Lucas Dias 83ae498008 Catch exception of DeserializeNodes
Fix calls to DeserializeNodes. They must
catch possible exceptions

Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-12-17 14:06:36 -05:00
Adrien Béraud 7c184e1c8c Revert "build/cmake: accept both llhttp and libllhttp"
This reverts commit 7cf43f53ac.
2024-11-26 11:22:58 -05:00
Andreas Traczyk 4aa417802f deps: win32: migrate from http_parser to llhttp 2024-11-26 11:09:21 -05:00
Adrien Béraud cdba5b33cc proxy server: add options to listen route 2024-11-20 11:40:12 -05:00
Adrien Béraud 81bd05fe84 proxy node: remove jquery, update for new APIs 2024-11-20 11:40:12 -05:00
Adrien Béraud cf135d18b4 c node: fix typo 2024-11-20 11:40:12 -05:00
Adrien Béraud c7ba7f6703 utils: use fmt::format for time 2024-11-20 11:40:12 -05:00
Adrien Beraud c73c8c77f2 search: combine callbacks in case of multiple equivalent puts 2024-11-20 11:39:19 -05:00
Adrien Beraud c3bb16e92f tests: add testPutDuplicate 2024-11-20 11:39:19 -05:00
Adrien Beraud 3f27cd7069 proxy client: resubscribe on token change 2024-11-18 11:07:55 -05:00
Adrien Beraud b222efe638 proxy client: pass push parameters to constructor 2024-11-18 11:07:55 -05:00
Adrien Béraud 3c62026b5c proxy server: move time_point using statement before use 2024-11-05 20:20:45 -05:00
Adrien Béraud 7cf43f53ac build/cmake: accept both llhttp and libllhttp 2024-11-05 20:12:13 -05:00
François-Simon Fauteux-Chapleau df189e3e12 dht_proxy_server: add push notification statistics 2024-11-05 15:13:39 -05:00
Adrien Beraud 7e0e7d5483 github/ci: update macOS job to macOS 15 2024-11-04 16:44:36 -05:00
Adrien Beraud 1aeb596b04 crypto: fix warning 2024-11-04 16:39:35 -05:00
Adrien Beraud 950194f68e proxy client: allow to configure user agent for proxy 2024-11-04 16:34:02 -05:00
AmnaSnene 5dc3d3cfd7 Raise an error if any Identity file fails to save 2024-11-04 12:08:34 -05:00
François-Simon Fauteux-Chapleau 5397f80b87 value: preserve priority when encrypting
All encrypted values put on the DHT currently have the default priority
of 0 because the priority information is ignored by the Value::encrypt
function.
2024-10-22 15:22:43 -04:00
Adrien Beraud 88d0af9e3d meson: fix conf_data used before definition 2024-10-03 15:33:03 -04:00
François-Simon Fauteux-Chapleau 792b851d77 dht_proxy_server: fix Android push notifications
This commit updates the format of the push notification requests sent by
the DHT proxy server to conform to FCM's HTTP v1 API. (The previously
used API was deprecated in 2023, see:
https://firebase.google.com/docs/cloud-messaging/migrate-v1)
The "priority" and "ttl" (time to live) options are specific to Android
and therefore need to be put in the "android" block, as documented here:
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages
2024-09-19 12:48:36 -04:00
Adrien Béraud 9da832c1d1 http: use appropriate string format syntax 2024-08-11 11:44:47 -04:00
liufei 44f6d21c83 DecryptError cause by low level error 2024-07-23 11:37:26 -04:00
AmnaSnene 38454eaf6e peer discovery: add a timer to schedule connectivityChanged with a maximum interval of one minute 2024-07-16 14:25:01 -04:00
novemus 3be70cd90d msvc build adjustment 2024-07-13 09:42:34 +03:00
Matthew Webb 76a2bd234a Get off of deprecated GCM AES methods
Multiple compiler warnings note that the gcm_aes_* family of functions are deprecated. They have been replaced with gcm_aes<key_length>_*. This change uses the correct set of functions based on the given key size. Resolves #571.

Sample compiler warning:
/home/noviv/opendht/src/crypto.cpp: In function ‘dht::Blob dht::crypto::aesEncrypt(const uint8_t*, size_t, const dht::Blob&)’: /home/noviv/opendht/src/crypto.cpp:97:20: warning: ‘void nettle_gcm_aes_set_key(gcm_aes_ctx*, size_t, const uint8_t*)’ is deprecated [-Wdeprecated-declarations]
   97 |     gcm_aes_set_key(&aes, key.size(), key.data());
         |                    ^
         In file included from /home/noviv/opendht/src/crypto.cpp:27:
         /usr/include/nettle/gcm.h:276:1: note: declared here
           276 | gcm_aes_set_key(struct gcm_aes_ctx *ctx,
                 | ^~~~~~~~~~~~~~~)

https://github.com/gnutls/nettle/commit/6a19845e6f71791ca98765d490ec08e776494bee marked the functions as deprecated.
2024-07-11 10:07:05 -04:00
Adrien Beraud 972d4d28a1 pkgconfig: add optional liburing dependency 2024-07-05 11:38:32 -04:00
Matthew Webb 72e0a4fb6b Fix an unused parameter warning in dhtrunnertester
This change eliminates the following compiler warning without reducing readability:

/home/noviv/opendht/tests/dhtrunnertester.cpp: In lambda function:
/home/noviv/opendht/tests/dhtrunnertester.cpp:292:89: warning: unused parameter ‘expired’ [-Wunused-parameter]
  292 |     node2.listen(key2, [&](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired){
      |                                                                                    ~~~~~^~~~~~~
2024-07-03 21:59:07 -04:00
AmnaSnene 3e2fd5e8fa peer discovery: address requested changes 2024-06-25 13:27:35 -04:00
AmnaSnene 8b3f7f2480 peer discovery: re-publish and re-discover immediately when a node disconnects, instead of on the connectivityChanged signal. 2024-06-25 13:27:35 -04:00
AmnaSnene 57c855e1cb peer discovery: post reDiscover() and publish() to the ioContext when connectivity changes. 2024-06-25 13:27:35 -04:00
Adrien Beraud 56e7cd94a5 cmake, meson: allow to use io_uring 2024-06-21 12:09:29 -04:00
Adrien Beraud 074e05cc32 ci/github: update to latest action versions 2024-06-10 16:39:55 -04:00
Lanius-collaris 251f66dfce fix getif_workaround_android.h
char may be signed
2024-06-10 08:21:57 -04:00
Lucas Dias 227a7aa0d9 make crypto error messages more readable
Add verifications to gnutls calls and throw expcetion
with readable messages.
For example, if call loadIdentity and crt file has name
different of private key exception message was
Can't get certificate public key ID: ASN1 parser: Value was not found.

However, the real problem is that crt file was not found.
Now, for the same problem the exception message will be:
Error while reading file.

Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 16:56:29 -03:00
Lucas Dias e12e344a79 make crypto error messages more readable
Add verifications to gnutls calls and throw expcetion
with readable messages.
For example, if call loadIdentity and crt file has name
different of private key exception message was
Can't get certificate public key ID: ASN1 parser: Value was not found.

However, the real problem is that crt file was not found.
Now, for the same problem the exception message will be:
Error while reading file.

Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 16:55:10 -03:00
Lucas Dias d4fc4fd658 Merge branch 'crypto_error_messages' of https://github.com/lucassdiass/opendht into crypto_error_messages
Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 16:53:32 -03:00
Lucas Dias 08d67cc8d8 Merge branch 'crypto_error_messages' of https://github.com/lucassdiass/opendht into crypto_error_messages
Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 16:52:09 -03:00
Lucas Dias 208afd22f2 Merge branch 'crypto_error_messages' of https://github.com/lucassdiass/opendht into crypto_error_messages 2024-06-09 15:55:31 -03:00
Lucas Dias 9eea01202a make crypto error messages more readable
Add verifications to gnutls calls and throw expcetion
with readable messages.
For example, if call loadIdentity and crt file has name
different of private key exception message was
Can't get certificate public key ID: ASN1 parser: Value was not found.

However, the real problem is that crt file was not found.
Now, for the same problem the exception message will be:
Error while reading file.

Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 15:46:34 -03:00
Lucas Dias 304a9992fe make crypto error messages more readable
Add verifications to gnutls calls and throw expcetion
with readable messages.
For example, if call loadIdentity and crt file has name
different of private key exception message was
Can't get certificate public key ID: ASN1 parser: Value was not found.

However, the real problem is that crt file was not found.
Now, for the same problem the exception message will be:
Error while reading file.

Signed-off-by: Lucas Dias <lucas_dias@redes.ufsm.br>
2024-06-09 09:45:21 -03:00
Adrien Beraud ae62216bf4 rust: update to 2021, fix memory issues 2024-06-07 10:29:26 -04:00
Adrien Beraud cd92eeaae5 dht: add support to behave as a client node 2024-06-07 09:52:01 -04:00
Adrien Beraud 9dad7c69fd peer discovery: cleanup 2024-06-07 09:31:48 -04:00
Lanius-collaris 5cc5b98aeb fix android workaround 2024-06-07 09:21:05 -04:00
Lanius-collaris c03ce419ca peer_discovery: add a workaround for Android hotspot 2024-06-07 09:21:05 -04:00
Adrien Béraud ceef3f048c README: add llhttp dependency 2024-06-03 08:32:17 -04:00
Adrien Béraud 8dd926182c ci/github: update before install 2024-06-03 08:26:52 -04:00
Adrien Béraud c8b528b3f4 update version to 3.2.0 2024-05-31 06:58:09 -04:00
Adrien Béraud a65148cd08 ci: build proxy client for Autotools build 2024-05-31 06:58:09 -04:00
Adrien Béraud 5a2a20a32f http: migrate from http-parser to llhttp 2024-05-31 06:58:09 -04:00
Lanius-collaris 318d02c55a update http, dht_proxy_client
http: simplify Connection::async_connect()
dht_proxy_client: add listenKeepIdle setting
2024-05-25 23:57:52 -04:00
Lanius-collaris a69da52f89 update http.h, http.cpp 2024-05-25 23:57:52 -04:00
Lanius-collaris ac0ea6ac57 proxy client: decrease the frequency of keepalive for listen op 2024-05-25 23:57:52 -04:00
Lanius-collaris 88d65a55a7 http: allow to modify keepalive option 2024-05-25 23:57:52 -04:00
Lanius-collaris dffe7d91ee return to 386943de 2024-05-25 23:57:52 -04:00
Lanius-collaris da638b3ae6 cleanup 2024-05-25 23:57:52 -04:00
Lanius-collaris 379568ae0d Update http.cpp 2024-05-25 23:57:52 -04:00
Lanius-collaris 24adfbf2c4 Adjust TCP keepalive options for listen op 2024-05-25 23:57:52 -04:00
François-Simon Fauteux-Chapleau 89179cad4f network_utils: use poll instead of select
select is limited to file descriptor numbers below FD_SETSIZE (1024),
and calling FD_SET with a higher value can cause a buffer overflow. This
can be problematic for applications using OpenDHT as a library.
2024-05-22 11:57:38 -04:00
François-Simon Fauteux-Chapleau f2cee8e9ce thread pool: add function to detach threads 2024-04-23 14:02:32 -04:00
Adrien Béraud 386943de39 tests/proxy: use random port 2024-04-06 23:29:38 -04:00
Adrien Béraud 60b810af7e meson: disable long tests by default 2024-04-06 23:29:35 -04:00
Adrien Béraud aa2c0c2da9 meson: add test for PeerDiscovery 2024-04-06 23:01:41 -04:00
Adrien Béraud 62debfa58a meson: add test prefix for unit tests 2024-04-06 22:59:12 -04:00
Adrien Béraud 9741dba974 update version to 3.1.11 2024-04-06 22:26:56 -04:00
Adrien Béraud 93ac28ead2 meson: configure pkgconfig files 2024-04-06 20:10:33 -04:00
Adrien Beraud a0a3cd3028 proxy: add long test 2024-04-06 19:42:42 -04:00
Adrien Béraud 611ecbd06a meson: add ability to build static or shared 2024-04-06 19:18:27 -04:00
Adrien Béraud 70c465b006 meson: link tests with msgpack 2024-04-06 18:43:36 -04:00
Adrien Beraud 59c8d9b9be op cache: return cache result in onValue 2024-04-06 18:24:16 -04:00
Adrien Beraud 7f70fcd316 proxy client: cancel http request on listen cancel 2024-04-06 18:24:16 -04:00
Adrien Beraud 17e9ad5093 meson: fix build with proxy server 2024-04-06 15:51:11 -04:00
Adrien Beraud 42435bdd4f meson: allow to build unit tests 2024-04-06 15:51:11 -04:00
Adrien Beraud c125a2af1f meson: build thread pool 2024-04-06 15:51:11 -04:00
Andreas Traczyk c0a1356049 dht_proxy_server: use lambda instead of std::bind for listen callback
Avoids issues compiling with MSC.

Also move PushSessionContext definition outside the OPENDHT_PUSH_NOTIFICATIONS condition.
2024-04-04 14:20:01 -04:00
Adrien Béraud 5e6679139b update version to 3.1.10 2024-04-03 14:35:42 -04:00
Andreas Traczyk c118f85886 Merge pull request #694 from savoirfairelinux/push-value-IDs
provide value IDs for push notifications
2024-04-03 11:52:01 -04:00
Andreas Traczyk b40d604ef7 provide value IDs for push notifications 2024-04-02 17:34:16 -04:00
SASANO Takayoshi f630b013ee replace CPPFLAGS += ... (2) 2024-04-02 13:04:52 -04:00
SASANO Takayoshi 36167c3e45 replace CPPFLAGS += ... 2024-04-02 13:04:52 -04:00
Adrien Béraud 4eaa53a4a6 update version to 3.1.9 2024-03-24 23:42:44 -04:00
Adrien Béraud 4859e9c4e7 meson: support building with push notification support 2024-03-24 23:42:01 -04:00
Adrien Béraud c82c393102 ci: use Cython from pip 2024-03-24 23:31:18 -04:00
Adrien Béraud 5dc162a4ec meson: support building python 2024-03-24 23:26:05 -04:00
Adrien Béraud 5a4c599139 meson: support building with indexation 2024-03-24 23:25:40 -04:00
Adrien Béraud 07ca10a451 Revert "ci: build proxy client for Autotools build"
This reverts commit 2dc9f25ff4.
2024-03-24 22:14:32 -04:00
Adrien Béraud 0e556b88be docker: use cython, meson from pip 2024-03-24 22:08:03 -04:00
Adrien Béraud 0b242e62c5 update version to 3.1.8 2024-03-24 21:46:15 -04:00
Adrien Béraud acde8fa6ec crypto: remove legacy decrypt 2024-03-24 18:12:27 -04:00
Adrien Béraud c8b5611386 dhtnode: fix small typo in put encrypted log 2024-03-24 15:45:55 -04:00
Adrien Béraud f7e4533282 crypto: always zero-initialize gnutls_datum_t 2024-03-24 15:45:52 -04:00
Adrien Beraud 5abbef547b use new log format 2024-03-22 13:49:44 -04:00
Adrien Beraud 3c27b2c777 dhtrunner: avoid blocking when stopping
A deadlock was possible when if shutdown operation occured when the dht was in "connecting" state.
2024-03-22 13:49:44 -04:00
Adrien Beraud 903eba6a31 proxy client: cancel resolver on stop 2024-03-22 13:49:44 -04:00
Adrien Beraud a37e42af37 Request: cancel resolver on cancel 2024-03-22 13:49:44 -04:00
Adrien Beraud cc6cce6157 http: allow to cancel resolver 2024-03-22 13:49:44 -04:00
Adrien Béraud 2dc9f25ff4 ci: build proxy client for Autotools build 2024-03-17 16:38:35 -04:00
Adrien Béraud 7ca39b4a20 http: use OCSP_check_validity to check OCSP validity 2024-03-17 15:56:48 -04:00
Adrien Béraud fcffcee383 build/cmake: require cmake 3.16 2024-03-17 13:38:17 -04:00
Adrien Béraud e371bddd48 ci/github: use Cython from pip on Ubuntu 22.04 2024-03-17 13:16:44 -04:00
Adrien Béraud 26d23cf94f ci/github: use recent Meson for build 2024-03-17 12:48:10 -04:00
Adrien Béraud b608349e94 ci/github: use BUILD_TESTING instead of OPENDHT_TESTS 2024-03-17 12:19:02 -04:00
Lanius-collaris f9b46168d0 dht_proxy_server: Allow user to specify non-standard ports in UnifiedPush endpoint 2024-01-17 15:54:04 -05:00
Adrien Béraud 88d15be4ea build: update version to 3.1.7 2024-01-02 16:25:16 -05:00
Adrien Béraud 0c4942439b move secure_vector to its own file 2024-01-02 16:22:02 -05:00
Adrien Béraud b03df3f7a6 aesEncrypt: allow to provide salt 2024-01-02 15:18:44 -05:00
Adrien Béraud 6a6816ada7 build/meson: allow to build c binding 2023-12-11 22:16:58 -05:00
Adrien Béraud 372c87ac12 build: remove rng.cpp 2023-12-11 21:18:15 -05:00
Adrien Béraud 728c99999f getDerivedRandomEngine: use 32 bit input for std::seed_seq 2023-12-11 21:12:50 -05:00
Adrien Béraud 2017473156 build: update version to 3.1.6 2023-12-11 09:57:51 -05:00
Adrien Béraud 08d6367fdc pht: move to std::random_device 2023-12-10 16:02:56 -05:00
Adrien Béraud 23d07dae38 rng: drop custom random_device implementation for MinGW/Windows
MinGW now has std::random_device support on Windows:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85494
2023-12-10 15:18:59 -05:00
Adrien Béraud 29c83d9c97 rng: improve getSeededRandomEngine
* Make sure to use 32 bit input for std::seed_seq
* Retry using random device every use
* Adjust delays and retry count to keep approx. the same max timeout.
 In practice the actual average timeout should be reduced, because
 the algo doesn't lose existing data and can move forward in case
 of occasional failure/retry.
2023-12-10 15:07:39 -05:00
Adrien Béraud abbc77744e dhtrunner: allow to configure rng used by the dht 2023-12-10 15:07:39 -05:00
Adrien Béraud 7a61fa371f dht: allow to provide rng to constructor 2023-12-10 15:06:51 -05:00
Adrien Béraud ce7f592b1c search: return if added node is actually removed 2023-12-08 11:02:21 -05:00
Adrien Béraud 111bfea6f3 build: update version to 3.1.4 2023-12-03 22:09:34 -05:00
Adrien Béraud e35a11a495 tests: add test for aesBuildEncrypted 2023-12-03 22:03:22 -05:00
Adrien Béraud 0592b9ff51 crypto: add aesBuildEncrypted 2023-12-03 22:03:22 -05:00
Adrien Béraud 297e182576 crypto: fix typo in comment 2023-11-28 19:57:01 -05:00
Adrien Béraud b285e6fd2b ci/github: use macOS 12 2023-11-28 18:34:37 -05:00
Adrien Béraud 8ed72e204b build: update version to 3.1.3 2023-11-28 18:18:05 -05:00
Amin Bandali 4592663fd2 build/cmake: Link libatomic where needed for 64-bit atomic ops.
Link against libatomic also on architectures that need it for 64-bit
atomic operations.  ARM EABI (armel) and little-endian MIPS (mipsel)
are two such architectures.
2023-11-28 10:52:01 -05:00
Adrien Béraud 4c1c6cf8e9 python: add aesEncrypt, aesDecrypt with password 2023-11-28 10:49:41 -05:00
Adrien Béraud 09046ec698 tests: add tests for AES encryption and key streching 2023-11-28 10:49:41 -05:00
Adrien Béraud 24e7b00e4e crypto: add aesGetKey, aesGetSalt, aesGetEncrypted
Allows to retrieve the encryption key and salt from
an encrypted blob, leading the way for biometry support.
2023-11-28 10:49:41 -05:00
Adrien Béraud 95fdadf16b build: update version to 3.1.2 2023-11-07 13:15:56 -05:00
Adrien Béraud a271ab1680 python: add putSigned, putEncrypted to DhtRunner 2023-11-07 13:15:56 -05:00
Moreno Giussani ac9d7942ce Add loadIdentity 2023-11-07 09:29:46 -05:00
Adrien Béraud 5ca7b8d6dc python: add cancelPut 2023-11-07 09:15:11 -05:00
Adrien Béraud 805cdbed1d python: add biding for missing DhtConfig fields 2023-11-06 22:57:50 -05:00
Adrien Béraud 29efd42de3 python: add binding for SockAddr.resolve 2023-11-06 22:57:50 -05:00
Adrien Béraud ae2a1d83cf python: use shared_ptr, make_shared from Cython 2023-11-06 21:59:22 -05:00
Adrien Béraud bad8bdfe13 python: support 'permanent' argument for put 2023-11-06 21:55:16 -05:00
Adrien Béraud 13194b66d3 proxy client: retry permanent put after reconnect 2023-11-02 15:58:11 -04:00
Adrien Béraud 601758f5fd proxy server: use isMember for timeout 2023-09-27 13:56:43 -04:00
Adrien Béraud 3191498855 update version to 3.0.0 2023-09-24 18:13:22 -04:00
Adrien Béraud 4882826f58 ci, docker: update restinio 2023-09-24 18:13:22 -04:00
Kateryna Kostiuk 61f43c6b05 iOS: use high priority for resubscribe notifications 2023-09-18 15:27:41 -04:00
Adrien Béraud 8b91c24414 python: make callbacks noexcept 2023-09-11 11:52:55 -04:00
Adrien Béraud dbebaae1f3 callbacks: make raw callbacks except 2023-09-11 11:42:05 -04:00
Adrien Béraud 7cc743ff5e callbacks: make raw callbacks noexcept 2023-09-11 11:30:22 -04:00
Adrien Béraud 3b02cee495 python: update classifiers 2023-09-11 11:30:04 -04:00
Adrien Béraud 2e520bea4f unit tests: make testListen run 256 times
Makes the test pass in many more cases.
2023-09-09 12:51:15 -04:00
Adrien Béraud f9f57b50b1 update README.md 2023-09-09 12:41:16 -04:00
Adrien Béraud fb9e6eee48 Revert "build: do not define ASN1_time_parse when using openssl"
This reverts commit 3a8adb4e17.
2023-08-30 17:59:07 -04:00
Adrien Béraud b53af75a7f meson, autotools: link with fmt 2023-08-30 17:58:45 -04:00
Adrien Béraud 2ed40aeefe proxy client: use [[maybe_unused]] 2023-08-30 17:58:45 -04:00
Adrien Béraud bb61b8468b proxy client: implement OnPublicAddressChanged 2023-08-30 17:58:45 -04:00
Adrien Béraud 55688a25aa http: don't encode whole url
url encoding should be used for url components
by users of the library,
otherwise characters like '/' get escaped.
2023-08-30 17:58:45 -04:00
Adrien Béraud 21fd58a39c tools: show log on PublicAddressChanged 2023-08-30 17:58:45 -04:00
Adrien Béraud ae56d4e9be dht: implement OnPublicAddressChanged 2023-08-30 17:58:45 -04:00
Adrien Béraud 982896a718 dht interface: add OnPublicAddressChanged 2023-08-30 17:58:45 -04:00
Adrien Béraud 2ae092e266 storage: remove unused variable 2023-08-30 17:58:45 -04:00
Adrien Béraud 27ce8b00ed add syncLevel to send announce/listen early 2023-08-30 16:31:47 -04:00
Kateryna Kostiuk 3a8adb4e17 build: do not define ASN1_time_parse when using openssl 2023-08-27 16:54:16 -04:00
Adrien Béraud 899d18968e thread pool: add missing header 2023-08-20 23:44:49 -04:00
Adrien Béraud 285105c8d1 thread pool: simplify cleanup logic 2023-08-20 23:02:41 -04:00
Adrien Béraud 9e0ad9d926 thread pool: wait for tasks to complete on stop 2023-08-19 18:48:53 -04:00
Adrien Béraud 0fdded0606 thread pool: allow pool to reduce in size after some time 2023-08-19 18:48:53 -04:00
Adrien Béraud 9947172abb tests/http: wait for the server to start 2023-08-19 18:48:53 -04:00
Adrien Béraud b034a823a9 dhtcnode: reduce exposed stack storage 2023-08-19 18:48:53 -04:00
Jakob Haufe 7baee925f6 doc: fix dhtnode(1) man page formatting
This fixes the following lintian issue:
    22: warning: macro 'mF' not defined [usr/share/man/man1/dhtnode.1.gz:1]
2023-08-16 22:44:06 -04:00
Adrien Béraud ed6c5381d8 http: remove incorrect static usage 2023-07-29 00:02:48 -04:00
Adrien Béraud d58e4c8a89 build/cmake: remove unsupported attribute 2023-07-28 23:58:46 -04:00
Léo Banno-Cloutier 2f2ed9bca7 url_encode: escape url query
For routes such as /api/auth/directory/search, when searching for names such as
"Léo", jams would not respond to the request
since the URL contained invalid characters defined in RFC3986. `url_encode`
turns such characters into their equivalent escaped characters.
2023-07-25 10:28:22 -04:00
Amna 3e888d8e2d network engine: remove link-local condition from isMartian() 2023-07-05 19:38:24 -04:00
Adrien Béraud f461eaa191 log: cleanup, avoid using default constructor 2023-06-28 11:27:03 -04:00
Adrien Béraud 411d8dbe62 network_engine: add missing headers 2023-06-28 11:27:03 -04:00
Lanius-collaris 825cf98bf4 dhtnode.cpp: fix void print_usage()
Print pushserver parameter instead of openpush
2023-06-28 09:08:52 -04:00
Adrien Béraud aff1ed4575 network engine: make UA private, constexpr 2023-06-27 20:07:03 -04:00
Adrien Béraud 6b1e7513b3 logger: make class public 2023-06-26 18:25:43 -04:00
Adrien Béraud 8c94dc8f89 dht: update User-Agent (UA) to "o2"
The update reflects the slow evolution of the protocol.
Also, saves two bytes in every packet.
2023-06-26 18:25:31 -04:00
Adrien Béraud a7f459eab9 log: fix build on Windows 2023-06-26 16:10:11 -04:00
Adrien Béraud 7383e3ea29 node cache: increase cleanup period 2023-06-19 18:36:58 -04:00
Adrien Béraud a416d472fb node: properly skip id 0 2023-06-19 18:36:17 -04:00
Adrien Béraud 8fb707824e dockerfile: use deps from ghcr 2023-06-13 20:40:00 -04:00
Adrien Béraud e646636bde docker/alpine: use Alpine 3.18 2023-06-13 20:21:34 -04:00
Adrien Béraud fafd2f0233 update copyright year 2023-06-02 23:16:04 -04:00
Adrien Béraud 9f031303a2 securedht: destroy dht before other fields 2023-06-02 21:50:25 -04:00
Adrien Béraud 9a2e69ea9c log: simplify logger 2023-06-02 21:50:25 -04:00
Sébastien Blin 54eff3b0aa proxyServer: no need for a pushServer_ for type==UnifiedPush 2023-06-02 13:18:58 -04:00
Adrien Béraud 817a5baef2 build/cmake: apply OPENDHT_SANITIZE to the C binding 2023-06-01 14:26:22 -04:00
Adrien Béraud 79dfc0403a dht: remove deprecated constructor 2023-06-01 14:25:45 -04:00
Adrien Béraud 675d892fc1 update version to 2.6.0 2023-05-18 13:13:25 -04:00
Adrien Béraud 2654970499 logger: remove OPENDHT_LOG, rename to logger.h 2023-05-18 12:31:42 -04:00
Adrien Béraud b3c5c2fcfa hash: add fmt formatter 2023-05-18 12:31:42 -04:00
Adrien Béraud 6919df592f sockaddr: add fmt formatter 2023-05-18 12:31:42 -04:00
Adrien Béraud 6cfede0868 logs: use fmt 2023-05-18 12:31:42 -04:00
Adrien Béraud e176e4baa6 logs: use fmt 2023-05-17 23:43:55 -04:00
Adrien Béraud 4041b69800 DhtRunner, dht_interface: remove setLoggers 2023-05-17 23:43:55 -04:00
Adrien Béraud da6579132c log: move Color, printLog as private 2023-05-17 23:43:55 -04:00
Adrien Béraud 24628ff13d meson: build dhtchat, dhtscanner 2023-05-17 23:43:55 -04:00
Adrien Beraud d2f29b72c3 update version to 2.5.5 2023-04-24 18:37:47 -04:00
Adrien Beraud 546a960951 cmake: use full path for pkgconfig 2023-04-24 18:36:24 -04:00
Adrien Béraud 27978f3b9f update version to 2.5.4 2023-04-21 18:34:24 -04:00
Adrien Béraud a831afdc1e docker: build using current repo state 2023-04-21 18:33:29 -04:00
Adrien Béraud 13bb50b863 CMake: handle missing SYSTEMD_UNIT_INSTALL_DIR 2023-04-21 18:32:49 -04:00
Adrien Béraud d16d30c483 Hash: add Hash<N>::get(Hash<M>) to compute an hash from another 2023-04-21 12:00:15 -04:00
Adrien Béraud 4480436cb3 securedht: allow certificate to be stored on longId hash 2023-04-20 22:41:38 -04:00
Adrien Béraud d4114830be update version to 2.5.3 2023-04-20 22:41:38 -04:00
Adrien Béraud 9fbac2707d build/cmake: handle empty SYSTEMD_UNIT_FILE_LOCATION 2023-04-20 22:41:38 -04:00
Adrien Béraud 7cdd6948bf misc: use bootstrap.jami.net instead of ring.cx 2023-04-20 22:41:38 -04:00
Adrien Beraud d9c5ff9624 build/cmake: don't use testing on MSVC 2023-04-20 22:41:35 -04:00
Adrien Beraud 47691b8242 cmake: fix msvc build 2023-04-10 11:45:50 -04:00
Adrien Beraud adf57ce2f0 update version to 2.5.2 2023-04-10 11:39:37 -04:00
Adrien Beraud aea84977fd msgpack: support more package names 2023-04-10 11:27:38 -04:00
Adrien Beraud 2f1aef272a msgpack: support more package names 2023-04-10 11:12:51 -04:00
Adrien Beraud 76089d09a4 msgpack: support more package names 2023-04-10 10:51:14 -04:00
Adrien Beraud f88f99959b update version to 2.5.1 2023-04-05 15:57:47 -04:00
Sébastien Blin dc6aca83c6 Makefile: add node_export 2023-04-05 09:41:22 -04:00
Adrien Beraud b0e18e9ca4 docker: use dep alpine base image 2023-03-25 18:51:41 -04:00
Adrien Beraud 8516e35e5f ci/github: cleanup 2023-03-25 18:40:22 -04:00
Adrien Beraud 41eabc7261 thread pool: handle exceptions starting threads 2023-03-25 18:22:58 -04:00
Adrien Beraud 424fe61a49 dht: send large amounts of values in multiple messages 2023-03-25 17:49:16 -04:00
Adrien Beraud 02e03771d4 docker: add Alpine deps 2023-03-25 17:49:08 -04:00
Adrien Beraud e35f8c29ee ci/github: don't run ci with autotools 2023-03-25 17:17:40 -04:00
Adrien Beraud 64e3bcf0dc ci/github: use ninja with meson 2023-03-25 15:08:31 -04:00
Adrien Beraud a9f3883bfa meson: install, include public dir from tools 2023-03-25 15:04:11 -04:00
Adrien Beraud 3c3b3dc303 ci/github: add meson build 2023-03-25 14:42:46 -04:00
Adrien Beraud 970e71d215 ci/github: add meson build 2023-03-25 14:38:48 -04:00
Adrien Beraud b6552ec300 NodeExport: add missing include 2023-03-25 10:46:12 -04:00
Adrien Béraud 58bc772256 NodeExport: use SockAddr, move to separate header 2023-03-23 16:50:19 -04:00
Adrien Béraud 31af08feaa build/meson: build durl with http and tools 2023-03-23 16:50:19 -04:00
Adrien Béraud 9e60a681f3 use ostringstream instead of stringstream where possible 2023-03-23 16:50:19 -04:00
Adrien Beraud 51525d144b certificate: add public key cache 2023-03-15 20:44:29 -04:00
Adrien Beraud 965fbb43c7 more attempts to find msgpackc-cxx in a universal way 2023-03-15 12:50:06 -04:00
Adrien Béraud 133d77d985 thread pool: increase max io pool size to 512 2023-03-14 13:11:29 -04:00
Adrien Béraud 9451861f51 update version to 2.5.0 2023-03-13 13:24:21 -04:00
Adrien Béraud 4b489fb7d7 build/meson: make tools an option 2023-03-13 13:24:05 -04:00
Adrien Béraud 7fcaf19ca3 meson: add initial support 2023-03-12 23:57:32 -04:00
Adrien Béraud c51d59a3a3 Revert "cmake: update msgpack package name"
This reverts commit b9d7957bf6.
2023-03-11 22:30:19 -05:00
Adrien Béraud bcc02837d3 use proper image name for github action 2023-03-11 22:25:22 -05:00
Adrien Béraud 611017e187 add Alpine image 2023-03-11 22:21:50 -05:00
Adrien Béraud 7f7bff6a28 readme: cleanup 2023-03-11 22:18:52 -05:00
Adrien Béraud b9d7957bf6 cmake: update msgpack package name 2023-03-11 22:18:27 -05:00
Adrien Béraud fa31cec73e pkgconfig: gnutls jsoncpp, openssl are public dependencies 2023-03-09 00:37:46 -05:00
Adrien Béraud 550a8cf362 cmake: use CTest 2023-02-28 19:45:05 -05:00
Adrien Béraud 50996eaf7e build/cmake: unify static and shared build 2023-02-28 12:58:13 -05:00
Adrien Béraud 813c3b43d2 move filter 2023-02-28 12:58:13 -05:00
Adrien Béraud 4ce9292b28 proxy server: allow to ping push 2023-02-23 15:43:16 -05:00
Adrien Béraud 655aa074bf update version to 2.4.11 2023-01-31 23:47:01 -05:00
Adrien Béraud 2e9c119dca build/cmake: add SOVERSION for c binding 2023-01-31 23:45:48 -05:00
Adrien Béraud 7bf2d2a7a9 update version to 2.4.11 2023-01-30 12:05:02 -05:00
Adrien Béraud d9a97e2cec use pkg-config for gnutls, fix msgpack 2023-01-29 18:30:28 -05:00
Adrien Béraud 6395399c2d cmake: use IMPORTED_TARGET with pkg_search_module 2023-01-29 18:30:28 -05:00
Adrien Béraud e6971c196b dht: fix value edition, add unit test 2023-01-27 17:31:59 -05:00
Adrien Béraud b1009a54e3 crypto: compare public keys with longId 2023-01-27 17:31:59 -05:00
Adrien Béraud 33d73d5d55 securedht: compare public key content instead of pointer 2023-01-27 17:31:59 -05:00
Amin Bandali f42d94da59 build/cmake: Set variables needed by pkg-config files.
Up until now, these were only set by the GNU Build System in
configure.ac, and so the pkg-config files generated from CMake builds
did not have the right Libs.private and Requires.private, especially
useful when linking statically.
2023-01-26 21:31:59 -05:00
Adrien Béraud 2418b355d7 ci: build macOS with push notifications 2023-01-25 19:53:53 -05:00
Adrien Béraud 2cb57251a1 proxy client: protect resolver 2023-01-25 19:53:53 -05:00
Adrien Béraud 446da4b792 value: use move in where 2022-12-30 20:42:16 -05:00
Adrien Béraud aa958b0f1d value: inline filter 2022-12-30 20:42:14 -05:00
Adrien Béraud 58be07a8b0 infohash: add to_view() 2022-12-30 20:42:11 -05:00
Adrien Béraud 6c61ac53c4 proxy client: cleanup 2022-12-30 20:42:08 -05:00
Sébastien Blin 6e73a78a8b unifiedpush: remove unifiedpush parameter
Because there is multiple unifiedpush endpoint (ntfy.sh is one),
we should not pass it as an option to dhtnode, but use the one
provided by the user in the token (from unified push library).
2022-12-30 20:36:49 -05:00
Amin Bandali f2623bd51d build/cmake: Set opendht-c-static's OUTPUT_NAME to opendht-c. 2022-12-30 20:35:17 -05:00
Sébastien Blin d6a99d0edd proxyclient: add possibility to set the platform
This allow android to change the platform to "unifiedpush".
2022-11-17 11:46:09 -05:00
Sébastien Blin b9ccc968b2 proxyserver: add support for UnifiedPush standard
Make the proxy able to support the UnifiedPush platform, so that
applications using the proxy server can use any UnifiedPush provider.

Documentation: https://unifiedpush.org/

How to test:
+ Install a UnifiedPush provider on a device (e.g. https://ntfy.sh)
+ Run dhtnode with a proxyserver and --unifiedpush https://ntfy.sh
+ Subscribe to a random topic on ntfy (e.g. "dhtproxytest")
+ Subscribe to a hash on the DHT:
    curl -X SUBSCRIBE http://my.dht.proxy:8000/key/foo \
         -d '{"key":"dhtproxytest", "platform":"unifiedpush"}'
+ Send data on the subscribed hash

Note: the topic should be completely random.
2022-10-11 15:14:51 -04:00
Sébastien Blin 7e33c4fc76 dht_proxy_server: fix push notifications if tls is enabled
If the proxy got TLS enabled, this doesn't mean that the REST
endpoint for push notifications is also using TLS.

Also, fix an incorrect log.
2022-10-11 11:54:37 -04:00
Adrien Béraud 39bb520339 proxy server: don't send refresh notification for non-push operations 2022-09-22 12:46:54 -04:00
Sébastien Blin 18e53b9ec8 proxyserver: send correct value id to client
when searching for a value to put, the proxy server returned
a json with value->id = 0, causing the client to not refreshing
correctly the values later (when timeout-ing, the value to refresh
is not found).
2022-09-15 11:45:11 -04:00
Sébastien Blin 0b5379380a rust: update os_socketaddr to latest version 2022-09-08 11:47:02 -04:00
Sébastien Blin b800012c57 proxyserver: add topic to msgpack 2022-09-08 11:15:28 -04:00
Sébastien Blin ebeff20215 dht_proxy_server: fix permanent put
When a second permanent put request was received, we didn't call
async_wait after changing the expiration, causing push to not be
sent the second day and presence to expire on some devices after
~3 days.
2022-09-07 16:47:37 -04:00
Adrien Béraud 16ff16bd39 docker, ci: update restinio 2022-09-02 17:15:29 -04:00
Adrien Béraud 0d28a7bdab ci/github: update restinio 2022-09-02 17:14:58 -04:00
Adrien Béraud 69a1bdfc45 update version to 2.4.10 2022-09-02 17:01:23 -04:00
Adrien Béraud af7d88b057 crypto: allow to build all from std::string_view 2022-08-11 14:52:14 -04:00
Sébastien Blin abe2e018b6 Merge pull request #629 from AmarOk1412/fix/request_timeout
http: modify timeout behaviour
2022-08-11 14:41:10 -04:00
Sébastien Blin 2e79ee4f11 dht_proxy_client: fix not contextually convertible to 'bool' error
The current master is broken with clang, this fix the issue.
2022-08-11 14:30:59 -04:00
Sébastien Blin 8b022d0022 Merge branch 'master' into fix/request_timeout 2022-08-11 13:49:44 -04:00
Sébastien Blin 5399dbdfbc proxy_client: reconnect account if local ip changes
When switching between two network interfaces, local address will
change but not the public ip. This generally cause the client to
not correctly updates its candidates.
In this patch, we inject in the proxy client the local candidates
and use it to check if the network changed.
2022-08-11 12:32:44 -04:00
Sébastien Blin 0e3bca1dde http: modify timeout behaviour
In the previous version, the timeout for the connection could be
set only after async_connect while the request is sending.
This means if async_connect is slow (it can happen as if there is
an ipv6 endpoint, it can try to resolve it during dozens of seconds
before falling back on ipv4).

In this patch, it moves the timeout callback in the request. This
callback will be set just before async_connect, to be sure that we
are using the callback while connecting.
2022-08-11 11:17:30 -04:00
Adrien Béraud a992aa1f05 crypto: allow to build all from std::string_view 2022-07-28 17:11:25 -04:00
Adrien Béraud 1a267418dd thread pool: release tasks on stop 2022-07-28 17:08:08 -04:00
kkostiuk 0f8d891476 iOS: drop support for voip notifications 2022-07-25 15:26:57 -04:00
Adrien Béraud b9c79a1de5 thread pool: release tasks on stop 2022-07-20 16:35:47 -04:00
Adrien Béraud 2c7edb695f update version to 2.4.9 2022-07-18 11:43:35 -04:00
Adrien Béraud c3ad33687e misc: fix various warnings 2022-07-17 14:41:41 -04:00
Adrien Béraud 9c5e5cd7b7 proxy server: export symbols for ProxyServerConfig 2022-07-17 14:41:02 -04:00
Adrien Béraud 9048e4a31c peer discovery: cleanup, reduce memory usage 2022-07-17 14:29:54 -04:00
Adrien Béraud ba1b3c26c5 procy client: use new routes 2022-07-17 13:00:05 -04:00
Adrien Béraud c6b4e317df dhtrunner: only start peer discovery if proxy is disabled 2022-07-17 13:00:05 -04:00
Adrien Béraud 44267a72de ci/github: cleanup 2022-07-17 13:00:05 -04:00
Adrien Béraud 8c1c5d09c7 build: use Wno-deprecated 2022-07-17 13:00:05 -04:00
Adrien Béraud acadeb220a docker: add dhtnode image 2022-07-05 20:02:45 -04:00
Adrien Béraud ff7c80d416 build/dev: build in sanitize mode 2022-07-05 19:39:36 -04:00
Adrien Béraud 577f2a0645 proxy server: allow to configure address to bind 2022-07-05 19:32:29 -04:00
Adrien Béraud 48e718ffd8 ci/github: update release action 2022-07-05 16:49:54 -04:00
Adrien Béraud 07d25a4140 docker: install systemd 2022-07-05 16:48:23 -04:00
Adrien Béraud 2f7fabf1c7 ci/github: use secrets.AUTH_TOKEN 2022-07-05 16:25:42 -04:00
Adrien Béraud 60274655dd ci/github: release on tag 2022-07-05 16:20:20 -04:00
Adrien Béraud eace3d91b2 docker: add python3-virtualenv 2022-07-05 15:21:32 -04:00
Adrien Béraud 86cc41f446 docker: use Ubuntu 22.04 for LLVM build 2022-07-05 15:12:27 -04:00
Adrien Béraud 3ac5b9466a ci/github: don't build static lib 2022-07-05 15:10:02 -04:00
Adrien Béraud c95c3de136 docker: use Ubuntu 22.04 2022-07-05 15:09:07 -04:00
Adrien Béraud a865d6854c ci/github: use unique names for steps 2022-07-05 14:57:31 -04:00
Adrien Béraud 52b735b1b9 ci/github: build Python Wheel 2022-07-05 14:27:02 -04:00
Adrien Béraud f862305f78 ci/github: build LLVM Docker images 2022-07-05 14:18:24 -04:00
Adrien Béraud ce7ffbf2cd build/python: add dist target 2022-07-05 14:18:24 -04:00
Adrien Béraud 687f643059 build/python: add pyproject.toml 2022-07-05 14:18:24 -04:00
Adrien Béraud f6e3fc99e6 build/cmake: refactor library linking 2022-07-05 14:18:24 -04:00
Adrien Béraud 293662a710 proxyserver: cleanup, avoid ref-to-temporary 2022-07-05 12:16:41 -04:00
Adrien Béraud 437252bfcc proxyserver: add bundleId at the end of ProxyServerConfig 2022-07-04 18:20:32 -04:00
kkostiuk ead21d24a0 proxyserver: add application bundle id option 2022-07-04 18:17:12 -04:00
Adrien Béraud 53de63e829 update version to 2.4.8 2022-06-30 16:10:25 -04:00
Adrien Béraud 633a03d76a ios: support multiple notification types
- VOIP notifications for iOS < 14.5
- alert and background notifications for iOS >= 14.5
2022-06-30 15:44:16 -04:00
Adrien Béraud 3e5fbb0b5c Update codeql-analysis.yml 2022-06-30 10:48:25 -04:00
Adrien Béraud 6d13e301f9 Create codeql-analysis.yml 2022-06-30 10:43:18 -04:00
Adrien Béraud 4d356b6dca ci/github: add experimental docker build action 2022-06-29 16:39:49 -04:00
Adrien Béraud 44a251de56 build/autotools: don't export internal symbols 2022-06-28 16:23:40 -04:00
Adrien Béraud 1c536a4c51 update version to 2.4.7 2022-06-28 14:23:23 -04:00
Adrien Béraud 502a649f42 build/cmake: use max version for cmake_minimum_required 2022-06-28 14:22:49 -04:00
Adrien Béraud 12a52c78ac x509: make PrivateKey::getPublicKey() thread-safe 2022-06-28 14:12:45 -04:00
Adrien Béraud df2a775927 build/autotols: allow to build with header-only msgpack-cxx installation 2022-06-28 14:12:45 -04:00
Adrien Béraud 2c86ccbe15 build/pkgconfig: update project description 2022-06-28 14:12:45 -04:00
Adrien Béraud b9321a338b buiild/autotools: use -fvisibility=hidden in release mode 2022-06-28 14:12:45 -04:00
Adrien Béraud dc9a211fb0 crypto: protect Id caching with atomic_bool 2022-06-27 15:40:45 -04:00
Adrien Béraud d49b394eae crypto: cache public key id 2022-06-27 15:40:45 -04:00
Adrien Béraud f82c68a871 crypto: remove support for GnuTLS < 3.4 2022-06-27 15:40:45 -04:00
Sébastien Blin 3f4235da69 infohash: fix alignment warning 2022-06-27 15:32:50 -04:00
Sébastien Blin e259cb0847 infohash: remove optimization due to weird warnings
Current operator== creates a very weird warning about using an
uninitialized value (no warning without the reinterpret_cast).
2022-06-27 14:37:25 -04:00
Adrien Béraud 08f9b424de cmake: allow to build with header-only msgpack-cxx installation 2022-06-23 14:26:26 -04:00
Adrien Béraud d33c3515f8 update version to 2.4.6 2022-06-23 10:05:28 -04:00
Adrien Béraud 0a70b0f80f dhtrunner: don't bind port if proxy is used 2022-06-22 22:20:15 -04:00
Adrien Béraud 949cbb9fc7 sockaddr: allow to release ownership 2022-06-22 22:20:15 -04:00
Adrien Béraud 37cfbffdca dhtcnode: cleanup 2022-06-22 22:20:15 -04:00
Adrien Béraud efad2ada89 dhtrunner: make getPublicAddress const 2022-06-22 22:20:15 -04:00
Adrien Béraud d825f4e5ae misc: use std::make_unique 2022-06-08 13:14:09 -04:00
Adrien Béraud baa2a5d21c dhtrunner: remove support for running both dht and proxy client
If configured to run as a proxy client, no port will be bound and the local dht node
won't be instantiated.
2022-06-08 13:14:09 -04:00
Sébastien Blin b3f9683018 securedht: avoid to update cache if not necessary 2022-06-08 13:07:06 -04:00
Adrien Béraud 6d1819acb9 securedht: fix warning 2022-06-07 15:58:16 -04:00
Adrien Béraud d6ee44b640 dhtrunner: use consistent path for state 2022-06-07 15:38:44 -04:00
Peter Saveliev 383c53d71f python/tools: network builder v2
* `-n`: interfaces number check (1 <= ifnum <= 245)
* `-b`: turn on NDB debug logging, very chatty, dump topology DB files
* `-v`: verbose mode, print main operations
* fix code formatting (isort, flake8, black)
* code refactoring
2022-06-07 15:29:07 -04:00
Peter Saveliev 833c647524 python/tools: update network builder
Use updated pyroute2 API:

* NSPopen import from the root
* NDB instead of IPDB

No logic changes, only translated obsoleted API calls.
No code formatting.
2022-06-07 15:29:07 -04:00
Adrien Béraud 7f6f50411c autotools: fix check for CppUnit 2022-05-30 10:07:04 -04:00
Adrien Béraud 1c7089c055 github: add minimal build 2022-05-25 11:27:15 -04:00
Adrien Béraud 4641780fe6 update version to 2.4.5 2022-05-25 11:05:34 -04:00
Adrien Béraud c67df2ead3 tasks: generate compile commands 2022-05-25 11:04:59 -04:00
Adrien Béraud 5f743344e5 value: cleanup, move sign & encrypt to cpp 2022-05-25 11:04:46 -04:00
Michael Cho 56442acc84 value: fix build without jsoncpp 2022-05-25 09:49:30 -04:00
Adrien Béraud 41c9104b8a value: add inline specifier to inline methods 2022-05-05 11:33:53 -04:00
Adrien Béraud 126f0ca966 update version to 2.4.4 2022-05-03 14:46:07 -04:00
Adrien Béraud adeca7fa1f tests/dhtrunner: split count per key 2022-04-25 13:48:57 -04:00
Adrien Béraud 5527b6553d c: use void for dht_version 2022-04-25 13:43:59 -04:00
Adrien Béraud 5a6b9db60c securedht: move crypto ops to Value 2022-04-25 13:43:57 -04:00
Adrien Béraud 8f1c075897 update version to 2.4.3 2022-04-22 21:12:54 -04:00
Adrien Béraud fca11e621c tools/dhtcnode: use version arg, cleanup 2022-04-22 21:10:53 -04:00
Adrien Béraud 38a7234ae3 dht: increase max hashes to 1G 2022-04-22 21:01:36 -04:00
Adrien Béraud 115a0c683f c: add dht_infohash_from_hex_null 2022-04-22 21:00:18 -04:00
Adrien Béraud 61b7bed0f8 network engine: minor refactoring 2022-04-22 20:25:18 -04:00
Adrien Béraud dcd8ec7394 tests/dhtrunner: use unlimited store size 2022-04-22 20:25:18 -04:00
Adrien Béraud 51880afcce tests/dhtrunner: consider value expiration for counting 2022-04-22 20:25:18 -04:00
Adrien Béraud db3a4e52b2 dht: add config max_store_keys 2022-04-22 20:24:59 -04:00
Adrien Béraud af8e66b813 tools/dhtnode: show basic storage stats on "ll" 2022-04-20 16:11:21 -04:00
Adrien Béraud 9646eb9374 NodeInfo: add storage stats 2022-04-20 16:10:25 -04:00
Adrien Béraud 0df2fbe5de tools/dhtcnode: print version on startup 2022-04-20 16:09:24 -04:00
Adrien Béraud c39eceeddf tools/dhtcnode: include stdio.h before readline.h 2022-04-20 16:09:08 -04:00
Adrien Béraud 11396c315e c: add dht_version() 2022-04-20 16:08:12 -04:00
Adrien Béraud 955af06e29 dht: add getStorageLimit 2022-04-20 15:56:14 -04:00
Adrien Béraud e207e59226 tools/dhtcnode: count values in listen, add "ll" 2022-04-20 12:23:25 -04:00
Adrien Béraud 0302cee8d5 tools/dhtcnode: use memset instead of bzero 2022-04-19 17:45:14 -04:00
Adrien Béraud 8f4031c8cb update version to 2.4.2
Fix typo in 2.4.1 release
2022-04-19 15:37:46 -04:00
Adrien Béraud f72d1ffa64 update version to 2.4.1 2022-04-19 15:07:55 -04:00
Adrien Béraud 90c65fb0be tests/dhtrunner: increase put count 2022-04-19 15:07:13 -04:00
Adrien Béraud c8eb704a92 dhtrunner: prevent integer underflow in UDP rx callback 2022-04-19 14:51:24 -04:00
Adrien Béraud 4c5e26922c net: increase max queue size
Queue is also time-bounded.
Allow for larger bursts of packets.
2022-04-18 17:24:27 -04:00
Adrien Béraud 724c3e431c dht: notify listeners when value is removed because of limits 2022-04-18 17:19:32 -04:00
Adrien Béraud a9ddf49ecc storage: check size before returning oldest 2022-04-18 17:18:08 -04:00
Adrien Béraud de3dba7ce4 cmake/c: respect OPENDHT_STATIC/SHARED flags 2022-04-15 21:07:56 -04:00
Adrien Béraud cd9eda6511 tools/dhtcnode: increase shutdown pooling period 2022-04-15 21:06:45 -04:00
Adrien Béraud ed972fd365 dht: allow to store up to 64k values per hash 2022-04-15 20:12:48 -04:00
Adrien Béraud 75834fb08f dht: fix potential of-by-one largest computation, cleanup 2022-04-15 20:12:48 -04:00
Adrien Béraud 9991c976ff dht: prevent potential use-after-free in storageChanged 2022-04-15 20:12:48 -04:00
Adrien Béraud 92b08bbbc9 dht: pass value directly to storageChanged 2022-04-15 20:12:48 -04:00
Adrien Béraud 4f9b50dd60 print_addr: use ostringstream insted of stringstream 2022-04-15 19:18:24 -04:00
Adrien Béraud d6d73efa37 dht: update storage bucket on refresh 2022-04-15 19:14:12 -04:00
Adrien Béraud 19a4729bf2 test/dhtrunner: use random port, add more assertions 2022-04-14 20:12:57 -04:00
Adrien Béraud 405b8739ab dhtrunner: always call opEnded once per op 2022-04-14 20:12:55 -04:00
Adrien Béraud 7ed11a02ae c: cleanup dhtcnode 2022-04-12 17:04:55 -04:00
Adrien Béraud 3442e0acd9 build/dev: cleanup launch.json 2022-04-12 15:38:48 -04:00
Adrien Béraud 59f86861d2 docker: install libtool 2022-04-12 15:38:48 -04:00
Adrien Béraud 091d01a799 c: update dhtcnode 2022-04-12 15:38:48 -04:00
Adrien Béraud 1ed45cdcf9 c: support log to stdout/stderr 2022-04-12 15:38:48 -04:00
Adrien Béraud c40ba83cb3 c: support building with autotools 2022-04-12 15:38:48 -04:00
Adrien Béraud 7dc5aa9dfd build/dev: build in build_dev 2022-04-06 12:19:11 -04:00
Adrien Béraud 808eb688b3 tests: wait for put callback before retrieving certificate 2022-04-06 12:18:42 -04:00
Adrien Béraud 12b75a612c misc: fix various clang-tidy warnings 2022-04-06 12:18:20 -04:00
Sprite ac79dc5761 cmake: fix incorrectly linking to libatomic on macOS 2022-04-03 20:44:23 -04:00
Adrien Béraud fe6676f2e6 unit tests: run on pull request 2022-04-03 20:23:37 -04:00
Adrien Béraud 7915b987ec misc: use more string_view 2022-04-02 17:14:36 -04:00
Adrien Béraud 29bdc1a46f Revert "cmake: check atomic for RISC-V architecture"
Reason for partial revert:
Adding the atomic library is meant by CheckAtomic
to be automatic through CMAKE_REQUIRED_LIBRARIES.
2022-04-01 19:35:15 -04:00
Adrien Béraud e0d32e80fb build/dev: use gdb on linux, llvm on macOS with vscode tasks 2022-04-01 19:17:44 -04:00
Sprite e753d200c6 cmake: fix incorrect variable name 2022-04-01 11:30:47 -04:00
Sprite 85fd395c52 cmake: simplify atomic checks 2022-04-01 11:30:47 -04:00
Sprite 0f146a354b cmake: check atomic for RISC-V architecture 2022-04-01 11:30:47 -04:00
Adrien Béraud 9fcaca9232 build/dev: add tests to vscode tasks 2022-04-01 11:09:01 -04:00
Adrien Béraud 1bc65bc5f5 network engine: use string_view for better performance 2022-04-01 11:04:59 -04:00
Adrien Béraud 478d28a326 dhtnode: display total count of values for get and listen 2022-03-30 17:56:39 -04:00
Adrien Béraud 4d544d53a8 ci: use scan-build with debug mode 2022-03-29 15:07:24 -04:00
Adrien Béraud 694c44bbec value: use namespace std::literals 2022-03-29 14:54:59 -04:00
Adrien Béraud 16915ff424 build/dev: add vscode devcontainer and dhtnode task 2022-03-29 14:47:42 -04:00
Adrien Béraud a22566599c proxy client: fix building Listener map 2022-03-29 14:47:42 -04:00
Adrien Béraud f9b2285593 use string view literals where relevant 2022-03-29 14:47:01 -04:00
Adrien Béraud 9c2268fa41 fix various cppcheck warnings/errors 2022-03-29 10:15:00 -04:00
Adrien Béraud d4e6fd545a search: use const for iterator comparison 2022-03-24 21:33:51 -04:00
Adrien Béraud dfd0a09361 ci/github: add Clang static analysis 2022-03-23 18:32:26 -04:00
Adrien Béraud 0afa40820a autotools: update m4 for C++17 2022-03-23 17:49:14 -04:00
Adrien Béraud f984a6a69a ci/github: update to checkout@v3 2022-03-23 17:25:23 -04:00
Adrien Béraud b4bbc6ae38 update readme 2022-03-23 15:43:31 -04:00
Adrien Béraud bc98d974cb ci: remove travis 2022-03-23 15:43:24 -04:00
Adrien Béraud 785e54838b docker: fix Bionic (Ubuntu 18.04) support 2022-03-23 15:19:29 -04:00
Adrien Béraud bb7611fc3d docker: build with tools, peer discovery 2022-03-23 14:42:02 -04:00
Adrien Béraud f675a6bdd3 python: adapt for C++17 2022-03-23 14:28:12 -04:00
Adrien Béraud 21a71b1559 proxy server: support c++17 2022-03-23 13:35:30 -04:00
Adrien Béraud ca5455302d value: support std::string_view 2022-03-23 13:35:14 -04:00
Adrien Béraud f206a8ac9e infohash: support std::string_view 2022-03-23 13:15:37 -04:00
Adrien Béraud 0c4cec66ff update Dockerfiles, remove Travis 2022-03-23 12:04:26 -04:00
Adrien Béraud a03124d889 build: use C++17 2022-03-22 17:02:31 -04:00
Adrien Béraud 9691746fde build: remove OPENDHT_LTO 2022-03-22 17:02:31 -04:00
Adrien Béraud d7c9311014 update dockerfiles 2022-03-22 17:02:31 -04:00
Adrien Béraud 290e8594b6 update copyright 2022-03-21 11:32:56 -04:00
Adrien Béraud c59f951e5a update copyright 2022-03-10 19:51:25 -05:00
Adrien Béraud 6919a34f88 c: add license header 2022-03-10 19:49:53 -05:00
Adrien Béraud 3480bb1098 c: include errno.h 2022-03-10 19:49:00 -05:00
Adrien Béraud 27b8c870f3 c: add dht_privatekey_decrypt, handle crypto exceptions 2022-03-10 19:46:25 -05:00
Adrien Béraud be43212a73 c: add callback to dht_runner_ping 2022-03-10 19:45:29 -05:00
Adrien Béraud f0b9bc56a6 c: add dht_runner_is_running, dht_runner_get_bound_port 2022-03-10 19:43:58 -05:00
Adrien Béraud 5654816f5a dhtrunner: re-throw exception directly in init 2022-03-10 19:43:10 -05:00
Adrien Béraud b0fb476d97 dhtrunner: pass function argument by value 2022-03-10 19:42:37 -05:00
Adrien Béraud fada8d067d c: handle exception during initialization 2022-03-10 19:10:24 -05:00
Adrien Béraud 90022ee3e8 build: update version to 2.3.5 2022-03-09 14:33:25 -05:00
Adrien Béraud de68a47a16 dhtrunner: handle exception during initialization 2022-03-09 14:32:22 -05:00
Adrien Béraud 714af68292 c: specify void argument for dht_runner_new 2022-03-03 14:44:52 -05:00
Adrien Béraud e6768edaf0 build: update version to 2.3.4 2022-03-01 19:54:43 -05:00
Adrien Béraud 6145e54543 cmake: update CheckAtomic 2022-02-28 12:37:49 -05:00
Adrien Béraud ac51c2300e dht: remove canceled tasks from scheduler 2022-02-27 03:34:36 -05:00
Adrien Béraud f590980c3e infohash: include cstddef 2022-02-27 03:34:36 -05:00
Adrien Béraud 5dbade3d0b value cache: move to lambda 2022-02-26 22:16:15 -05:00
Adrien Béraud 2028d4b13e build: update version to 2.3.3 2022-02-25 23:52:26 -05:00
Adrien Béraud a6f7b49b92 build: use msgpack cmake 2022-02-25 23:52:15 -05:00
Adrien Béraud c2415f38fa dht: avoid job & search leak 2022-02-24 13:33:42 -05:00
Adrien Béraud 9cf717ab43 tools/c: adapt include directory 2022-02-22 11:49:44 -05:00
Adrien Béraud d4589bb6f6 tools/c: use new api 2022-02-22 11:49:44 -05:00
Adrien Béraud 484878aec3 c: add missing value apis 2022-02-22 11:49:44 -05:00
Adrien Béraud ace3a94e08 scheduler: remove debug log
This reverts commit 5d771e119c.
2022-02-19 16:32:07 -05:00
Adrien Béraud 5d771e119c c: install header to opendht directory 2022-02-19 12:33:31 -05:00
Adrien Béraud 8dcc695947 value: cleanup 2022-02-19 10:53:31 -05:00
Adrien Béraud 1ae28e07b6 storage: cleanup 2022-02-19 10:53:31 -05:00
Adrien Béraud 2de0737443 cmake: support some policies 2022-02-19 10:53:31 -05:00
Adrien Béraud bc32f848cb thread pool: cleanup 2022-02-19 10:53:31 -05:00
Adrien Béraud edee6d63d6 build: use msgpack without boost 2022-02-19 10:49:25 -05:00
Adrien Béraud af3f6f40bb c: install header 2022-02-19 10:48:28 -05:00
Adrien Béraud 32f72c245d dht: add max bootstrap period 2022-02-19 09:23:57 -05:00
Adrien Béraud 043ef8da72 dht: reset bootstrap period on connectivity change
Also starts a bootstrap if disconnected.
2022-02-19 09:23:57 -05:00
Adrien Béraud 6812b733bb dht: respect exponential backoff 2022-02-19 09:23:57 -05:00
Adrien Béraud 2ec28dcb83 dhtrunner: use configured logger for dropped packets 2022-02-19 09:23:57 -05:00
Adrien Béraud db000a2f88 build: update version to 2.3.2 2022-01-26 14:17:57 -05:00
Adrien Béraud 59880df60e perftest: cleanup 2022-01-26 14:16:33 -05:00
Adrien Béraud 75f1b07e7a crypto: cleanup 2022-01-26 14:16:33 -05:00
Adrien Béraud f191c4f636 storage: 0-init size_diff 2022-01-26 14:16:33 -05:00
Sébastien Blin 1b2bc7b1e3 crypto: add parameter to change Certificate's validity period
This allow to create certificate with a different validity than
10 years and be able to change the expiration of a certificate
2022-01-19 14:51:45 -05:00
Bruno Pagani a89e4d626e tests: fix building with GCC11
Fixes `error: ‘sleep_for’ is not a member of ‘std::this_thread’`
2021-11-13 12:31:17 -05:00
Sébastien Blin dbbfdaab0f proxyclient: onConnectedCallbacks must be launched if started by notif 2021-10-27 13:45:30 -04:00
Sébastien Blin 536f30ec84 opendht.cpp: fix build 2021-10-22 11:03:12 -04:00
Adrien Béraud b7aec1310c crypto: make cachedId mutable 2021-09-16 11:28:59 -04:00
Adrien Béraud 31d76b1080 github: remove argon2 build 2021-09-16 11:19:10 -04:00
Adrien Béraud 2fbafc3591 crypto: cache Certificate Id 2021-09-16 11:08:02 -04:00
Adrien Béraud 19fe34415a thread pool: fix build on MSVC 2021-09-15 16:45:56 -04:00
Sébastien Blin 2a50f85a30 proxy_server: set expiration for iOS devices 2021-09-10 10:21:31 -04:00
Sébastien Blin 26b71ab993 proxyclient: do not play with stop when resubscribing
At this point we do not care for the request. Subscribes are
instantaneous, so the request will be terminated at this point.
Changing the stop status can cause some push notifications to be
dropped if coming at this moment.
2021-09-10 10:21:31 -04:00
Sébastien Blin 04a78445c6 dht_proxy_server: increase ttl for push to 24 hours
If the android device is offline during more than 10 minutes, it
can misses push notifications and cause an incorrect state with
values not expired even if the re-subscribe is correct.
2021-09-10 10:21:31 -04:00
Adrien Béraud fa19897016 HexMap: align on 64 bits 2021-08-09 18:20:12 -04:00
Adrien Béraud 3806355509 gitignore: add DS_Store 2021-08-09 18:20:12 -04:00
Adrien Béraud 3f6738185b tests: fix testIdOps() 2021-08-05 12:42:29 -04:00
Adrien Béraud e58d09e5da dht: always display value ID as hex 2021-08-05 12:42:29 -04:00
heroku-miraheze 71cd9d22c6 Moved to Libera.chat. 2021-07-19 11:25:59 -04:00
Adrien Béraud 6c58d4f2e9 build: update version to 2.3.0 2021-06-09 16:56:19 -04:00
Adrien Béraud 4070eecea7 gitignore: add tools 2021-06-09 16:56:19 -04:00
Adrien Béraud ffb53ceb1d thread pool: add ExecutionContext 2021-06-09 13:59:33 -04:00
Adrien Béraud 0c00544798 remove embedded argon2, HTTP_PARSER_FORK 2021-06-09 13:57:10 -04:00
Adrien Béraud 471d443e4a tests: add multithread test 2021-06-07 14:45:58 -04:00
Adrien Béraud ba9a445263 securedht: clenup 2021-06-07 14:45:58 -04:00
Adrien Béraud 056bc2850b test putEncrypted(pk) 2021-06-07 14:45:58 -04:00
Adrien Béraud b668d6ad68 dhtrunner: add putEncrypted with public key 2021-06-07 14:45:58 -04:00
Adrien Béraud 29fab5560f dhtrunner: add getPublicKey() 2021-06-07 14:45:58 -04:00
Adrien Béraud 8aef63ce4a crypto: cache public key 2021-06-07 14:45:58 -04:00
Adrien Béraud 1ea7a2994e value: use non-const PublicKey 2021-06-07 14:45:58 -04:00
Adrien Béraud 208b3fa6fe SignedValue: add owner 2021-06-07 14:45:58 -04:00
Adrien Béraud d9ff95da49 Revert "dhtrunner: force execution of pending ops on shutdown"
This reverts commit c8a0b443f3.
2021-06-07 14:45:58 -04:00
Adrien Béraud c8a0b443f3 dhtrunner: force execution of pending ops on shutdown 2021-06-03 16:54:31 -04:00
Adrien Béraud 00e595d737 dht: fail if op key is null 2021-06-03 16:54:31 -04:00
Adrien Béraud a178a8f820 dht, dhtrunner: add shutdown stop argument 2021-05-31 14:43:57 -04:00
Adrien Béraud ec359d50fb proxy tester: increase shutdown timeout 2021-05-31 14:43:57 -04:00
Adrien Béraud 3c5aeccd53 dhtrunner: don't read port config if already configured 2021-05-28 13:17:25 -04:00
Adrien Béraud f99fe16a46 subset: use const ref 2021-05-28 13:17:25 -04:00
Adrien Béraud 43dc7cf222 sockaddr: fix warning 2021-05-28 13:17:25 -04:00
Sébastien Blin ad549098f8 proxyServer: use lockListener_ to protect pushListeners_ 2021-05-25 16:05:03 -04:00
Adrien Béraud 6795ba3838 cmake: fix building with peer discovery and without http 2021-05-20 15:49:11 -04:00
Adrien Béraud efb5f8e36a crypto: avoid generating 0 or negative certificate serial numbers 2021-05-15 01:08:07 -04:00
JUAN MÉNDEZ 8aa24f1289 Add python bindings for TypeValue
Signed-off-by: JUAN MÉNDEZ <vpsink@gmail.com>
2021-05-10 14:54:16 -04:00
Sébastien Blin 14d882d220 http: add support for TCP keep alive and handle broken pipes 2021-05-03 10:09:31 -04:00
Adrien Béraud f4c6c54a08 unit tests: add test for identityAnnouncedCb, putEncrypted 2021-04-16 16:11:02 -04:00
Adrien Béraud 4dc7a5ca0a dhtrunner: log warning if calling run() while already running 2021-04-16 15:54:45 -04:00
Adrien Béraud 40fdd04cb3 dht: cleanup handling of onConnectCallback 2021-04-16 15:13:07 -04:00
Adrien Béraud a24dedd225 proxy client: move callbacks to lambda 2021-04-16 15:04:19 -04:00
Adrien Béraud ae2445fd07 proxy client: schedule connectCallbacks in callback queue 2021-04-16 15:01:23 -04:00
Adrien Béraud 7ba53cb4b3 proxy client: use unique_ptr for timers 2021-04-16 15:00:48 -04:00
Adrien Béraud fbff8389c5 dhtrunner: build proxy with identity callback, logger 2021-04-16 14:45:33 -04:00
Adrien Béraud 827fdacc4b securedht: build with logger 2021-04-16 14:45:14 -04:00
Adrien Béraud 3efc27e9f3 securedht: avoid use-after-free 2021-04-16 14:42:45 -04:00
Adrien Béraud f7104199e3 securedht: fix typo 2021-04-15 12:50:31 -04:00
Adrien Béraud 5c0fbf7e68 securedht: pass IdentityAnnouncedCb by value, don't store 2021-04-15 12:47:18 -04:00
Adrien Béraud 55c595330a securedht: use onConnect callback 2021-04-15 12:36:57 -04:00
Adrien Béraud d3fc75589f dht: add onConnect callback 2021-04-15 12:36:03 -04:00
Sébastien Blin f8605f45f7 securedht: add IdentityAnnouncedCb to detect when identity is announced 2021-04-14 18:55:22 -04:00
Adrien Béraud d541b17fe1 sockaddr: cleanup 2021-04-13 21:35:31 -04:00
Adrien Béraud 29eb1d97f8 tests: add unit test for Dhtrunner::run(config, context) 2021-04-13 21:35:31 -04:00
Adrien Béraud 623b1c4585 dhtrunner: add async version of getPublicAddress 2021-04-13 21:35:31 -04:00
Adrien Béraud 74f7d7811e dhtrunner: use default bound address if not set 2021-04-13 21:35:31 -04:00
Adrien Béraud 7774331a20 dhtrunner: allow to provide address to bind in configuration 2021-04-13 21:35:31 -04:00
Sébastien Blin aae30c5891 docker: update restinio version 2021-04-12 11:55:45 -04:00
Adrien Béraud 41760e4b65 ocsp response: improve exception message 2021-03-25 00:02:51 -04:00
Adrien Béraud 9ca0de250b tests: add testOcsp 2021-03-24 23:29:53 -04:00
Adrien Béraud d0156b4637 crypto: add OcspRequest 2021-03-24 23:29:18 -04:00
Adrien Béraud f6cca88593 ocsp response: verifyDirect now returns revocation status 2021-03-24 23:11:59 -04:00
Adrien Béraud c6da80573e ocsp: fix leak 2021-03-24 23:09:24 -04:00
Adrien Béraud 5527869d13 Revert "dht: don't send unnecessary findNode"
This reverts commit 0b4caeda73.
2021-03-22 13:55:04 -04:00
Adrien Béraud 5c599b2feb ocsp: check the appropriate field for status 2021-03-22 13:54:39 -04:00
Adrien Béraud 122d814a33 TrustRequest: add default empty parameter for conversationId 2021-03-18 17:08:54 -04:00
Adrien Béraud a1a8adbe4b update to version 2.2.0 2021-03-18 10:39:59 -04:00
Adrien Béraud 5a370cabb5 crypto: disable legacy encryption
Require OpenDHT 2.x to decrypt encrypted data
2021-03-18 10:37:28 -04:00
Adrien Béraud 639ae26ac1 PEMCache: cleanup 2021-03-18 10:35:35 -04:00
Adrien Béraud 896b6de60c dht: remove default constructor 2021-03-18 10:35:35 -04:00
Adrien Béraud d025f9d1b5 crypto: add methods to sign/decrypt raw data 2021-03-18 10:35:35 -04:00
Sébastien Blin 0b029bc0bf types: add conversationId to TrustRequest 2021-03-18 09:13:43 -04:00
Adrien Béraud 2256434ec7 dht: add inspection methods 2021-03-09 17:43:57 -05:00
Adrien Béraud 0b4caeda73 dht: don't send unnecessary findNode 2021-03-09 17:43:35 -05:00
Adrien Béraud 18a1a1c47f callbacks: move function argument to lambda 2021-03-09 17:43:35 -05:00
Sébastien Blin 6702956521 infohash: add xor operator 2021-03-09 17:27:04 -05:00
Lucas Dias c996220685 network_engine::process could throw an exception in message type MessageType::ValueUpdate if rsocket does not exist. processMessage called process out of try-catch 2021-01-19 12:55:02 -05:00
Adrien Béraud df85abfabe cmake: use THREADS_PREFER_PTHREAD_FLAG 2020-12-30 10:32:27 -05:00
Bruno Pagani e6c760ec6b Fix use of OPENDHT_SYSTEMD_UNIT_FILE_LOCATION
For some reason 1778f64048 reverted part of 4d70c214b0

This commit fixes that.
2020-12-22 18:03:31 -05:00
Adrien Béraud a77dc855f0 OCSP: use RFC-mandated parameters
* use 32 bytes nounce
* use SHA-1 for the certificate ID
2020-12-17 12:35:33 -05:00
Adrien Béraud 2524e167d9 tests: add test for toHex 2020-12-08 14:39:25 -05:00
Adrien Béraud 638d1c91f1 toHex: use proper std::string constructor 2020-12-08 14:34:33 -05:00
Amin Bandali ba4058dfd9 cmake: fix atomic check, hopefully 2020-12-04 16:55:03 -05:00
Adrien Béraud ab90a170af http: checkOcsp is void 2020-11-24 16:16:11 -05:00
Adrien Béraud f780499241 ocsp response: add string constructor 2020-11-24 16:11:02 -05:00
Adrien Béraud 91709bc999 proxytester: disable https for now 2020-11-24 15:59:42 -05:00
Adrien Béraud 72725dc5c1 http: make OCSP check optional 2020-11-24 15:34:19 -05:00
Adrien Béraud 3098439db2 proxy client: set CA for every request 2020-11-24 15:22:14 -05:00
Adrien Béraud 6441a09e09 ocsp: fix memleaks 2020-11-20 14:42:55 -05:00
Adrien Béraud 57e7699723 update to version 2.1.9 2020-11-20 11:39:01 -05:00
Adrien Béraud 17e1cfbbbe crypto: export OCSP request as string 2020-11-20 11:38:11 -05:00
Adrien Béraud bfe1311ca8 crypto: cleanup OCSP result check 2020-11-19 17:12:54 -05:00
Adrien Béraud 537a1650f2 infohash: add toHex(const std::string&) 2020-11-19 17:07:06 -05:00
Kateryna Kostiuk 8c852c20e7 os_cert: do not load for iOS 2020-11-18 15:47:10 -05:00
Adrien Béraud 1da46382d3 cmake: add missing include in CheckAtomic 2020-11-17 16:30:36 -05:00
Adrien Béraud 4953888af3 update to version 2.1.8 2020-11-17 16:24:30 -05:00
Adrien Béraud 22de868c6c cmake: check for 64 bits atomic support 2020-11-17 16:23:43 -05:00
Adrien Béraud 0998707e03 automake: add os_cert 2020-11-17 15:48:13 -05:00
Adrien Béraud b5fcd49b7b os_cert: only build with http 2020-11-17 15:20:46 -05:00
Adrien Béraud 81cdd9650b os_cert: cleanup 2020-11-17 14:37:03 -05:00
Adrien Béraud e028cea687 os_cert: only define timegm on Windows 2020-11-17 13:15:22 -05:00
Adrien Béraud 17ed4a9e26 os_cert: include crypto/x509 from OpenSSL 3.0 2020-11-17 12:27:41 -05:00
Adrien Béraud 3ff318b9e4 os_cert: cleanup detection of ASN1_time_parse 2020-11-17 11:35:07 -05:00
Adrien Béraud 0c11c25c66 infohash: make toHex inline 2020-11-17 11:34:40 -05:00
Adrien Béraud 0d31139402 crypto: throw in case of certificate generation error 2020-11-16 17:35:00 -05:00
Adrien Béraud e970cac4d7 infohash: expose toHex 2020-11-16 14:58:35 -05:00
Adrien Béraud 7c8eecd745 update to version 2.1.7 2020-11-15 17:25:12 -05:00
Adrien Béraud 4d87c2267b os_cert: build ASN1_time_parse if not libressl 2020-11-15 00:42:29 -05:00
Adrien Béraud 88b2439deb http: use string for body, fix log arguments 2020-11-14 18:07:05 -05:00
Federico Ceratto 766a06c69a Remove line 2020-11-13 09:33:11 -05:00
Federico Ceratto aa502553bb Put @bindir@ back 2020-11-13 09:33:11 -05:00
Federico Ceratto 05ff4205d2 Configure dhtnode service sandboxing
Tested on Debian Sid
2020-11-13 09:33:11 -05:00
Adrien Béraud 9d937bb277 http: factor setting CA source 2020-11-12 19:00:02 -05:00
Andreas Traczyk 1621515b3c http: use local cache to store pre-decoded certs
- pre-decode certs from DER->PEM and store them so http connections
  can add them the ssl context x509 store
- fixes the windows build by adding the crypto/x509 header
2020-11-12 18:58:18 -05:00
Adrien Béraud 30261e70ad cache: cleanup, small perf improvements 2020-11-12 12:53:57 -05:00
Adrien Béraud c2a4f667a7 http: look for CA path in env 2020-11-12 12:53:03 -05:00
Adrien Béraud 05b95331d8 cmake: add CheckAtomic 2020-11-04 16:24:52 -05:00
Kateryna Kostiuk c986f44704 http: fix linking on macOS 2020-10-29 14:04:45 -04:00
Adrien Béraud 7f62073d93 cmake: add proper ssl build/link flags 2020-10-28 16:51:37 -04:00
Adrien Béraud 1a562962ba cmake: look for asio 2020-10-28 14:49:54 -04:00
Adrien Béraud 065be0621d ssl: fix build on non-MSVC platforms 2020-10-28 14:06:08 -04:00
Andreas Traczyk 6c085ed975 http: load ca certs from platform specific stores into x509 store 2020-10-28 12:23:53 -04:00
Adrien Béraud 4c5776f9d2 http: add support for OCSP verification 2020-10-28 12:23:53 -04:00
Adrien Béraud c84fac6823 http: add Request::await 2020-10-28 12:23:53 -04:00
Andreas Traczyk 1778f64048 cmake: remove vcxproj files and use cmake on windows 2020-10-20 13:04:26 -04:00
Sébastien Blin d1000635dd dht_proxy_client: do not launch loopSignal_ while searchLock_ is locked 2020-10-08 18:34:21 -04:00
Adrien Béraud 1273b062e1 update to version 2.1.6 2020-09-24 17:09:10 -04:00
Adrien Béraud 961b96ca3d update to version 2.1.5 2020-09-23 15:00:48 -04:00
Adrien Béraud bcb29c3588 build/cmake: support new pkgconfig macros 2020-09-23 14:45:04 -04:00
Sébastien Blin 5d9395b16f stats: use /node/stats 2020-09-18 10:40:12 -04:00
Sébastien Blin 23a75a3f50 proxyclient: do not lock loopSignal_ 2020-09-15 10:54:44 -04:00
Adrien Béraud 7b87d32c0a python scanner: update for new APIs 2020-09-01 17:33:08 -04:00
Adrien Béraud d5f4f81566 http tester: adapt to API changes 2020-09-01 16:26:52 -04:00
Adrien Béraud a69863da4e search: avoid comparing invalidated iterators 2020-09-01 15:55:43 -04:00
Doron Behar 4d70c214b0 Enable to configure systemd unit installation dir 2020-08-22 10:24:37 -04:00
Doron Behar 11afc2b468 Enable to disable network tests 2020-08-02 11:32:28 -04:00
Adrien Béraud 879e4f4e02 tests/http: update for new API 2020-07-06 10:37:20 -04:00
Adrien Béraud b5b4eea253 dht: reschedule search step 2020-07-06 10:26:08 -04:00
Adrien Béraud 67adc09d52 http: add non-Linux exception for current libressl limitation 2020-07-03 16:33:12 -04:00
Adrien Béraud e2b39dd3a0 http/request: make terminate public 2020-06-30 10:42:49 -04:00
Adrien Béraud 9dc0ce7392 http: cleanup 2020-06-29 23:06:42 -04:00
Adrien Béraud 1a025c5cea http: log peer subject name during TLS certificate verification 2020-06-29 20:52:53 -04:00
Adrien Béraud 732e9af439 http: set SNI when using TLS 2020-06-29 19:17:16 -04:00
Adrien Béraud 4e5666fc3a http: add verify path for Android 2020-06-29 19:17:16 -04:00
Sébastien Blin b41f5b04f5 proxyclient: only restart listeners when connected
restartListeners() must be called only when the proxy is connected. Else, the
client will receive a lot of http errors
2020-06-29 15:18:58 -04:00
Adrien Béraud cfa21df8b3 http: cleanup, always verify host in TLS mode 2020-06-29 12:12:22 -04:00
Adrien Béraud 6ac451a5de update to version 2.1.4 2020-06-19 15:45:26 -04:00
Adrien Béraud 9efb8bb662 dockerfile: build with proxy 2020-06-19 15:44:47 -04:00
Adrien Béraud f0aee6f909 docker: update restinio 2020-06-19 15:44:35 -04:00
Adrien Béraud f72bfc9df2 http: use hostname for certificate authentication 2020-06-19 15:21:34 -04:00
Adrien Béraud c9ebfd1119 tests: cleanup 2020-06-15 18:33:04 -04:00
Adrien Béraud cf1874baaa crypto: free token before return 2020-06-15 18:25:23 -04:00
Adrien Béraud c221cfdafe http/Request: add get json constructor 2020-06-15 17:47:32 -04:00
Adrien Béraud 31b84e6d92 thread pool: unlock after notify 2020-06-15 17:47:32 -04:00
Adrien Béraud ae05bc8ea5 crypto: avoid goto 2020-06-15 17:47:32 -04:00
Seva acbf7cfcf0 crypto: cleanup ocsp api & tests 2020-06-15 17:47:32 -04:00
Seva 8250116946 crypto: embed ocsp response into class 2020-06-15 17:47:32 -04:00
Seva 45e9458373 crypto: add get ocsp response in readable format 2020-06-15 17:47:32 -04:00
Seva 2623b86274 crypto/cert: add generate ocsp request & verify response 2020-06-15 17:47:32 -04:00
Seva 2e1dda8189 crypto: enable test certificate serial number 2020-06-15 17:47:32 -04:00
Seva e26256b819 crypto: add get ocsp response certificate status 2020-06-15 17:47:32 -04:00
Seva 18e59ad7c8 crypto: test certificate serial number 2020-06-15 17:47:32 -04:00
Seva a7a3d23f50 crypto: add get serial number of cert. 2020-06-15 17:47:32 -04:00
Adrien Béraud 323a2b5093 dht: move socket to SearchNode 2020-06-15 17:46:43 -04:00
Adrien Béraud 563811ebf8 dht: add error handler for sendRefreshValue 2020-06-15 17:46:43 -04:00
Adrien Béraud 190c7f2063 network engine: complete request in case of error 2020-06-15 17:46:43 -04:00
Adrien Béraud 6158751a32 network engine: auth success in case of refresh 2020-06-12 02:51:08 -04:00
Adrien Béraud 4c7d126782 network engine: fix sendError with non-default netId 2020-06-11 15:10:48 -04:00
Sébastien Blin 3e24ea1212 rng.h: fix build 2020-05-25 18:50:35 -04:00
Adrien Béraud a7ac979da6 update to version 2.1.3 2020-05-25 15:18:51 -04:00
Adrien Béraud 87f48f0a28 getSeededRandomEngine: retry in case of exception 2020-05-25 15:18:51 -04:00
Adrien Béraud 15586a3cb1 travis: update configuration 2020-05-24 14:24:30 -04:00
Adrien Béraud 2195c0ed3e proxy server: allow build without push notification support 2020-05-24 14:11:13 -04:00
Adrien Béraud af1e904895 dockerfile: add pkg-config 2020-05-24 11:52:56 -04:00
Adrien Béraud a4fbf7ced0 docker: update 2020-05-24 02:04:45 -04:00
Adrien Béraud 1b7e0679d5 proxy server: check push token when loading state 2020-05-24 02:04:45 -04:00
Sébastien Blin 9292c1116c proxy: count permanent put values by hash in stats 2020-05-24 01:25:31 -04:00
Adrien Béraud a2afb5bb31 network engine: send confirmation for value update 2020-05-24 00:20:27 -04:00
Adrien Béraud 15fbfdebcc dht: only load id if set in configuration 2020-05-22 12:28:25 -04:00
Adrien Béraud 15eb221cd1 dht: save id, port when saving state 2020-05-22 12:15:10 -04:00
Adrien Béraud 7d3781acc8 dht: use pseudo-rng for ID generation 2020-05-22 12:14:47 -04:00
Sébastien Blin f3100a6752 proxyclient: avoid to generate tokens with \0 2020-05-20 12:23:59 -04:00
Adrien Béraud e3cd2a9d02 proxy server: add missing listener type 2020-05-19 19:52:51 -04:00
Adrien Béraud 19ccc3a327 proxy server: restart timers on resubscribe 2020-05-19 19:50:20 -04:00
Adrien Béraud 4587c0925f utils: always check length in findMapValue 2020-05-19 19:50:20 -04:00
Adrien Béraud fc96245891 cmake: cleanup 2020-05-19 19:50:20 -04:00
Adrien Béraud a27815b4a9 proxy server: persist ops on disk 2020-05-19 19:50:20 -04:00
Adrien Béraud 5daaf372b4 proxyserver: generate id before put 2020-05-11 12:31:07 -04:00
Sébastien Blin cc51d2684c proxy: only keep last total stat
The rest is not needed.
2020-05-05 17:00:07 -04:00
Sébastien Blin 28b5893239 listener: fully migrate to requests
This patch migrates tellListenerRefreshed and tellListenerExpired
to the new behavior
2020-05-05 10:38:03 -04:00
Adrien Béraud c754b5cfce update to version 2.1.0 2020-04-30 14:58:25 -04:00
Adrien Béraud b0c1249710 network engine: check for logger 2020-04-29 20:23:19 -04:00
Adrien Béraud c41ee417fb tools: cleanup 2020-04-29 19:22:24 -04:00
Adrien Béraud 47ba0415ca tools: use bootstrap split/default port from dht 2020-04-29 17:12:11 -04:00
Adrien Béraud 99857e25cc dhtnode: use async version of getNodeInfo 2020-04-29 16:13:36 -04:00
Adrien Béraud 7f832ba9d5 NodeInfo: add bound ports 2020-04-29 16:00:02 -04:00
Sébastien Blin 8c4a894f93 misc: replace TransId to Tid 2020-04-28 13:55:29 -04:00
Sébastien Blin dd3de412fb dht: move updateValues logic into network_engine 2020-04-28 13:55:29 -04:00
Sébastien Blin 4ad5e6c9ba misc: clean 2020-04-28 13:55:29 -04:00
Sébastien Blin b445818521 tests: enable test for listening with lot of values 2020-04-28 13:55:29 -04:00
Sébastien Blin 7c14ea1730 network_engine: fix pack for sendUpdateValues 2020-04-28 13:55:29 -04:00
Sébastien Blin 7bf9f861a5 dht: send update values for listeners 2020-04-28 13:55:29 -04:00
Sébastien Blin 4cf5c87761 network_engin: move to pack(socket) 2020-04-28 13:55:29 -04:00
Sébastien Blin e1c6fec581 dht: starts to add update and version support 2020-04-28 13:55:29 -04:00
Sébastien Blin 31da5b91fa [WIP]net: add updateValues to replace Listen operations
Actually, packets are not retransmitted for listen operations. This
leads to some problems when they are already several values present
at one hash. Ideally, packets should be transmitted inside a request
to avoid packet loss and get all datas.

This patch breaks the compatibility with previous versions
2020-04-28 13:55:29 -04:00
Adrien Béraud 01bcb1a750 network engine: completely remove TransId 2020-04-24 18:46:46 -04:00
Adrien Béraud 35348bf77f dht: use default port for bootstraping 2020-04-24 17:45:40 -04:00
Adrien Béraud ae58ea8312 search: expire only after candidate expiration 2020-04-24 16:32:07 -04:00
Adrien Béraud f30d21e96f move bootstrap logic from DhtRunner to Dht 2020-04-24 16:32:07 -04:00
Vladimir Stoiakin 7628aab230 opendht.pc: change -lpthread to -pthread 2020-04-19 14:13:56 -04:00
Adrien Béraud f4cba56b3c dht: optimize getStatus() 2020-04-17 02:09:57 -04:00
Adrien Béraud 7155dc4fb7 stats: add search, cached node count 2020-04-16 02:08:00 -04:00
Adrien Béraud c961e2e99f dht: allow to configure max searches & store size 2020-04-16 02:08:00 -04:00
Adrien Béraud 2fb8e1c7ee Update README.md 2020-04-12 15:56:23 -04:00
Vladimir Stoiakin 4d689ef51a update opendht.pc 2020-04-10 09:24:31 -04:00
Adrien Béraud face9f12b2 request: cleanup 2020-03-30 18:39:28 -04:00
Adrien Béraud c92f553a24 network engine: retransmit value parts 2020-03-30 17:54:50 -04:00
Adrien Béraud 8564cf3b86 tests/dhtrunner: test put/listen for large values 2020-03-30 17:54:47 -04:00
Adrien Béraud e7c810d5d6 value: don't print large values 2020-03-30 17:54:42 -04:00
Adrien Béraud e76c80b8be tests: disable rate limiting 2020-03-30 17:54:34 -04:00
Adrien Béraud 69f8969883 utils: fix build in 32 bit 2020-03-25 23:39:54 -04:00
Adrien Béraud bc200cd76d utils: fix indentation 2020-03-25 23:08:39 -04:00
Adrien Béraud 187c7dbce3 http: preserve headers during redirect 2020-03-25 23:00:16 -04:00
Adrien Béraud 81131f1c4e utils: check time bounds 2020-03-25 23:00:16 -04:00
Adrien Béraud ce9445a93f pseudo-rng: improve fallback seed 2020-03-25 23:00:16 -04:00
Adrien Béraud 16372cba0c Update README.md 2020-03-21 12:45:11 -04:00
Adrien Béraud a2cbef315a dht: avoid crash in persistent put when logging 2020-02-22 19:59:36 -05:00
Adrien Béraud bc7c43dfd1 value: cleanup 2020-02-22 19:59:36 -05:00
Adrien Béraud 771b300622 durl: cleanup, fix on macOS 2020-02-22 19:59:36 -05:00
Adrien Béraud 5ffb5c628d dht: avoid use-after-free when sending probe query 2020-02-14 13:52:55 -05:00
Adrien Béraud cfa4ce61b4 cmake: add option to build http without proxy 2020-02-13 16:55:59 -05:00
Adrien Béraud 5f15043f03 tools: add durl for http client testing 2020-02-12 16:46:06 -05:00
Adrien Béraud f445b2536d http: handle redirects 2020-02-12 16:45:25 -05:00
Adrien Béraud 6c2f791c4d network utils: don't block on mutex in rx thread (2) 2020-02-11 17:07:53 -05:00
Adrien Béraud 780726c66d network utils: don't block on mutex in rx thread 2020-02-11 16:20:30 -05:00
Adrien Béraud 8703cfdaee dht: erase announce form search nodes on cancelPut 2020-02-09 15:15:47 -05:00
Adrien Béraud 1c536cbf5e permanent put: set clientId 2020-02-09 10:34:42 -05:00
Adrien Béraud a39e2443a0 dht: reuse probe query, avoid leak 2020-02-09 00:51:58 -05:00
Adrien Béraud 57528e7aab scheduler: don't sync time on run 2020-02-08 22:04:50 -05:00
Adrien Béraud e9d70f204a tools: add perftest 2020-02-08 22:04:41 -05:00
Adrien Béraud ceb35c05c1 securedht: add option to disable cache 2020-02-08 20:27:44 -05:00
Adrien Béraud 55ccec5871 securedht: putEncrypted, putSigned fail if no key 2020-02-07 00:54:18 -05:00
Adrien Béraud 95028e3770 dht: always use pseudo-RNG for non-critical random numbers 2020-02-07 00:36:42 -05:00
Adrien Béraud abede1e72a pingpong: print execution time 2020-02-07 00:21:13 -05:00
Adrien Béraud 859d8dc9cf proxy server: check clientId for merging put 2020-02-07 00:21:13 -05:00
Sébastien Blin 1a67140463 proxyserver: enable keep alive packets 2020-02-06 14:15:47 -05:00
Adrien Béraud 9ae3d3c4d4 proxy: move info if possible 2020-02-05 14:25:03 -05:00
Adrien Béraud d3508c80f5 dhtrunner: take bound address by reference 2020-02-04 16:21:24 -05:00
Adrien Béraud 6c43efa4da http: use proper target in requests 2020-02-04 16:21:24 -05:00
Sébastien Blin c5c4c217dd tools: add script for following dhtproxy's stats 2020-01-28 16:27:20 -05:00
Sébastien Blin 5cfcf4861d proxyserver: set permanent put pushToken 2020-01-28 16:27:20 -05:00
Adrien Béraud 8597267c63 dht: add 'public stable' node configuration 2020-01-27 16:27:21 -05:00
Adrien Béraud 1b81d707f3 value: fix potential crash in contentEquals 2020-01-27 12:13:17 -05:00
Adrien Béraud 7791163d49 proxy: receive values in blocks 2020-01-22 16:02:26 -05:00
Adrien Béraud 56db1bba19 proxy server: merge identical put requests 2020-01-22 15:56:48 -05:00
Adrien Béraud a7092c2dc7 dhtnode: show value id in put response 2020-01-22 13:15:37 -05:00
Adrien Béraud fc95c85983 proxy server: send values in batches 2020-01-22 13:15:37 -05:00
Adrien Béraud 3490b19fe3 proxy client: cleanup 2020-01-22 13:15:37 -05:00
Adrien Béraud 4a20814d59 proxy client: let the server choose the value id 2020-01-22 13:15:37 -05:00
Adrien Béraud 707fb39975 net: fix sending query in sendGetValues 2020-01-20 12:15:33 -05:00
Adrien Béraud cbb2406a12 utils: improve duration display 2020-01-19 17:47:54 -05:00
Adrien Béraud 7764620460 proxy client: fix warning 2020-01-19 14:32:57 -05:00
Adrien Béraud 5af0f0c3d0 proxy server: flush response after all values are sent 2020-01-19 14:32:57 -05:00
Adrien Béraud ec8beec427 proxy server: update stats on startup 2020-01-19 14:32:57 -05:00
Adrien Béraud 7b8ebbc54d proxy server: catch more exceptions, cleanup 2020-01-19 14:32:57 -05:00
Adrien Béraud dc46c2274c net: exponential backoff, randomize packet expiration time 2020-01-19 14:32:57 -05:00
Adrien Béraud 052ed1f58c proxy server: handlePrintStats on startup 2020-01-18 22:20:01 -05:00
Adrien Béraud 9096f650f5 dht: increase default max request rate to 8k req/s 2020-01-18 19:54:54 -05:00
Adrien Béraud 900655b11f dht: give current time through periodic 2020-01-18 13:58:22 -05:00
Adrien Béraud 2900b1d17f net: limit recycled packet queue max size 2020-01-18 13:56:50 -05:00
Adrien Béraud 69e71dbeaa SecureDht: cleanup 2020-01-17 15:58:22 -05:00
Adrien Béraud 3793423b2f dht: log cleanup 2020-01-17 15:57:32 -05:00
Adrien Béraud b012878488 dhtrunner: set logger in setLogger 2020-01-17 15:57:32 -05:00
Adrien Béraud c1005fa334 request: free message memory on clear 2020-01-17 15:17:35 -05:00
Adrien Béraud 0f9f623b31 dht: use unique_ptr for SearchNode 2020-01-17 12:47:14 -05:00
Adrien Béraud 2cfebdf9fa net: use packet lists and recycle old packet structures 2020-01-17 12:26:03 -05:00
Adrien Béraud 481b1cb3b4 dht: use pseudo-random generator for value ids 2020-01-16 13:51:51 -05:00
Adrien Béraud 7f1d960a56 dhtrunner: add async/non-blocking version of getNodeInfo 2020-01-16 13:24:37 -05:00
Adrien Béraud 91e1e942ab Update peer_discovery.cpp 2020-01-15 23:16:36 -05:00
Adrien Béraud ae89365f23 Update peer_discovery.cpp 2020-01-15 23:16:36 -05:00
Adrien Béraud 93cd8d541c Update peer_discovery.cpp 2020-01-15 23:16:36 -05:00
Paymon 9487bc5e42 implement connectivity change in peer discovery
this makes peer discovery pub/sub on connectivity change, it aims to
make peer discovery more energy efficient.

also, stop echo'ing.

TODO:
in its current implementation however, peer_discovery operates in the
dark; it doesn't know routes available to it (v4 vs v6); nor does it
know of the state of the link(s) (UP vs. DOWN) and therefore it merely
tries to, on connectivity change, (re)pub/sub on previous ip version
routes.

IDEA:
open an interface to kernel so that peer discovery, and perhaps others,
can learn about the routes available to them.

don't leave

add query() and direct publish(endpoint)

check if peer discovery was request (run and compile time)

add try/catch routine to DomainPeerDiscovery's constructor
2020-01-15 23:16:36 -05:00
Adrien Béraud 10d48137a9 proxy server: update stats on node info 2020-01-15 17:04:12 -05:00
Adrien Béraud 5b15fdeeef proxy server: use shared_ptr for stats, remove statsMutex_ 2020-01-15 13:54:24 -05:00
Adrien Béraud 3ba43c80a2 http: add weak_ptr to Request in Response 2020-01-15 11:45:26 -05:00
Adrien Béraud 16333f4224 http: add mutex to Request, Connection 2020-01-15 11:45:03 -05:00
Adrien Béraud 0864ac9a39 proxy server: handle put session id provided after first request 2020-01-10 12:26:57 -05:00
Adrien Béraud 616d6fe4b8 update copyright date 2020-01-03 15:14:32 -05:00
Adrien Béraud dea4b202bf proxy server: make json type explicit 2020-01-03 15:10:22 -05:00
Adrien Béraud dc2f354652 proxy: use timestamps to handle reordered notifications 2020-01-03 14:47:22 -05:00
Sébastien Blin 87041e301f proxyclient: refresh put on restartListeners
There is no need to check if the put is ok or not before refreshing it. Indeed,
the first successful put will make the ok flag to true. But, if an expiration
is missed (when not connected for example), the put will not be refreshed when
the connectivity will change (moreover, server and client can have different
timeouts).
2020-01-03 11:39:05 -05:00
Sébastien Blin 189f94442e dhtproxyclient: setPushNotification before first permanent put
When SecureDHT is initialized, a permanent put is done to announce the node
and then the push token is set. This means the the first permanent put will not
get expirations notification because it's considered as a non push device's put.
We should inject the push token as soon as possible.
2020-01-03 11:39:05 -05:00
Adrien Béraud c5c3695612 logger: use shared_ptr 2019-12-19 15:12:23 -05:00
Adrien Béraud 6a7ad871e2 value: toString prints raw data if text/plain 2019-12-19 15:12:23 -05:00
Adrien Béraud 99890fca64 proxy server: update sessionId when necessary 2019-12-19 14:20:03 -05:00
Adrien Béraud 2dbf57d36b Update README.md 2019-12-16 23:42:31 -05:00
Adrien Béraud 5438d50578 proxy: add session token 2019-12-16 16:37:07 -05:00
Adrien Béraud 548255073f docker: build c bindings, use asio 1.12 2019-12-16 12:22:05 -05:00
Adrien Béraud abaf091772 c binding: fix build 2019-12-16 11:41:49 -05:00
Adrien Béraud 7094b79714 crypto: add PublicKey::pack(uint8_t* out, size_t* out_len) 2019-12-14 15:29:42 -05:00
Adrien Béraud 1f672773ba proxy server: respect value priority for push notifications 2019-12-14 13:02:07 -05:00
Adrien Béraud 374fdd6cc9 proxy: send normal priority push message for value expiration 2019-12-14 13:02:07 -05:00
Adrien Béraud 54b1314ab8 value: optimize json parsing 2019-12-14 13:02:07 -05:00
Adrien Béraud 51c35d8b54 value: add priority 2019-12-14 13:02:07 -05:00
Adrien Béraud fea736428e msgpack: take const reference in unpack 2019-12-14 13:01:24 -05:00
Adrien Béraud 2d358adf0e utils: add findMapValue(string) 2019-12-14 13:00:13 -05:00
Adrien Béraud 26c2e16a42 value: optimize json parsing 2019-12-14 00:41:41 -05:00
Adrien Béraud e8b385c220 utils: optimize findMapValue 2019-12-13 23:57:22 -05:00
Adrien Béraud c1e2a368a8 docker: add ssl, install http-parser to /usr 2019-12-13 16:24:46 -05:00
Adrien Béraud c62f27c929 tools: add missing include 2019-12-12 17:00:35 -05:00
Adrien Béraud ec0c3d4d25 docker: build asio without tests and examples 2019-12-12 15:04:45 -05:00
Adrien Béraud 17a1178054 tools: add missing includes for indexation support 2019-12-12 15:00:17 -05:00
Adrien Béraud 6256c576c9 configure: cleanup 2019-12-12 14:51:59 -05:00
Adrien Béraud 9565adf693 proxy server: always depend on jsoncpp 2019-12-12 14:51:59 -05:00
Adrien Béraud c10aa32596 cpp: include config.h when necessary 2019-12-12 14:51:59 -05:00
Adrien Béraud 21c294f352 docker: update asio 2019-12-12 14:51:59 -05:00
Adrien Béraud 4654f78e08 autotools: allow to build without peer discovery 2019-12-12 14:51:59 -05:00
Adrien Béraud 38644fc934 includes: don't include proxy server, pht by default 2019-12-12 14:44:53 -05:00
Adrien Béraud fa8dc4c835 callbacks: add missing header 2019-12-12 14:33:00 -05:00
Adrien Béraud 6dab10cac2 github: disable tests and examples when building asio 2019-12-12 12:24:56 -05:00
Adrien Béraud 77a1c27f2b github: build asio 2019-12-12 11:52:43 -05:00
Adrien Béraud e8577bfd05 dhtrunner: fix build without peer discovery 2019-12-12 11:42:06 -05:00
Adrien Béraud c0327a9881 dhtrunner: fix build without peer discovery 2019-12-11 11:43:20 -05:00
Adrien Béraud 2a1eacc949 tests: only link with ssl if required 2019-12-09 16:23:15 -05:00
Adrien Béraud e705bebc25 github: don't build proxy 2019-12-09 16:06:39 -05:00
Adrien Béraud a330762f40 build: always use standalone asio 2019-12-09 15:40:48 -05:00
Adrien Béraud e7972ae897 dockerfiles: update 2019-12-09 15:34:26 -05:00
Adrien Béraud 8d2d40cb7f peer discovery: simplify includes 2019-12-09 14:53:27 -05:00
Adrien Béraud aceb548c26 cmake: make peer discovery build optional 2019-12-09 14:43:04 -05:00
Adrien Béraud afce4639e1 tests/peerdiscover: add missing includes 2019-12-09 14:07:42 -05:00
Adrien Béraud e5d248bcd0 peer discovery: use asio 2019-12-09 03:28:45 -05:00
Adrien Béraud 0fbebf8e03 http: cleanup, fix handling error when no logger is set 2019-12-08 10:48:34 -05:00
Adrien Béraud 24efa37846 http: cleanup 2019-12-08 00:25:21 -05:00
Linas Vepstas c0f14ca59d Fix duplicated, non-functional log message.
Inside the if-statement, the log message will always print zero.
Confusingly, its the same message as the one in the loop above it.
Make the message distinct.
2019-12-07 22:28:35 -05:00
Adrien Béraud 05a66cc1f1 proxy client: use common jsonReader 2019-12-07 22:22:37 -05:00
Adrien Béraud ed6df8869c proxy: don't use keep-alive by default 2019-12-07 22:22:37 -05:00
Adrien Béraud b7d410e1aa tests: add http tester 2019-12-07 16:23:08 -05:00
Adrien Béraud 77a377a406 http: add OnDone callback 2019-12-07 16:23:08 -05:00
Adrien Béraud e0b6f152f1 proxy client: add LineSplitter 2019-12-07 16:23:08 -05:00
Adrien Béraud dd3c789916 proxy server: 0-initialize fields 2019-12-07 16:23:08 -05:00
Adrien Béraud 333087bcba dhtrunner: fix getNodeInfo using proxy client 2019-12-07 16:23:08 -05:00
Adrien Béraud 5b87090cab http: use http_parser parsing logic 2019-12-07 16:23:08 -05:00
Adrien Béraud fffee634f1 proxy client: avoid destroying twice 2019-12-05 18:39:39 -05:00
Adrien Béraud c4aa272dbb http/request: add constructor 2019-12-05 18:39:39 -05:00
Adrien Béraud 4ce78bdb4d c wrapper: link statically when required 2019-12-05 18:35:43 -05:00
Adrien Béraud f331f39c77 c wrapper: add dht_privatekey_export 2019-12-05 18:35:43 -05:00
Adrien Béraud 17fb92654e http: check parser before use 2019-12-03 16:45:19 -05:00
Adrien Béraud 294034f00f proxy client: don't report connectivity failure for aborted requests 2019-12-03 16:21:33 -05:00
Adrien Béraud 36857c1f3d http/request: add aborted flag and actual status code 2019-12-03 16:21:04 -05:00
Adrien Béraud 7e9f5303bd github: don't run distcheck 2019-12-02 01:30:56 -05:00
Adrien Béraud c2780b1ca9 build/autoconf: always build python Makefile 2019-12-02 01:15:38 -05:00
Adrien Béraud 16b798324d github: disable python 2019-12-02 00:53:27 -05:00
Adrien Béraud bc850bf00c build/autotools: use proper path for tools build include 2019-12-02 00:30:37 -05:00
Adrien Béraud 0d8d302128 update argon2 2019-12-02 00:11:08 -05:00
Adrien Béraud 97013badfa github: install argon2 before configure 2019-12-02 00:06:49 -05:00
Adrien Béraud 31185c24f0 build/autoconf: always build doc Makefile 2019-12-01 23:49:04 -05:00
Adrien Béraud 2f6f8e2ac1 cmake/tools: link with readline dependenciess 2019-12-01 22:46:41 -05:00
zhengfish 8f141951ce fixed a compiling error in openwrt-18.04.5
Signed-off-by: zhengfish <zhengfish@gmail.com>
2019-12-01 22:41:29 -05:00
zhengfish 43d111b7dc fixed a linking error in openwrt-18.06: undefined reference to 'tgetnum'
Signed-off-by: zhengfish <zhengfish@gmail.com>
2019-12-01 22:41:29 -05:00
Adrien Béraud 620ba2a89b proxy server: fix warning 2019-12-01 21:01:42 -05:00
Adrien Béraud d1598380db proxy server: fix build without push notifications 2019-12-01 21:00:27 -05:00
Adrien Béraud 69fe399db0 proxy server: cancelListen on destroy 2019-12-01 20:54:48 -05:00
Adrien Béraud a60dde2e13 tests: use shutdown 2019-12-01 19:41:02 -05:00
Adrien Béraud 201982b1a9 dhtrunner: don't count cancel as ops 2019-12-01 19:40:44 -05:00
Adrien Béraud 83f2b272a7 dhtrunner: add ongoing op count to node info 2019-12-01 15:07:35 -05:00
Adrien Béraud 7e47d0458a tests/proxy: cleanup 2019-12-01 14:53:50 -05:00
Adrien Béraud f6d26757fa dhtrunner: wait for current ops to complete on shutdown 2019-12-01 14:53:36 -05:00
Adrien Béraud 476d0bca4f proxy client: lock while canceling requests 2019-12-01 14:52:42 -05:00
Adrien Béraud 259986e786 network engine: don't throw in case of unknown transaction 2019-12-01 14:52:21 -05:00
Adrien Béraud 8ff0c979d4 proxy server: cleanup 2019-11-30 20:36:20 -05:00
Adrien Béraud 913cb543c8 crypto: improve exception types 2019-11-30 19:42:02 -05:00
Adrien Béraud b380c9ffba http: cleanup 2019-11-30 18:47:29 -05:00
Adrien Béraud 8c717085b4 cmake: cleanup 2019-11-30 18:11:00 -05:00
Adrien Béraud 48742a1058 tests: fix catching exception 2019-11-30 18:11:00 -05:00
Adrien Béraud fe11285a03 http: close on request end with Connection: close, cleanup 2019-11-30 18:11:00 -05:00
Adrien Béraud fb34770a54 http: reuse connection istream, cleanup 2019-11-30 17:21:52 -05:00
Adrien Béraud 4a909419e9 http: handle Request lifetime when sharing resolver/connection 2019-11-30 17:21:52 -05:00
Adrien Béraud dab7099369 proxy server: cleanup 2019-11-28 22:16:22 -05:00
Adrien Béraud 9c84e59bbf autotools: update to C++14 2019-11-27 12:12:29 -05:00
Adrien Béraud eae383b3ed autotools: remove unneeded macros 2019-11-26 12:46:26 -05:00
Adrien Béraud 28bf78408d network utils: fix some race conditions 2019-11-26 12:24:37 -05:00
Adrien Béraud 7ed6f74e6b proxy_server: add mutex to protect requests 2019-11-26 12:24:28 -05:00
Adrien Béraud cf6d9fd8c2 proxy client: add lock for requests 2019-11-25 15:43:23 -05:00
Adrien Béraud 5df34bb752 http: use atomic ids 2019-11-25 15:42:45 -05:00
Adrien Béraud bebb66490d tests: fix proxy tester 2019-11-25 13:44:55 -05:00
Adrien Béraud 5f361748eb Update ccpp.yml 2019-11-19 13:59:55 -05:00
Adrien Béraud 984745624c Update ccpp.yml 2019-11-19 13:58:46 -05:00
Adrien Béraud f9e860fdc8 docker/github: use deps base image 2019-11-19 13:52:40 -05:00
Adrien Béraud 06ea3d23e5 docker: add dockerfiles for Ubuntu 18.04 (Bionic) 2019-11-19 13:44:45 -05:00
Adrien Béraud f0857a5925 Update ccpp.yml 2019-11-19 11:05:00 -05:00
Adrien Béraud 5a993fb902 Create ccpp.yml 2019-11-19 11:02:54 -05:00
Adrien Béraud 8a18c591e9 http: initialize connection type, cleanup 2019-11-12 16:45:00 -05:00
Adrien Béraud 9daa7ec283 dhtrunner: default peer request rate to global/8 2019-11-11 12:58:11 -05:00
Adrien Béraud 01f2ad9ea4 tools: show connectivity change in log 2019-11-11 11:54:44 -05:00
Adrien Béraud 2dd4cde035 tools: factorize print_node_info 2019-11-08 16:52:27 -05:00
Adrien Béraud cb0005d0eb tools: factor configuration parsing 2019-11-08 16:12:04 -05:00
Adrien Béraud eca340b785 tools: add argument to disable rate limiting 2019-11-08 15:29:53 -05:00
Adrien Béraud cdd035b801 rate limiter: cleanup 2019-11-07 19:17:27 -05:00
Adrien Béraud cb7d7f6614 dht: allow to configure rate limiter 2019-11-07 16:43:04 -05:00
Adrien Béraud f5a6801ab9 value: cleanup 2019-11-07 11:52:27 -05:00
Adrien Béraud 0049ba92e6 thread pool: retransmit exception through future 2019-11-07 11:51:44 -05:00
Adrien Béraud 7838e7de0b docker: add python3-setuptools 2019-11-06 12:51:18 -05:00
Adrien Béraud e2d7dbc293 proxy client: declare mutex before protected objects 2019-11-05 16:39:03 -05:00
Adrien Béraud 090da49fed http/Request: cleanup 2019-11-04 15:50:55 -05:00
Adrien Béraud 22594396d2 http/Request: check conn_ on cancel 2019-11-04 15:49:05 -05:00
Adrien Béraud 0c8d0e2e0d http/Request: atomically exchange terminate 2019-11-04 15:48:39 -05:00
Adrien Béraud 18793cee3b proxy server: close listener on connection close only 2019-11-01 10:37:19 -04:00
Adrien Béraud 0bde82a218 tests/proxy: cleanup 2019-11-01 10:24:17 -04:00
Adrien Béraud bc84655f42 proxy server: update for Restinio v.0.6.0.1 2019-10-31 16:00:51 -04:00
Adrien Béraud ed642b0337 proxy: check that callback is not null 2019-10-31 14:36:34 -04:00
Adrien Béraud f710df9675 proxy: cleanup 2019-10-31 13:44:05 -04:00
Sébastien Blin 42398a541d rust: infohash support == operator and from hex 2019-10-31 10:56:52 -04:00
Sébastien Blin 429a5ad1d4 dhtrunner: fix put_encrypted API 2019-10-31 10:56:52 -04:00
Sébastien Blin 01bc43af35 rust: fix import for PrivateKey 2019-10-31 10:56:52 -04:00
Sébastien Blin 555487012b rust: remove T for no. Anyway we must at least add None 2019-10-31 10:56:52 -04:00
Sébastien Blin 697d554edb dhtrunner: change put methods 2019-10-31 10:56:52 -04:00
Sébastien Blin 8edd67834c rust: add some wrappers for value 2019-10-31 10:56:52 -04:00
Adrien Béraud 80f04430c3 proxy client: build resolver if none available 2019-10-30 14:53:07 -04:00
Adrien Béraud e4853bd29c proxy: use common Json builder 2019-10-30 14:17:42 -04:00
Adrien Béraud 6863800cfb dhtrunner: allow to cancelPut with value 2019-10-30 11:33:33 -04:00
Adrien Béraud 1f387a0e95 proxy client: resolve again on connectivity change 2019-10-30 11:33:16 -04:00
Adrien Béraud 142aee12a7 c wrapper: add support for putEncrypted 2019-10-28 17:43:00 -04:00
Adrien Béraud 95a65ce565 c wrapper: add support for putSigned 2019-10-28 17:35:41 -04:00
Adrien Béraud 144fa7ddc8 dhtrunner: allow permanent put for signed/encrypted values 2019-10-28 17:35:19 -04:00
Adrien Béraud b77fd2336f c wrapper: return null if no signer 2019-10-28 17:34:03 -04:00
Adrien Béraud c0e117871e c wrapper: allow retrieving value owner and recipient 2019-10-28 15:25:31 -04:00
Sébastien Blin 3c88eaa602 rust: add from_slice 2019-10-25 15:29:38 -04:00
Sébastien Blin 8d131449a8 rust: load identity from bytes 2019-10-25 15:29:38 -04:00
Sébastien Blin fee7e5dd30 rust: fix callback result and add DhtIdentity::new() 2019-10-25 15:29:38 -04:00
Sébastien Blin 4c2a974433 rust: link to certificate C-bindings 2019-10-25 15:29:38 -04:00
Sébastien Blin a483205976 infohash: add from_bytes 2019-10-25 15:29:38 -04:00
Adrien Béraud 96df1d4339 c wrapper: update callback return types 2019-10-25 11:05:35 -04:00
Seva 432f387423 http: ensure conn callbacks are always invoked 2019-10-24 16:03:07 -04:00
Seva 3abb9114ba http: ensure sockets exists before invocations 2019-10-24 16:03:07 -04:00
Adrien Béraud 727c5f0e8c c wrapper: add wrappers for dht::crypto::Certificate 2019-10-24 13:29:50 -04:00
Adrien Béraud f86abfaf22 crypto: add tests for corrupted data 2019-10-22 13:59:36 -04:00
Adrien Béraud f84131c820 crypto: improve authenticated encryption performance 2019-10-22 13:59:36 -04:00
Adrien Béraud 28de983166 update to version 2.0.0 2019-10-22 10:52:49 -04:00
Adrien Béraud 4b28278cb1 Update README.md 2019-10-22 10:48:50 -04:00
Sébastien Blin 653a4309bd rust: value to bytes 2019-10-22 10:47:43 -04:00
Sébastien Blin 48b763f11b rust: add from_bytes for value 2019-10-22 10:47:43 -04:00
Sébastien Blin cbfa12a921 rust: add permanent put, get_id(), get_node_id(), get_public_addresses() 2019-10-22 10:47:43 -04:00
Sébastien Blin 3e0d4cd703 rust: link DhtRunnerConfig 2019-10-22 10:47:43 -04:00
Sébastien Blin 4bff6d392a rust: clean warnings 2019-10-22 10:47:43 -04:00
Sébastien Blin 712b7218a9 rust: clean listen API 2019-10-22 10:47:43 -04:00
Sébastien Blin 5a8e252e32 rust: get2 -> get 2019-10-22 10:47:43 -04:00
Sébastien Blin b5be4549dc rust: clean dhtnode.rs 2019-10-22 10:47:43 -04:00
Sébastien Blin bf8fb6f321 rust: clean listen API 2019-10-22 10:47:43 -04:00
Sébastien Blin 08cf212c53 rust: split in files 2019-10-22 10:47:43 -04:00
Sébastien Blin fc2a597bb2 rust: update bootstrap api 2019-10-22 10:47:43 -04:00
Sébastien Blin 7212b7a28b rust: change put api 2019-10-22 10:47:43 -04:00
Sébastien Blin 5c610895fe rust: add support for all functions available in the C wrapper 2019-10-22 10:47:43 -04:00
Sébastien Blin a567ca1dc1 rust: add support for listen/cancel_listen 2019-10-22 10:47:43 -04:00
Sébastien Blin 97b20705a1 rust: add put bindings 2019-10-22 10:47:43 -04:00
Sébastien Blin 431da16ba6 dhtnode: add example with get 2019-10-22 10:47:43 -04:00
Sébastien Blin 09818d779e rust: start dhtnode example 2019-10-22 10:47:43 -04:00
Sébastien Blin 934e36ba13 rust: ffi POC 2019-10-22 10:47:43 -04:00
Adrien Béraud 2e47b9bab5 c wrapper: add dht_runner_get_public_address to dhtcnode 2019-10-21 15:56:35 -04:00
Adrien Béraud f938d486d5 c wrapper: add listen context to dhtcnode 2019-10-21 15:09:56 -04:00
Adrien Béraud 76b4da089e c wrapper: add dht_runner_get_public_address 2019-10-21 14:33:37 -04:00
Adrien Béraud 2a72277194 c wrapper: add dht_runner_get_id, get_node_id 2019-10-21 14:19:29 -04:00
Adrien Béraud e8d96d3b42 c wrapper: add support for permanent put 2019-10-21 14:04:12 -04:00
Adrien Béraud c92d236c1b c wrapper: handle null string in config 2019-10-21 12:37:36 -04:00
Adrien Béraud b680407e9a c wrapper: add callback to free listen context data 2019-10-21 11:08:42 -04:00
Seva 6caf4b0d0b http: ensure no data is lost in read_bytes 2019-10-18 15:44:26 -04:00
Seva 7f65fdc7f9 http: try to read full content-length after headers 2019-10-18 10:45:34 -04:00
Adrien Béraud b00dfdf572 c wrapper: reverse is_zero value 2019-10-17 10:29:37 -04:00
Adrien Béraud 2b1d2fc3f6 c wrapper: use shared_ptr for dht_privatekey 2019-10-16 17:23:04 -04:00
Adrien Béraud a0566cf695 dhtchat: cancel listen on channel disconnect 2019-10-16 16:18:38 -04:00
Adrien Béraud a3f2b055a1 c wrapper: don't build by default 2019-10-16 16:17:09 -04:00
Adrien Béraud 01bf8f9303 c wrapper: add dht_infohash_get 2019-10-16 15:07:31 -04:00
Adrien Béraud 22741436e3 python: add wrapper for ValueCallback 2019-10-16 15:02:58 -04:00
Adrien Béraud d958b0ea5f c wrapper: add dht_privatekey_delete, handle import failure 2019-10-16 14:40:24 -04:00
Adrien Béraud 6c96a47f13 c wrapper: update dhtcnode, add dht_op_token_delete 2019-10-16 14:27:54 -04:00
Adrien Béraud 15403c0f6e c wrapper: add dht_runner_put 2019-10-16 14:02:51 -04:00
Adrien Béraud 0eee567c4e c wrapper: add support to create, ref/unref dht_value 2019-10-16 13:57:31 -04:00
Adrien Béraud e8843076d9 c wrapper: install library 2019-10-16 13:18:39 -04:00
Adrien Béraud 3a6ce2f499 c wrapper: add initial dht_privatekey support 2019-10-16 13:09:59 -04:00
Adrien Béraud 299e632795 c wrapper: clarify memory management 2019-10-16 12:56:06 -04:00
Adrien Béraud 12aee01ffe c wrapper: add pkg-config file 2019-10-16 12:26:36 -04:00
Adrien Béraud 83c5014a36 c wrapper: add dht_runner_listen 2019-10-16 12:19:42 -04:00
Adrien Béraud e9377f2eb6 c wrapper: add Blob, PublicKey 2019-10-16 12:01:52 -04:00
Adrien Beraud 083a28f5d8 c wrapper: add wrapper foundations
Wrapper can be enabled/disabled with
-DOPENDHT_C=On/Off when configuring the cmake
project.

This commit add foundations for a C wrapper
by building an opendht-c shared library that
wraps dhtrunner (for now only creation/destruction).

It also adds a test executable, dhtcnode, using the
C wrapper library.
2019-10-16 10:57:10 -04:00
Seva ab7f36ff85 https: use identity's certificate chain 2019-10-15 14:34:50 -04:00
Seva 8856a70af5 dhtproxy/http: dont store keys in objects 2019-10-15 14:34:50 -04:00
Seva f24b6ca3e3 dhtproxy/http: dont store keys in asio::const_buffer 2019-10-15 14:34:50 -04:00
Seva ccfb76d9b4 http: add client identity & fix CA 2019-10-15 14:34:50 -04:00
Seva 104a9e3b28 http: fix target's missing query 2019-10-10 14:24:51 -04:00
Seva d77c868c55 http: close connection if server requests 2019-10-07 15:02:08 -04:00
Adrien Béraud 347f404a92 dhtchat: respect new arguments 2019-10-07 12:11:46 -04:00
Adrien Béraud ed1b0220e5 dhtnode: always load node certificate 2019-10-07 11:06:38 -04:00
seva 739f4d0c0d Merge pull request #448 from AmarOk1412/fix/resubscribe
proxy_client: reset correct opstate
2019-10-01 11:47:13 -04:00
Sébastien Blin 8ec0ab0ae4 proxy_client: reset correct opstate
opstate is captured by value in callbacks. So reset(new OpState())
will only reset the new one and previously captured will be stopped
forever.
2019-10-01 11:30:32 -04:00
Seva 55c56a5203 http: avoid creating a field in map on new key 2019-09-30 14:28:46 -04:00
Seva 7558444ae0 http: implement chunked transfer-encoding 2019-09-30 14:28:46 -04:00
Adrien Béraud 9bc2ceca68 dhtrunner: use new push_token config option 2019-09-30 10:52:50 -04:00
Seva ac10afac44 dhtproxy: test put/get mtu with 40k chars 2019-09-30 10:21:35 -04:00
Adrien Béraud 128af52ea2 dhtrunner: allow to specify push token in config 2019-09-30 10:20:09 -04:00
Adrien Béraud 8ed2bf50b3 utils: fix printing negative durations 2019-09-30 10:17:41 -04:00
Seva dcdfeb0415 http: forward declare json in api 2019-09-24 15:49:03 -04:00
Seva 833dc7f5a7 http: refactor constructors & init default headers 2019-09-24 15:49:03 -04:00
Seva d0510dcb72 http: add send json & unit test 2019-09-24 15:49:03 -04:00
MingRui Zhang 6f87e9dbc3 Merge pull request #444 from binarytrails/http_fixes
http: fix parser reset racing condition
2019-09-23 15:19:26 -04:00
Seva 223260bc7d http: remove parser reset 2019-09-23 13:24:53 -04:00
Sébastien Blin c564810b8c Merge pull request #441 from atraczyk/master
msvc: fix compilation with VS 2019 16.0
2019-09-19 14:30:59 -04:00
Sébastien Blin f9ffb8650a dht_proxy_client: listener should not be stopped here
Moreover, when it's a subscribe, because the subscribe is direct
2019-09-19 13:54:52 -04:00
Andreas Traczyk e58fc4ef31 msvc: fix compilation with VS 2019 16.0
- <stdexcept> used to be included in <vector>
2019-09-18 16:40:12 -04:00
Seva 7fde8f63a8 peerdiscovery: refactor to camelcase & fix warning 2019-09-18 16:17:39 -04:00
Seva 166b5e352c proxyserver: default push to localhost if empty host 2019-09-18 16:15:53 -04:00
Seva 77356b0539 dhtnode: restore gen identity ifndef proxy server 2019-09-18 15:02:21 -04:00
Seva c7d633e609 dhtnode: separate proxy privkey, cert & pwd arguments 2019-09-18 15:02:21 -04:00
Seva 2576d95aa0 dhtnode: start ssl node only with valid identity 2019-09-18 15:02:21 -04:00
Seva b31a29ea26 dhtproxy: run in both http & https 2019-09-18 15:02:21 -04:00
Sébastien Blin 833bd069f4 Merge pull request #439 from binarytrails/request_fixes
http: end request on 0 body bytes
2019-09-18 12:51:54 -04:00
Seva 39a186c47d http: end request on 0 body bytes
the latter ensures that the request will be terminate even if the
http_parser on_message_complete callback is not called with an old
version of dhtproxy using restbed
2019-09-18 12:16:10 -04:00
Sébastien Blin c03af5f5a8 dhtrunner: fix context.logger handling 2019-09-18 12:01:24 -04:00
Sébastien Blin b03a7732e3 Merge pull request #436 from binarytrails/http_expect_100-continue
http: handle expect 100-continue on post
2019-09-16 11:32:43 -04:00
Seva 87f6f3df8b http: fix & test url with https but empty service 2019-09-13 13:50:45 -04:00
Seva 7270c353df http: handle expect 100-continue
expose raw request & ignore more self-signed
2019-09-12 11:32:54 -04:00
Seva 63afc8c29a http: fix resolver destruction race condition 2019-09-09 16:28:26 -04:00
Andreas Traczyk 6a760a629c msvc: update native windows build to use restinio 2019-09-09 15:24:23 -04:00
Seva 5068de7bc0 http: remove x509 subject name logging in verify cb 2019-09-05 15:24:50 -04:00
Seva 2a5f786f8b http: handle request error codes through terminate 2019-09-05 15:24:50 -04:00
Seva c690d060f9 http: fix req cancel racing condition 2019-09-05 15:24:50 -04:00
Adrien Béraud bcf8ab5404 http: check for null callbacks 2019-09-05 11:23:23 -04:00
Adrien Béraud f7c8168f99 http: cleanup, remove default port
Prevents ambiguous function call when just providing a URL.
2019-08-30 17:34:31 -04:00
Adrien Béraud c37f0083d3 crypto: add CertificateRequest::toString 2019-08-30 11:26:29 -04:00
Adrien Béraud 29e7768c9d proxy client: cleanup 2019-08-30 11:26:00 -04:00
Adrien Béraud 72a06b1425 http: add Request::set_auth 2019-08-30 11:24:51 -04:00
Adrien Béraud e4dacc64b5 cmake: find library in argon2_LIBRARY_DIRS 2019-08-30 01:34:09 -04:00
Adrien Béraud 20df5fe845 http: cleanup 2019-08-30 01:28:12 -04:00
Adrien Béraud 5b4f40229d proxy client: cleanup 2019-08-30 01:08:12 -04:00
Adrien Béraud 6c4af9bfea proxy server: fix warnings 2019-08-30 01:06:50 -04:00
Adrien Béraud ef26155b19 proxy client: add missing override 2019-08-30 00:35:51 -04:00
Seva eb2269625f http: optimize get_url funcs 2019-08-30 00:13:15 -04:00
Seva 70c92d6cea http: replace service by url 2019-08-30 00:13:15 -04:00
Seva fd7f644531 http: init request target with url one 2019-08-30 00:13:15 -04:00
Seva 562bf7124c http: handle url fragment 2019-08-30 00:13:15 -04:00
Seva 5b344cada7 http: propagate the use of url 2019-08-30 00:13:15 -04:00
Seva 7c4450fdb1 http: add url with tests, handle prefix 2019-08-30 00:13:15 -04:00
Seva 9b8358cdf1 configure: set openssl & fmt flags with pkg_check_modules 2019-08-28 11:03:15 -04:00
Seva 7ae3b3af5b configure: use cflags,libs,ldflags of openssl 2019-08-28 11:03:15 -04:00
Seva 06d1865446 configure: build with ssl, rm not used cppflag 2019-08-28 11:03:15 -04:00
Seva 83495a94db dhtproxy: fix client class member redeclaration 2019-08-28 11:03:15 -04:00
Seva 8ee5485767 autotools: fix dhtproxy build 2019-08-28 11:03:15 -04:00
Seva e7742489ca http: ignore rw ops on closed connection 2019-08-27 10:11:04 -04:00
Seva 99fc97f3cf http: return from async_handshake on op abort 2019-08-27 10:11:04 -04:00
Seva 82d5db81e0 http: let the connection terminate 2019-08-27 10:11:04 -04:00
Seva fbb90a71b7 cmake: add asio standalone flag to avoid boost 2019-08-27 10:11:04 -04:00
Seva 316f3ccfa0 docker: fix ubuntu xenial asio dep comment typo 2019-08-26 12:06:07 -04:00
Seva 185158f460 docker: build shared for libfmt 2019-08-26 12:06:07 -04:00
Seva baa9fcf820 dhtproxy: disable renegotiation only if supported 2019-08-26 12:06:07 -04:00
Seva 04a383c4fb docker: fix deps & depsllvm 2019-08-26 12:06:07 -04:00
Adrien Béraud b7b6fb802d http: header cleanup 2019-08-22 16:51:05 -04:00
Adrien Béraud 9575f84081 header cleanup 2019-08-22 15:39:15 -04:00
Adrien Béraud 0b0442bd02 proxy server: remove unneeded move 2019-08-21 13:22:36 -04:00
Adrien Béraud 251fe8bf2f dockerfiles: add restbed 2019-08-21 13:22:20 -04:00
Seva c211055bf9 tester: add https support to proxy_node 2019-08-20 15:17:10 -04:00
Seva fafe97194a dhtproxy: reduce & uniformize logs 2019-08-20 10:46:20 -04:00
Seva d214bfebf5 dhtproxy: patch client renegotiation 2019-08-20 10:45:05 -04:00
Adrien Béraud d551b8a54c Merge pull request #417 from binarytrails/proxy_docker
docker: switch dhtproxy build to cmake & remove conan
2019-08-16 10:20:07 -04:00
Seva 4a8397d71b dhtproxy: fix indirect memleaks from rest router traits 2019-08-16 10:18:36 -04:00
Seva 366f76986f docker: bump restinio & replace sed fix by new var 2019-08-15 16:38:53 -04:00
Seva 8072092b67 docker: switch to cmake build & remove conan 2019-08-15 16:20:22 -04:00
Adrien Béraud 624f36467e proxy: don't use shared_ptr for Identity 2019-08-14 17:30:29 -04:00
Adrien Béraud 561a660693 proxy: header cleanup 2019-08-14 17:19:33 -04:00
Adrien Béraud 414e0a2e60 proxy server: move type traits definition to cpp 2019-08-14 15:51:12 -04:00
Adrien Béraud e0393ff8ad Merge pull request #403 from binarytrails/proxy_restinio
dhtproxy: replace restbed by restinio & asio
2019-08-14 15:50:14 -04:00
Seva d26bfc58d8 http: align logs 2019-08-14 14:02:43 -04:00
Seva d50aae0751 dhtproxy: cleanup 2019-08-14 03:58:15 -04:00
Seva 1a79ae45e4 dhtproxy: fix server termination & use https tests 2019-08-14 03:41:32 -04:00
Seva c6f830f54d http: fix refactoring memory issues 2019-08-14 02:30:19 -04:00
Seva f018610ec9 http: fix ssl rfc2818 verif. due to self-signed cert. 2019-08-13 23:16:44 -04:00
Seva 119c162f49 dhtproxy: make optional the http_parser fork in client 2019-08-13 20:30:14 -04:00
Seva 144e254c40 build: add flag for http_parser fork 2019-08-13 17:17:32 -04:00
Seva 6cc84312aa dhtproxy: run tests in http 2019-08-13 16:55:42 -04:00
Seva b3a7bdd880 cppflags: rm OPENDHT_PROXY_OPENSSL last occurences 2019-08-13 16:25:33 -04:00
Seva a797ea9171 dhtproxy: create http & https server instances 2019-08-13 16:21:19 -04:00
Seva 023b4aff61 dhtnode: use generated identity only if specified 2019-08-13 14:53:45 -04:00
Seva 86429aa360 http: support all connections contd. 2019-08-13 13:45:10 -04:00
Seva fbea6afe5d http: support all connections idependent of build system 2019-08-13 10:23:15 -04:00
Seva 18bcad33bd autotools: add openssl support to configure 2019-08-12 15:24:13 -04:00
Seva 8bc43b4e47 dhtproxy: propagate server identity certicate to client 2019-08-12 15:11:37 -04:00
Seva 25f3000a78 http: verify peer only if certificate provided 2019-08-12 14:27:59 -04:00
Seva 96992b803c dhtproxy: implement https in server 2019-08-10 15:34:36 -04:00
Seva 500ae6ef54 http: handle asio cancel delays 2019-08-10 15:34:02 -04:00
Seva b01d3cfca5 dhtproxy: add identity to constructor if openssl 2019-08-07 11:57:18 -04:00
Seva 49f6dd3c9c http: implement secure connection
cmake: use provided findopenssl module
2019-08-07 10:35:47 -04:00
Seva 4054ec6af0 opendht: add ssl to build system
http: enforce ssl everywhere
2019-08-05 11:09:18 -04:00
Adrien Béraud 3345c1b048 update to version 1.10.1 2019-08-02 21:06:26 -04:00
Adrien Béraud 4b061d0886 dht: cleanup 2019-08-02 19:58:43 -04:00
Adrien Béraud c1f805e6e2 tools: use default port from network utils 2019-08-02 19:53:39 -04:00
Adrien Béraud 25c9375d95 dhtrunner: add bootstrap method with single arg. host:service 2019-08-02 19:41:42 -04:00
Adrien Béraud 84a9d899d5 dhtrunner: migrate to SockAddr, use default port if not set 2019-08-02 14:42:26 -04:00
Seva 7ea40c292b dhtproxy: fix indirect mem leak caused by 208758e 2019-08-02 10:19:06 -04:00
Seva 2954158bba http: handle all content-length cases 2019-08-01 13:44:14 -04:00
Seva 3382195760 http: refactor response funcs to handle mtu 2019-08-01 00:43:37 -04:00
Seva b67149c98c http: implement final api changes 2019-07-30 11:44:14 -04:00
Seva f34cb6440f http: add comments & log errors on end 2019-07-30 10:14:53 -04:00
Seva 9cf37eb865 dhtproxy: always log client in tests 2019-07-30 09:26:38 -04:00
Seva c8bed06641 http: rm default conn header & end properly 2019-07-30 09:22:03 -04:00
Seva 51aef18885 dhtproxy: fix operation stop in cancelAllListeners 2019-07-29 13:02:25 -04:00
Seva 49a132a54b http: fix request termination 2019-07-29 12:51:23 -04:00
Seva 235c48c400 dhtproxy: fail client ipv4/6 query on operation cancel 2019-07-29 09:40:41 -04:00
Seva 5465b08d76 dhtproxy: attempt to connect to an ipv4/ipv6 pair 2019-07-27 00:20:08 -04:00
Seva a8e24e505d dhtproxy: design clean persistent destruction
http: terminate with eof on_message_complete parser cb
2019-07-26 11:56:36 -04:00
Seva 5c0a8986a7 dhtproxy: fix listener destruction thus, restart 2019-07-26 09:57:00 -04:00
Seva 460205eb78 http: terminate connection with eof 2019-07-25 21:56:26 -04:00
Seva 208758ede3 dhtproxy: remove implicit std::move on a router return 2019-07-25 21:17:41 -04:00
Seva de9e0906de http: merge on_message_complete into on_state_change callback 2019-07-25 20:09:59 -04:00
Seva 692304c2e3 tests: log dhtproxy client 2019-07-25 19:25:57 -04:00
Seva f837c13e31 http: fragment request header & body read/parse 2019-07-24 23:56:32 -04:00
Seva 5812b24d56 http: transform client into request 2019-07-24 15:59:22 -04:00
Seva a72ddfdb03 dhtnode: fix shutdown deadlock 2019-07-16 15:57:19 -04:00
Seva e7b03e4d53 dhtproxy: unify client destruction & shutdown with stop() 2019-07-16 15:46:13 -04:00
Seva baf43d96ff dhtproxy: encapsulate server expire handlers 2019-07-16 15:12:38 -04:00
Seva 0f9df9a62b dhtproxy: fix server send push notif underflow 2019-07-16 13:04:37 -04:00
Seva 630112601c dhtproxy: fix client connectivity change
add handle resubscribe
          ignore operation aborted signals
2019-07-16 12:48:29 -04:00
Seva b0500af062 dhtproxy: fix client proxy confirmation 2019-07-15 13:47:31 -04:00
Seva 6c985e8fda dhtproxy: fix restart client listeners 2019-07-15 13:42:10 -04:00
Seva 9c1e55279c dhtproxy: fix refresh permanent put timer 2019-07-15 13:29:21 -04:00
Adrien Béraud 593d024f51 proxy client: fix cancelListen, add locks 2019-07-15 11:35:01 -04:00
Seva a6e57d95d6 dhtproxy: fix cancelListen & rm duplicated logging 2019-07-12 15:59:51 -04:00
Seva 846f495202 dhtproxy: fix indirect mem leak in create router 2019-07-11 11:06:36 -04:00
Seva 6f603bfc0a dhtproxy: fix options route 2019-07-11 10:46:33 -04:00
Seva 9c106f9efe http: make connection data unique & fix init warn 2019-07-11 10:26:51 -04:00
Seva ff288fb4a3 autotools: add dhtproxy dependencies checks 2019-07-09 15:28:57 -04:00
Seva 17ff4c0224 http: one line init of conn context 2019-07-09 14:17:17 -04:00
Seva 45a2c6dadb dhtproxy: sanitized by fixing client memory leaks 2019-07-09 12:21:56 -04:00
Seva 477ff59e91 dhtproxy: enhance error handling & msg for push 2019-07-09 10:20:39 -04:00
Seva a001e0cafd dhtproxy: fix client multi-line data in get/listen 2019-07-08 16:47:52 -04:00
Seva ac63527e0b http: split header & body processing
this allow to handle a case when an incomplete body is attached to a
header to forward it to the body processing for full recovery.
2019-07-08 16:46:49 -04:00
Seva 4b3d8d1231 dhtproxy: move operations into async_connect handler 2019-07-06 12:25:14 -04:00
Seva d04a741d5e http: better error handling
use async::connect instead of manually
2019-07-05 18:44:10 -04:00
Seva ac2b7deda8 http: add set_connection_timeout 2019-07-03 17:03:53 -04:00
Seva c8b08b5ed1 dhtproxy: fix client stop by cancelling io_context 2019-07-03 14:30:10 -04:00
Seva f556987e47 http: handle unavailable server 2019-07-03 14:23:49 -04:00
Seva 2daf36c97e Merge branch 'master' into proxy_restinio 2019-07-03 14:07:35 -04:00
Seva 2a2555f0c2 dhtproxy: fix type nomenclature & compile warnings 2019-07-03 12:10:49 -04:00
Seva bdfb0148e4 dhtproxy: use legacy listen route in client 2019-07-03 11:27:51 -04:00
Seva 01be4d2eb8 dhtproxy: enhance new api routes 2019-07-03 11:01:32 -04:00
Seva 93f7251805 http: segment resolving & connection from request
set connection id to unsigned int
      use service string instead of int port
      segment connection from request
      save endpoint associated with a conn
      add Connection is_v6 ip method
      propagate resolve errors
2019-07-03 10:30:33 -04:00
Adrien Béraud a8718242cd net: fix build on MSVC2017 2019-07-02 14:51:28 -04:00
Adrien Béraud 297a23fb1f dhtrunner: run shutdown on op queue 2019-07-02 12:09:31 -04:00
Adrien Béraud 0d641161e8 dhtrunner: fix minor warning 2019-07-01 23:22:00 -04:00
Adrien Béraud 27b3c0d47e dhtrunner: add appropriate lock to setProxyServer 2019-07-01 23:20:03 -04:00
Adrien Béraud 149b33ef57 dht: simplify error message to avoid use-after-move 2019-07-01 15:07:10 -04:00
Adrien Béraud 150e62de0b sockaddr: fix npe if address is not set 2019-07-01 14:08:41 -04:00
Adrien Béraud 89bdfce840 dhtrunner: add proper locks for push notification 2019-07-01 12:10:51 -04:00
Adrien Béraud bce41ecd69 proxy client: fix build with push notifications 2019-07-01 01:12:21 -04:00
Adrien Béraud 4374d206ab op_cache: simplify addListener 2019-07-01 00:34:05 -04:00
Adrien Béraud b64820af59 proxy client: remove unneeded filter
Filters are applied at the SearchCache level
2019-07-01 00:34:05 -04:00
Adrien Béraud 0e509318bb build: only build http with proxy 2019-06-28 20:56:22 -04:00
Seva bcc2baa94a http: ensure http_parser on_message_complete cb is always called 2019-06-28 15:28:12 -04:00
Seva bbed9d530d http: remove unnecessary resolve iteration log 2019-06-28 14:49:37 -04:00
Seva 5a3612be98 dhtproxy: default client port to 80 2019-06-28 14:32:24 -04:00
Seva 8202c1f7d7 http: add default port to 80 2019-06-28 13:55:36 -04:00
Seva a200b0e14c http: open client to public api 2019-06-27 09:48:33 -04:00
Seva bd32edc6c5 dhtproxy: uniform client logging 2019-06-25 17:04:38 -04:00
Seva d0d3ef7394 http: don't process resps & reqs on closed conn 2019-06-25 16:49:48 -04:00
Seva 712da15ae2 readme: change optional restbed mention to restinio 2019-06-25 16:08:19 -04:00
Seva fcdc997d29 cmake: fix undefined ref to pthreads for dhtnode 2019-06-25 15:45:12 -04:00
Seva cf18effebb dhtnode: fix logging 2019-06-25 15:21:49 -04:00
Seva b8c2ff8a11 dhtproxy: cleanup client handle proxy status 2019-06-25 14:35:04 -04:00
Seva 1fad1b9ce3 dhtrunner: use user logger with proxy client 2019-06-25 13:37:45 -04:00
Seva 117fedb641 dhtproxy: test with http client lib everything 2019-06-25 13:36:14 -04:00
Seva 422f5a6c45 dhtproxy: use one io_context, rm scheduler, fix get,proxyInfo 2019-06-25 13:35:26 -04:00
Seva 51a42aa2c8 dhtproxy: fix inconsistencies & add comments 2019-06-25 10:16:40 -04:00
Adrien Béraud be0baefee8 net: recompute selectFd in case of rebind 2019-06-22 22:51:56 -04:00
Adrien Béraud 2ac5157ab8 net: attempt to use the same port for IPv4 and IPv6 if 0 2019-06-22 21:30:49 -04:00
Adrien Béraud fbe8834e04 net: compute selectFd once 2019-06-22 18:49:50 -04:00
Adrien Béraud 89ff131750 tools: close stdin on sigint 2019-06-22 18:37:58 -04:00
Adrien Béraud feb498305f network engine: convert mapped IPv4 2019-06-22 18:37:58 -04:00
Seva b00f56c94a dhtproxy: fix server logging of non c str 2019-06-21 14:41:10 -04:00
Seva 2067cb052f dhtproxy: default to curly brakets instead of nullptr 2019-06-21 13:10:33 -04:00
Seva 51aeaeaeab dhtproxy: use logger everywhere & use same format 2019-06-21 12:49:47 -04:00
Seva c0bb8f065c dhtproxy: ensure client asio timers are initialized 2019-06-21 11:33:51 -04:00
Seva 126318956a dhtproxy: fix unintialized refresh timer in listen 2019-06-21 11:13:54 -04:00
Seva 9014c0a7bb dhtproxy: log subscribe to debug instead of warning 2019-06-21 11:12:49 -04:00
Seva 728782921c dhtproxy: test resubscribe with random port 2019-06-21 11:07:20 -04:00
Adrien Béraud d438d4ef1b sockaddr: add getMappedIPv6 2019-06-21 11:00:48 -04:00
Seva 2959709462 dhtproxy: log in client only if logger is defined 2019-06-20 16:44:13 -04:00
Seva 4a26168248 dhtproxy: ensure client http processing keeps running 2019-06-20 16:13:01 -04:00
Seva 9c348b1df4 dhtproxy: use same client logger 2019-06-20 15:31:43 -04:00
Seva 7e7654d1ae dhtproxy: use two io_contexts periodic & http 2019-06-20 14:43:16 -04:00
Seva 69ee1d212a http: replace tabs by 4 spaces 2019-06-20 12:30:42 -04:00
Seva 21ec9129c3 tools: rename proxy benchmark to loadtester 2019-06-20 12:24:44 -04:00
Seva b7185fa87c dhtproxy: rewrite client restartListeners & save listener connId 2019-06-20 12:14:27 -04:00
Seva 54acd67a1f dhtproxy: rewrite client cancelAllListeners with RESTinio 2019-06-20 11:56:16 -04:00
Seva 045de8602c dhtproxy: rewrite client doCancelListen with RESTinio 2019-06-20 11:52:15 -04:00
Seva 390fa48700 dhtproxy: replace status thread by asio timer 2019-06-20 11:24:56 -04:00
Seva 0d08f0d356 dhtproxy: replace client threads by asio timers 2019-06-20 11:23:38 -04:00
Adrien Béraud 738424b1ae dhtrunner: use default values for config 2019-06-19 19:27:54 -04:00
Seva d123d8f768 http: remove typo 2019-06-19 12:23:00 -04:00
Seva a20a48506d http: fix resolve & externalize conn close 2019-06-19 12:07:46 -04:00
Seva 063a2b4860 http: make conn async & resolve hostnames 2019-06-19 11:34:50 -04:00
Seva 829d365475 http: detect & handle close connection 2019-06-19 10:24:51 -04:00
Seva 11e6671e60 Merge branch 'proxy_asio_client' into proxy_restinio 2019-06-18 23:27:51 -04:00
Seva 6fe473d3cc http: fragment client into async operations 2019-06-18 23:17:49 -04:00
Seva 9f493b9572 http: make continious reads non blocking 2019-06-18 16:55:52 -04:00
Seva 2164c5ddc7 dhtproxy: add control for max_pipelined_requests 2019-06-18 14:57:17 -04:00
Seva a57a4d55e8 dhtproxy: optimize for concurency 2019-06-18 14:13:42 -04:00
Seva b98cc78b42 dhtproxy: add if logger before using it 2019-06-18 10:17:21 -04:00
Seva 789d41ff07 dhtproxy: fix join on terminated thread 2019-06-17 16:42:12 -04:00
Seva 632403875c dhtproxy: switch entirely to one thread 2019-06-17 16:27:39 -04:00
Seva bc2737cdc9 dhtproxy: move resp msgs to cpp file as constexpr 2019-06-17 15:29:25 -04:00
Seva 0c6bfde1c5 docker: cp restinio deps build files to system path 2019-06-17 15:13:32 -04:00
Seva cfeeaf7950 tools: add listen & subscribe to proxy_benchmark 2019-06-17 13:57:46 -04:00
Seva e31ebfea32 docker: finalize restinio conan setup 2019-06-17 13:06:04 -04:00
Seva 07efe8c76e tools: add locust proxy_benchmark.py 2019-06-17 11:46:29 -04:00
Seva 5c78bf386d docker: update restinio run commands 2019-06-16 22:04:05 -04:00
Adrien Béraud 86088b043b thread pool: getShared returns shared_future instead of shared_ptr<future> 2019-06-14 13:06:06 -04:00
Seva fad8bb1631 dhtrunner: change context logger from unique to shared ptr 2019-06-14 11:46:13 -04:00
Seva 9a56c099a1 docker: rename pip unknown cmd to pip3 & remove comments 2019-06-14 10:23:59 -04:00
Seva 8298c0c868 docker: add restinio & conan depsllvm 2019-06-13 18:44:23 -04:00
Seva 971f590941 Merge branch 'master' github.com:savoirfairelinux/opendht into proxy_restinio 2019-06-13 17:19:49 -04:00
Seva 1813d83273 docker: add restinio & conan dependency 2019-06-13 16:04:14 -04:00
Seva e87d164f0b dhtproxy: refactor client to use external io_context 2019-06-13 13:24:44 -04:00
Seva b9604807ea dhtproxy: replace threads by io_context
replace scheduler and its jobs by asio timers
2019-06-13 11:13:48 -04:00
Seva 9f12b44179 dhtproxy: move custom methods to http & default thread pool to 1 2019-06-11 16:30:42 -04:00
Seva 0772d5435c dhtproxy: replace listener thread with a conn state observer 2019-06-11 15:37:47 -04:00
Seva 368ee9e22e dhtproxy: ensure io_context thread pool & isolate settings 2019-06-11 11:31:43 -04:00
Seva dd56bdd8e2 dhtproxy: add conn listener & make http services singletons 2019-06-10 17:08:37 -04:00
Seva 71b36e0643 dhtproxy: set logger in sendPushNotification 2019-06-10 14:16:18 -04:00
Seva 61b43759df dhtproxy: set required timeout times 2019-06-10 10:12:08 -04:00
Adrien Béraud 96e12e88c3 dhtproxytester: add more checks, cleanup 2019-06-09 23:34:38 -04:00
Adrien Béraud 8da933c01a dhtrunner: use threaded mode by default 2019-06-09 23:31:40 -04:00
Adrien Béraud 20c0069867 dhtrunner/peerdiscovery: only advertise bound address families 2019-06-09 23:15:31 -04:00
Adrien Béraud 8942e0d00e dht: init parent class with logger 2019-06-09 19:07:04 -04:00
Adrien Béraud bc760f9348 Update README.md 2019-06-09 19:06:44 -04:00
Adrien Béraud 59702190a7 update to version 1.10.0 2019-06-09 09:06:36 -04:00
Adrien Béraud cb3e94d0be dhtnode: improve manpage 2019-06-08 13:28:52 -04:00
Adrien Béraud ab7b8f6027 dhtnode: improve manpage 2019-06-08 12:59:57 -04:00
Adrien Béraud 6e5231047b dhtrunnner: properly lock mutex in run & join 2019-06-08 10:20:25 -04:00
Adrien Béraud 777505434c tools: always handle signals, don't block in signal handling 2019-06-08 09:23:34 -04:00
Adrien Béraud 18c3161261 tools: allow to use existing certificate/private key 2019-06-08 01:43:07 -04:00
Seva 1060038bdf dhtproxy: write into dht logger 2019-06-07 16:46:28 -04:00
Seva 9d427a6a80 http: add optional client conn controls 2019-06-07 15:46:21 -04:00
Seva f1dbac2aff dhtproxy: fix client context lost in the abyss 2019-06-07 14:57:16 -04:00
Adrien Béraud a63c5d172b build: install network utils 2019-06-07 14:41:10 -04:00
Adrien Béraud 9c6de8cc16 net: add logger support for UdpSocket 2019-06-07 14:14:15 -04:00
Adrien Béraud fe9de44867 dhtrunner: stop socket after dht 2019-06-07 14:14:15 -04:00
Adrien Béraud 4bfd6bb545 dhtrunner: add pluggable transport 2019-06-07 14:14:15 -04:00
Adrien Béraud 120c017399 net: add DatagramSocket, UdpSocket transport 2019-06-07 14:14:15 -04:00
Seva 7fc7597564 dhtproxy: fix indent 2019-06-06 14:51:01 -04:00
Seva f8d62dc6a7 dhtproxy: add support for legacy http methods
Legacy non-standard http methods: LISTEN, STATS, SIGN, ECNRYPT

NOTE: Supported with RESTinio > 0.5.0 and custom http_parser
- https://github.com/Stiffstream/restinio/issues/26
- https://github.com/binarytrails/http-parser
2019-06-06 13:30:37 -04:00
Seva fc3686d817 dhtproxy: comment/remove restbed leftovers to build w/o 2019-06-06 11:08:39 -04:00
Seva a692f7fbe2 dhtproxy: add logger to tester & disable client proxy 2019-06-05 16:50:50 -04:00
Seva cb349d9cf6 dhtproxy: stop server eventloop on cmd 2019-06-05 16:39:18 -04:00
Seva 6266f88cd5 dhtproxy: port doPut,sendListen logic new http client 2019-06-04 17:21:44 -04:00
Seva 0a3320e2c8 dhtproxy: enhance http async api & finish client get 2019-06-04 16:14:37 -04:00
Mingrui Zhang d6ad67d8e2 peerdiscovery: change comment 2019-06-04 15:30:45 -04:00
Mingrui Zhang 19d0aa55f7 Test: change ip multicast address to organization local 2019-06-04 15:30:45 -04:00
Adrien Béraud 941e53425f update to version 1.9.5 2019-06-04 09:54:02 -04:00
Seva 10971f700f dhtproxy: add http classes with fully async client
use server's pushNotifications of this client
2019-06-03 17:10:19 -04:00
Seva 2e7767d192 dhtproxy: fix restinio start w/o dhtlogger 2019-06-03 13:52:35 -04:00
Adrien Béraud baf811bfe9 dhtrunner: don't override statusCallback if not provided 2019-05-31 19:29:59 -04:00
Adrien Béraud 76f0672e63 context: add statusCallback, certificateStore 2019-05-31 10:12:42 -04:00
Seva 330ad8ed12 dhtproxy: pipe restinio logs to opendht logger 2019-05-29 16:02:25 -04:00
Seva 3252e6daa3 dhtproxy: rewrite sendListen with restinio 2019-05-29 11:59:09 -04:00
Seva 07599239a6 dhtproxy: port restbed client listen to server 2019-05-28 11:39:04 -04:00
Seva eac61678f4 dhtproxy: add client request conn_cb for listeners 2019-05-28 10:26:47 -04:00
Seva 078c1198b0 Merge branch savoirfairelinux 'master' changes 2019-05-27 15:23:26 -04:00
Seva 3d525030b9 dhtproxy: add async put & swap threading for io_context 2019-05-27 15:06:11 -04:00
Seva 3733fc2890 dhtproxy: switch threading to io_context 2019-05-27 15:06:11 -04:00
Seva c40f35fa06 dhtproxy: fix context type casting in client get 2019-05-27 14:59:19 -04:00
Seva 13661929d1 dhtproxy: switch server to ipv6 (implicit ipv4 support) 2019-05-27 14:59:19 -04:00
Seva 4e934f8902 dhtproxy: add ipv6 to restinio client & get method 2019-05-27 14:59:19 -04:00
Seva 125a05a5fc dhtproxy: fix sendPushNotification 2019-05-27 14:59:19 -04:00
Seva 868c114bcb dhtproxy: fix restinio client rx by parts 2019-05-27 14:59:19 -04:00
Seva f0acc3e735 dhtproxy: add sendPushNotification to server 2019-05-27 14:59:19 -04:00
Seva 171e2b130b dhtproxy: implement restinio client 2019-05-27 14:59:19 -04:00
Seva cb5a261b82 dhtproxy: cleanup server 2019-05-27 14:59:19 -04:00
Seva feb8bd0d4f dhtproxy: rewrite listen with restinio 2019-05-27 14:59:19 -04:00
Seva 3955368c01 dhtproxy: rewrite putEncrypted with restinio 2019-05-27 14:59:19 -04:00
Seva b841ff1b83 dhtproxy: rewrite putSigned with restinio 2019-05-27 14:59:19 -04:00
Seva 7a04c0eb66 dhtproxy: rewrite getFiltered with restinio 2019-05-27 14:59:19 -04:00
Seva fe1659bd2f dhtproxy: rewrite un/subscribe with restinio 2019-05-27 14:59:19 -04:00
Seva b90e14edd6 dhtproxy: rewrite stats with restinio 2019-05-27 14:59:19 -04:00
Seva 9e3e9e65e6 dhtproxy: switch server to restinio
rewrite options, getNodeInfo, get & put
opendht: bump to c++14
2019-05-27 14:59:19 -04:00
Seva 1c3132e0ef dhtproxy: add async put & swap threading for io_context 2019-05-27 14:57:05 -04:00
Seva f3e304e661 dhtproxy: switch threading to io_context 2019-05-27 11:17:51 -04:00
Seva 2545282624 dhtproxy: fix context type casting in client get 2019-05-26 09:50:44 -04:00
Seva 52c413f056 dhtproxy: switch server to ipv6 (implicit ipv4 support) 2019-05-24 13:18:06 -04:00
Seva ab082543ea dhtproxy: add ipv6 to restinio client & get method 2019-05-24 11:01:35 -04:00
Adrien Béraud ff6be81929 peer discovery: add default port 2019-05-23 10:39:43 -04:00
Seva bd994384f0 dhtproxy: fix sendPushNotification 2019-05-22 17:23:36 -04:00
Seva 598e38dbf4 dhtproxy: fix restinio client rx by parts 2019-05-22 16:21:07 -04:00
Seva b1a35b82a2 dhtproxy: add sendPushNotification to server 2019-05-22 11:55:37 -04:00
Adrien Béraud e4516772ee dht: log cleanup 2019-05-22 11:20:27 -04:00
Seva c7844fc320 dhtproxy: implement restinio client 2019-05-22 10:29:27 -04:00
Adrien Béraud c7e2483160 dht: add logger to constructor 2019-05-22 00:47:25 -04:00
Adrien Béraud 37b12c114d dht: cleanup 2019-05-22 00:17:18 -04:00
MingruiZhangW 77bd34ad9c Merge pull request #405 from savoirfairelinux/context
dhtrunner: add context
2019-05-21 16:21:45 -04:00
Adrien Béraud 44490bd9ca dhtrunner: add context 2019-05-21 13:43:55 -04:00
Adrien Béraud ca01568824 dhtrunner: add API to access PeerDiscovery instance 2019-05-20 10:21:35 -04:00
Adrien Béraud 2b259639d2 peer discovery: fix occasional use-after-free in unit test 2019-05-20 10:21:26 -04:00
Adrien Béraud 84d322e428 peer discovery: check running before select 2019-05-20 10:21:26 -04:00
Seva 6d5e3d8cd2 dhtproxy: cleanup server 2019-05-17 14:27:18 -04:00
Seva b56518f258 dhtproxy: rewrite listen with restinio 2019-05-17 14:03:07 -04:00
Sébastien Blin d807af3951 Merge pull request #402 from MingruiZhangW/peerdiscovery_fix_bind
peerdiscovery: bind socket problem fix
2019-05-16 17:19:02 -04:00
Seva 5f393490a5 dhtproxy: rewrite putEncrypted with restinio 2019-05-16 17:15:31 -04:00
Seva efe869fe42 dhtproxy: rewrite putSigned with restinio 2019-05-16 16:06:47 -04:00
Seva a31cecdeac dhtproxy: rewrite getFiltered with restinio 2019-05-16 15:19:26 -04:00
Seva 4a4becdbec dhtproxy: rewrite un/subscribe with restinio 2019-05-16 14:09:13 -04:00
Seva eef2838a12 dhtproxy: rewrite stats with restinio 2019-05-16 12:31:58 -04:00
Seva a520657fac dhtproxy: switch server to restinio
rewrite options, getNodeInfo, get & put
opendht: bump to c++14
2019-05-16 11:30:41 -04:00
Mingrui Zhang 29003700db peerdiscovery: fix the issue where bind() can be interrupted after calling publish() first 2019-05-15 15:42:32 -04:00
Sébastien Blin b143bc459d default_types: add metadatas map into ImMessage
Give the ability to store more datas into an ImMessage

Issue: #345
2019-05-03 14:54:43 -04:00
Adrien Béraud 4d6e5ab877 peer discovery: fix warning 2019-05-03 10:13:05 -04:00
Adrien Béraud 248d2e3f73 update to version 1.9.4 2019-05-02 12:44:27 -04:00
Adrien Béraud 0692bd9bc9 proxy server: fix warning when building without push notifications 2019-04-30 17:47:40 -04:00
Adrien Béraud 7f48c4808b network engine: minor cleanup 2019-04-30 17:47:40 -04:00
Adrien Béraud 32a443a1d8 thread pool: add unit test 2019-04-30 17:47:40 -04:00
Adrien Béraud 6d0fcba3b5 thread pool: add Executor 2019-04-30 17:47:40 -04:00
Adrien Béraud 76e2efb19b peerdiscovery: undef write macro after use 2019-04-26 11:50:25 -04:00
Adrien Béraud bbe1b9233f dhtrunner: use recv instead of recvfrom for stoppipe 2019-04-26 02:29:49 -04:00
Adrien Béraud 7558ca0dca peerdiscovery: unit test cleanup 2019-04-26 02:29:49 -04:00
Adrien Béraud 38141322f1 peerdiscovery: stop threads when stopping services 2019-04-26 02:29:49 -04:00
Adrien Béraud 6c5ea125ca peerdiscovery: add automatic template serialization 2019-04-26 02:29:49 -04:00
Adrien Béraud d0362e58e0 dhtnode: update dht instance name
Avoid confusion with the namespace
2019-04-25 23:33:22 -04:00
Adrien Béraud 1b3a40f345 dhtrunner: clear stop file descriptor if still running 2019-04-25 22:12:28 -04:00
Adrien Béraud 38d854e6f4 dhtrunner: read correct size from buffer 2019-04-25 22:11:20 -04:00
Adrien Béraud e0241ccfbd dhtrunner: drop older packets in batch 2019-04-25 22:10:46 -04:00
Adrien Béraud d4311925b4 dhtrunner: shutdown: return if not running 2019-04-25 21:38:52 -04:00
Adrien Béraud 9aa56dd464 dhtnode/systemd: use simple service mode 2019-04-25 21:32:35 -04:00
Adrien Béraud ec3b259ead dhtnode/systemd: update default bootstrap 2019-04-25 21:18:11 -04:00
Adrien Béraud 332cab10ef tools: don't chdir to / when deamonizing 2019-04-25 21:17:44 -04:00
Adrien Béraud 85f2b618c7 logs: use ofstream for file logging 2019-04-25 14:31:06 -04:00
Adrien Béraud bcf18fda53 update to version 1.9.3 2019-04-25 11:10:42 -04:00
Adrien Béraud 6b78a4cad6 peerdiscovery: catch parsing errors 2019-04-25 10:25:36 -04:00
Adrien Béraud 66d3a8aeaa dhtrunner: cleanup 2019-04-24 14:51:43 -04:00
Adrien Béraud 958cb250a3 dhtnode: show both IPv4, IPv6 bound ports 2019-04-23 12:13:53 -04:00
Adrien Béraud 6a5724a868 peerdiscovery: allow per-domain publish, cleanup 2019-04-23 12:09:08 -04:00
Adrien Béraud 11ac84de54 Merge pull request #392 from MingruiZhangW/peer_discovery_version_2
peerdiscovery: modify to add support for sending and receiving msgpack
2019-04-23 11:20:18 -04:00
MingruiZhangW f65e8c1a1f Merge branch 'master' into peer_discovery_version_2 2019-04-22 09:13:17 -04:00
Adrien Béraud c2fdf6ae92 dhtnode: show grouped get results, improve duration display 2019-04-21 21:39:54 -04:00
Adrien Béraud 91a81f64ac thread pool: make public 2019-04-21 21:39:54 -04:00
Adrien Béraud 17b772e6cc proxy client: close all sockets before joining 2019-04-20 22:38:36 -04:00
Adrien Béraud 75738ac28b proxy client: don't hold lock while calling callback 2019-04-20 22:07:48 -04:00
Adrien Béraud 84a2d771c1 dht: add some missing override 2019-04-20 22:07:48 -04:00
Adrien Béraud f6273f9efc tools/dhtnode: improve documentation 2019-04-20 17:30:39 -04:00
Adrien Béraud 5881c91510 utils: include config.h 2019-04-19 20:24:01 -04:00
Adrien Béraud e09c55ca42 update to version 1.9.2 2019-04-19 16:15:56 -04:00
Andreas Traczyk c737e4690e update visual studio build 2019-04-19 15:53:42 -04:00
Adrien Béraud 35a9d1f612 proxy client: catch exception in Http::close() 2019-04-18 17:38:00 -04:00
Mingrui Zhang 0f3396cd66 peerdiscovery: make nested classes to hide ip versions 2019-04-18 12:20:17 -04:00
Mingrui Zhang 98cd6cc61e peerdiscovery: fix memory leakage cased by sbuffer release 2019-04-18 10:20:00 -04:00
Mingrui Zhang 092cb9551e peerdiscovery: add testpack into tester to verify the possibility of sending & receiving 2 packages simultaneously (including stop functions) 2019-04-18 09:33:15 -04:00
Mingrui Zhang a2bbca792c peerdiscovery: add dmtx_ to distinguish send & listen shared resources, add stopDiscovery, stoplisten to stop listen or discover certain type of service 2019-04-17 10:26:49 -04:00
Adrien Béraud 5ec72e213e dht: add override 2019-04-17 10:00:15 -04:00
Mingrui Zhang 0f51115f44 peerdiscovery: modify maps to handle more services in one instance 2019-04-16 15:11:07 -04:00
Adrien Béraud 683a111726 autotools: build versioned shared library 2019-04-16 12:23:32 -04:00
Adrien Béraud 0fd4fed537 search: add fallback return 2019-04-16 12:23:32 -04:00
Mingrui Zhang 18aa6ddb7b peerdiscovery: modify function signatures to make service consistent 2019-04-15 18:24:15 -04:00
Mingrui Zhang 0a436e17b0 peerdiscovery: modifications on tester fit for the updates 2019-04-15 17:26:59 -04:00
Mingrui Zhang 763ffddf51 peerdiscovery: modify to add support for sending and receiving msgpack 2019-04-15 16:50:48 -04:00
Adrien Béraud ef82652a1e network: header cleanup 2019-04-14 11:30:10 -04:00
Adrien Béraud 4f03a5c64e network: tid, socket_id, value_id: default to 0 2019-04-14 09:15:16 -04:00
Adrien Béraud 5257ac314f add API to retrieve version string 2019-04-14 00:19:01 -04:00
Adrien Béraud 0580a4e7dd update to version 1.9.1 2019-04-13 23:29:43 -04:00
Yanfei Han fd1f2cd0e4 add peer_discovery.o object into auto configure lib 2019-04-13 23:04:18 -04:00
Adrien Béraud af940c63b1 proxy: mute unused variable warning if disabled 2019-04-13 23:02:57 -04:00
Adrien Béraud 15da502354 dhtrunner: make peer discovery port static constexpr 2019-04-13 22:56:31 -04:00
Adrien Béraud b7a9a52f97 network engine: DhtProtocolException cleanup 2019-04-13 22:56:31 -04:00
Adrien Béraud 6e10756e28 peerdiscovery: cleanup 2019-04-13 22:56:31 -04:00
Adrien Béraud aad4ad03cf network utils: add missing includes 2019-04-13 22:56:31 -04:00
Adrien Béraud 3d1e055c7b peerdiscovery: always use local node id 2019-04-13 20:50:00 -04:00
Adrien Béraud b02e9cfff7 peerdiscovery: flush stop socket if not stopping 2019-04-13 20:50:00 -04:00
Adrien Béraud 453db29058 dht: add override to getNodeId 2019-04-13 20:43:57 -04:00
Adrien Béraud a8ba536d44 update to version 1.9.0 2019-04-09 16:25:39 -04:00
Adrien Béraud a238183031 peerdiscovery: don't assign IPv6 multicast interface 2019-04-09 16:11:21 -04:00
Adrien Béraud 73827cd34d peerdiscovery: allow IPV6_MULTICAST_IF failure 2019-04-09 15:12:37 -04:00
Adrien Béraud 876190a392 peerdiscovery: SO_REUSEADDR, SO_REUSEPORT in different calls 2019-04-09 14:58:22 -04:00
Adrien Béraud 7fe321e4fc peerdiscovery: cleanup data serialization 2019-04-09 14:57:48 -04:00
Adrien Béraud 7f7075ca9a peerdiscovery: support IPV6_JOIN_GROUP 2019-04-09 12:31:23 -04:00
Adrien Béraud 9b9f12d87e tests: accept null token if callback returns false 2019-04-08 15:58:46 -04:00
Adrien Béraud 26ad6de3a4 dhtrunner: avoid race condition when setting token 2019-04-08 15:57:25 -04:00
Adrien Béraud ae91f8bd55 dhtrunner: default-initialize tokens 2019-04-08 15:36:24 -04:00
Adrien Béraud 28eeee24ba runnertester: reduce number of test values 2019-04-08 15:35:55 -04:00
Adrien Béraud 671c55a01d dhtrunner: print peer discovery error message to cerr 2019-04-08 14:36:15 -04:00
Adrien Béraud a4f2e6efdd tests: avoid use-after-free in proxytester 2019-04-08 13:06:32 -04:00
Adrien Béraud 60831ee898 peerdiscovery: avoid crashing if message can't be sent 2019-04-08 13:02:39 -04:00
Adrien Béraud 98dbe1cba7 gitignore: ignore files from vscode, eclipse 2019-04-08 12:07:35 -04:00
Adrien Béraud 6c705e525f net: factorize logic to network_utils 2019-04-08 12:07:11 -04:00
Adrien Béraud 96347d83e1 tools: add argument for peer discovery 2019-04-08 11:34:52 -04:00
Adrien Béraud 01d8e513a1 peerdiscovery: cleanup 2019-04-08 11:34:52 -04:00
Mingrui Zhang b5921b0d9d peerdiscovery: error correction for tester, distinguish creation error(ip version support) and listen/receive error 2019-04-08 11:32:08 -04:00
Mingrui Zhang 8ee7883c53 peerdiscovery: Exception added for supporting construction error 2019-04-08 11:32:08 -04:00
Mingrui Zhang 4240820463 peerdiscovery: add multicast node discovery mechanism 2019-04-08 11:32:08 -04:00
Adrien Béraud 7ebbf17f37 InfoHash: use static size 2019-04-05 11:21:23 -04:00
Adrien Béraud 6821e5bd96 dhtrunner: default to null function instead of AllFilter 2019-04-05 10:49:40 -04:00
Adrien Béraud c4ec1e78e0 tests: fix occasional testListen failure 2019-04-05 10:49:35 -04:00
Adrien Béraud e86d717e81 dht: make getPut() const 2019-04-05 10:49:35 -04:00
Adrien Béraud db2b48d2af dhtrunner: select on maxfd+1 2019-04-03 16:18:35 -04:00
Adrien Béraud 2b938110fd cmake: force indexation if python is enabled 2019-04-03 14:52:35 -04:00
Adrien Béraud c647b19e91 infohash: make some methods constexpr, noexcept 2019-04-03 14:52:35 -04:00
Sébastien Blin 8cd14646a6 Merge pull request #387 from savoirfairelinux/cert_request
crypto: add certificate request support
2019-04-01 09:30:33 -04:00
Adrien Béraud d80aab9399 pingpong: cleanup 2019-03-29 13:13:29 -04:00
Adrien Béraud 9b881d4e95 crypto: add initial certificate request support 2019-03-29 13:13:29 -04:00
Adrien Béraud b4c3c2cba0 update to version 1.8.2 2019-03-18 13:47:41 -04:00
Sébastien Blin 4519a23996 Merge pull request #386 from savoirfairelinux/parse_perf
Network: improve parsing performance
2019-03-18 13:13:57 -04:00
Adrien Béraud 1ac4e08f45 build: add clang-tidy configuration 2019-03-17 19:23:26 -04:00
Adrien Béraud 5e92777702 fix clang-tidy warnings 2019-03-17 19:22:28 -04:00
Adrien Béraud 4401e47002 cleanup, fix clang-tidy warnings 2019-03-17 17:43:52 -04:00
Adrien Béraud 215b44ca3b search: don't store filter in search
Filter is not supported anymore at the search listen stage.
Filters are now stored and called by the op cache.
2019-03-17 17:30:30 -04:00
Adrien Béraud 379fdae212 cmake: don't explicitly disable stack protector 2019-03-17 16:07:20 -04:00
Adrien Béraud 1e10e28fd7 network: improve message parsing performance 2019-03-17 16:07:20 -04:00
Adrien Béraud dccdb84836 tests: add Value tester 2019-03-16 14:27:46 -04:00
Adrien Béraud 71599da8ea value: add "not" method 2019-03-16 14:27:23 -04:00
Adrien Béraud f418b3651f update copyright date 2019-03-16 12:37:23 -04:00
Adrien Béraud 313f54c840 dht: disable some verbose logs 2019-03-10 17:27:37 -04:00
Adrien Béraud cdb721ade4 dht: move store logic to storage 2019-03-10 17:04:26 -04:00
Adrien Béraud 57ea09808e value: fix chain null check 2019-03-10 16:39:31 -04:00
Adrien Béraud fec5a6ede7 make move operators noexcept 2019-03-10 16:39:16 -04:00
Adrien Béraud 5f8e9d9480 storage: make non-movable 2019-03-10 16:39:16 -04:00
Adrien Béraud 311a8981fc thread pool: add computation, io pools 2019-03-10 16:39:16 -04:00
Adrien Béraud 04850e1701 dht: add configuration to persist state 2019-03-10 16:39:16 -04:00
Adrien Béraud a30f1b8032 dht: make exportNodes const 2019-03-10 16:39:16 -04:00
Sébastien Blin 41f8b06743 Merge pull request #376 from savoirfairelinux/server_thread_pool
Server thread pool
2019-02-19 19:57:13 -05:00
Adrien Béraud 1c74c2207f proxy server: cache json StreamBuilder 2019-02-19 18:43:14 -05:00
Adrien Béraud 9319bec7b8 proxy client: close previous request on resubscribe 2019-02-19 18:43:14 -05:00
Adrien Béraud e5f2a6eef5 proxy: send expired to sync values 2019-02-19 18:43:14 -05:00
Adrien Béraud 55f6c847b8 build: use define flags for proxy 2019-02-19 18:43:14 -05:00
Adrien Béraud 00cc4ebe28 proxy server: send push notification on thread pool 2019-02-19 18:43:14 -05:00
Adrien Béraud aa93db4fa6 proxy server: move json to sendPushNotification 2019-02-19 18:43:14 -05:00
Adrien Béraud 683570a3da add ThreadPool 2019-02-19 18:43:14 -05:00
Sébastien Blin 43559577f6 Merge pull request #377 from savoirfairelinux/proxy_sync_expired
Proxy: sync expired state
2019-02-19 18:42:32 -05:00
Adrien Béraud ba2e179abe dht: optimize get 2019-02-19 01:59:59 -05:00
Adrien Béraud a5d29c904c op cache: optimize cache insertion 2019-02-19 01:59:59 -05:00
Adrien Béraud 989f32eb56 filter: cleanup and optimize 2019-02-19 01:59:59 -05:00
Adrien Béraud b66fa73c56 test: include cppunit headers 2019-02-19 01:59:59 -05:00
Adrien Béraud 1ca181db1d value: simplify expression 2019-02-19 01:59:59 -05:00
Adrien Béraud 1f3bf697c3 search: use syncStatus for get 2019-02-19 01:59:59 -05:00
Adrien Béraud a1f8cc906c proxy client: use SyncCallback 2019-02-19 01:59:59 -05:00
Adrien Béraud 35c6a57526 dht: add synced status 2019-02-19 01:59:59 -05:00
Adrien Béraud 39e69f813c network engine: cleanup 2019-02-19 01:59:59 -05:00
Sébastien Blin 8045c2cbf2 dhtrunner: avoid startNetwork failure if only one binding is failing 2019-02-19 01:44:47 -05:00
Sébastien Blin 79a2f4280f proxy: resolve url with protocol and port 2019-02-14 11:04:11 -05:00
Sébastien Blin 769ce45740 proxy_client: support prototype in serverHost 2019-01-22 07:56:27 -08:00
Sébastien Blin 75a14d3608 proxy: only get old values at first subscribe 2019-01-18 22:53:24 -08:00
Sébastien Blin d523e9f259 tests: test retrieve values when resubscribe 2019-01-14 10:53:08 -08:00
Sébastien Blin 3a3933e6d5 dhtproxy: remove sendSubscribe 2019-01-14 10:53:08 -08:00
Sébastien Blin 70f09ded3f dhtproxy: avoid notification after subscribe to retrieve values 2019-01-14 10:53:08 -08:00
Sébastien Blin 824a1bf5fa proxy_server: return old values when resubscribe 2019-01-14 10:53:08 -08:00
Sébastien Blin e5b56cc0a5 dht: link to tellListenerRefreshed
When a permanent put is refreshed, the node has to tell to its
remote listeners that the value is refreshed.
2019-01-09 13:34:51 -08:00
Sébastien Blin 36cf70f2a7 proxy: remove useless token for push listeners
Since we authentificate listeners with the clientId and the hash and
we use only one listener by hash/clientId, we doesn't need to store
a token always equals to 0.

Note: also avoid to get multiple hashes for one push notification.
2018-12-30 13:35:18 -05:00
Adrien Béraud 459c1344aa update to version 1.8.1 2018-12-28 11:38:15 -05:00
Adrien Béraud c0e376e15a dht: reduce log verbosity 2018-12-28 01:41:10 -05:00
Adrien Béraud 71b9672b96 value: don't print certificate id in toString by default 2018-12-28 01:38:45 -05:00
Adrien Béraud 086f37a71a op cache: remove listener if callback returned false 2018-12-28 01:38:02 -05:00
Adrien Béraud 87e76a5e4e tests: reverse nodes 2018-12-26 13:03:36 -05:00
Adrien Béraud 7f0a5dfda3 dht: increase max number of searches and hashes 2018-12-26 10:28:55 -05:00
Adrien Béraud 6d7f8004bf connectivity change: reset routing table instead of searches 2018-12-26 10:28:30 -05:00
Adrien Béraud 8168c39b63 dht: cleanup 2018-12-26 01:22:37 -05:00
Adrien Béraud d0fdbe5340 dhtrunner: print proper message on bind error 2018-12-26 00:58:43 -05:00
Adrien Béraud c7604fbb8d tests: wait for put before performing get 2018-12-26 00:56:49 -05:00
Adrien Béraud 56773baa98 unit tests: add listen test 2018-12-24 19:09:32 -05:00
Adrien Béraud e6cf67c575 dht: clear local listener if callback returns false 2018-12-24 18:37:06 -05:00
Adrien Béraud 00ebc5e2bf op cache: check callback return value 2018-12-24 18:36:29 -05:00
Adrien Béraud ccef94c11b Revert "storage: make non-movable"
This reverts commit 7ebad7d3c5.
2018-12-24 17:16:15 -05:00
Adrien Béraud 0066be49b9 python: add more bindings for SockAddr 2018-12-24 16:55:25 -05:00
Adrien Béraud 592ed4ee90 op cache: don't call callback if no value 2018-12-24 15:50:41 -05:00
Adrien Béraud 353a6f9db6 op cache: add onCancel callback 2018-12-24 15:41:17 -05:00
Adrien Béraud 7ebad7d3c5 storage: make non-movable 2018-12-24 15:28:03 -05:00
Adrien Béraud 14f6e6e5f3 proxy client: catch exceptions in restbed::Http::async 2018-12-22 23:45:37 -05:00
Adrien Béraud 9ce5b30931 securedht: use query to check for existing value 2018-12-22 11:42:45 -05:00
Adrien Béraud 92979fa96a dhtchat: add logging support 2018-12-21 19:55:27 -05:00
Adrien Béraud 0c1e7d2763 dht: run node confirmation if bucket was empty 2018-12-19 14:07:55 -05:00
Adrien Béraud 14a744f6cd dht: log cleanup 2018-12-19 14:07:55 -05:00
Adrien Béraud 3b26684a87 network engine: add default values for sendFindNodes 2018-12-19 14:07:55 -05:00
Sébastien Blin 0a764ee440 Merge pull request #361 from savoirfairelinux/schedule_restart
proxy client: schedule listener restart
2018-12-18 16:07:39 -05:00
Adrien Béraud 7dda5a3d5a proxy client: schedule listener restart 2018-12-18 10:10:14 -05:00
Adrien Béraud 306d573223 proxy client: fix race condition 2018-12-17 16:41:00 -05:00
Sébastien Blin 20f4355b73 Merge pull request #356 from savoirfairelinux/build
securedht: add override
2018-12-11 14:52:07 -05:00
Adrien Béraud a2d7cd56a8 Merge pull request #358 from atraczyk/master
replace _write with send when building for windows
2018-12-11 14:48:26 -05:00
Andreas Traczyk 5cd53f3624 replace _write with send when building for windows 2018-12-11 14:37:14 -05:00
Adrien Béraud 32eea55f10 autotools: don't build doc if doxygen not found 2018-12-11 14:04:35 -05:00
Adrien Béraud f2f913f93f securedht: add override for relevant methods 2018-12-11 14:04:35 -05:00
Adrien Béraud cb9fe9d1fe Merge pull request #354 from atraczyk/master
msvc: replace write with _write when building on windows
2018-12-06 12:23:36 -05:00
Andreas Traczyk dcab32ef4f replace write with _write when building with msvc 2018-12-06 12:16:59 -05:00
Adrien Béraud 4948bd7ad3 node cache: remove expired weak pointers from cache
Remove expired Node weak pointers regularly,
in a way that ensures that:
* every expired pointer gets eventually cleaned up
* expired pointer ratio remains reasonably low
* no cleanup pass blocks the node for too long,
* impact on performance is negligible

Impact on performance:
Every N insertions, at most N nodes are tested by iterating the map
-> performance impact in O(1) (constant).
2018-11-29 19:27:32 -05:00
Adrien Béraud 4416b91461 update to version 1.8.0 2018-11-28 18:44:03 -05:00
Adrien Béraud 378ae396f0 Merge pull request #351 from hanyf/master
A obvious bug on network engine
2018-11-28 12:48:02 -05:00
Yanfei Han dc4a790a38 A obviouse bug on network engine 2018-11-29 00:47:00 +08:00
Sébastien Blin 07dd8f5648 Merge pull request #350 from savoirfairelinux/feature/cache
Feature/cache
2018-11-28 09:22:06 -05:00
Adrien Béraud f7433a2289 travis: update to xenial 2018-11-26 16:48:00 -05:00
Adrien Béraud ce4a65ff00 dhtrunner: add APIs for listen<T> with expiration information 2018-11-26 16:34:19 -05:00
Adrien Béraud 092f5cfef0 network_engine: fix warning 2018-11-26 16:34:19 -05:00
Adrien Béraud 12a45e7558 cmake: remove unnecessary flags for lto 2018-11-26 16:30:18 -05:00
Adrien Béraud 18d359a7d2 dht: refresh value if already exists 2018-11-26 01:57:57 -05:00
Adrien Béraud c6bb67d1ac dht: add storageRefresh 2018-11-26 01:57:57 -05:00
Adrien Béraud f4cd7636ce securedht: use signature cache in storePolicy, editPolicy 2018-11-26 01:57:57 -05:00
Adrien Béraud 2dd4e640c4 dhtrunner: add APIs for listen<T> with expiration information 2018-11-25 23:01:03 -05:00
Adrien Béraud 9a301e3590 Revert "cmake: use CMAKE_INTERPROCEDURAL_OPTIMIZATION for LTO"
This reverts commit b7b5152348.
2018-11-24 15:32:29 -05:00
Sébastien Blin aa16b9a235 Merge pull request #348 from savoirfairelinux/feature/probepermanent
dht: don't send probe query for non permanent puts
2018-11-23 10:10:35 -05:00
Adrien Béraud b2542a57df securedht: cache value signature check/decryption results 2018-11-22 15:43:55 -05:00
Adrien Béraud 00c1be9cdc logger: use DBG for DEBUG to avoid name conflicts 2018-11-22 15:43:55 -05:00
Adrien Béraud e414ca89c7 dht: don't send probe query for non permanent puts 2018-11-22 15:43:55 -05:00
Adrien Béraud 4d26537b93 Merge pull request #346 from AmarOk1412/fix/finished
dht_proxy_client: fix finished behavior
2018-11-11 22:19:50 -05:00
Sébastien Blin 00a9333de7 dht_proxy_client: fix finished behavior
callback_.emplace_back() returns immediately, so, in some case,
finished can be set to true even before we execute one callback.
Finished should not be used into callback. This patch adds a
finished variable only used by the callbacks to avoid this
case.

This improve the reactivity of the proxy client.
2018-11-11 15:27:57 -05:00
Adrien Béraud 971f96bf95 dhtrunner: improve getId()/getNodeId() documentation. 2018-10-29 16:23:21 -04:00
Adrien Béraud f9a12a9dca crypto: use proper size for getRandom()
Provided size should be the number of elements, not the number of bytes.
Also, if secure_vector where used with sizeof(T) > 1 (currently not the case),
there would be memory write to invalid address.
2018-10-29 16:21:51 -04:00
Adrien Béraud c05a93ae54 proxy server: cleanup 2018-10-29 12:45:52 -04:00
Adrien Béraud ff83a6daab proxy: support value expiration 2018-10-29 12:45:52 -04:00
Adrien Béraud b7b5152348 cmake: use CMAKE_INTERPROCEDURAL_OPTIMIZATION for LTO 2018-10-27 16:38:37 -04:00
Adrien Béraud a3768d1e50 cmake: use LINK_FLAGS for LTO 2018-10-27 14:57:51 -04:00
Adrien Béraud 94926cea22 proxy server: avoid early session close 2018-10-27 13:21:26 -04:00
Adrien Béraud 82ca2d1993 cmake: use single target_link_libraries for static library 2018-10-27 12:30:40 -04:00
Adrien Béraud 3e148599c5 proxy server: stop get if session is closed 2018-10-27 12:20:00 -04:00
Adrien Béraud 02d5592fdb cmake: improve restbed, jsoncpp search & usage 2018-10-27 11:51:42 -04:00
Adrien Béraud 328b306fd0 crypto: add documentation 2018-10-27 11:50:26 -04:00
Adrien Béraud 522a89b6f8 dht: use search cache for get ops 2018-10-27 11:49:55 -04:00
Adrien Béraud 897b451f44 crypto: fix build on Win32 2018-10-26 13:16:02 -04:00
Adrien Béraud ba3a42697c Merge pull request #331 from Dale-M/master
Some additions to automake infrastructure to get clean default build.
2018-09-20 14:24:34 -04:00
Adrien Béraud 5112a322de dht: reschedule permanent put refresh after request 2018-09-19 01:54:54 -04:00
Adrien Béraud 85961c6a62 storage: properly refresh expiration 2018-09-19 01:54:54 -04:00
Adrien Béraud 1eb1f3d5ac storageStore: add permanent mode 2018-09-19 01:54:54 -04:00
Adrien Béraud 726c138d90 dht: move storageStore to put 2018-09-19 01:54:54 -04:00
Adrien Béraud 1b6b1ca072 comments: fix typos 2018-09-19 01:54:54 -04:00
Dale Mellor 77da72c603 Some additions to automake infrastructure to get clean default build.
Be sure to pull in paths to headers for json and MsgPack dependencies.

Be sure to always build the base64 encoder and decoder, as they are
needed.
2018-09-17 09:40:07 +01:00
Adrien Béraud 7fb2da7c54 dhtrunner: avoid polling, use pipe to stop select 2018-09-15 17:22:12 -04:00
Sébastien Blin 6721a272ea Merge pull request #327 from savoirfairelinux/value_cache
value_cache: expire value if expiration is now
2018-08-12 10:42:22 -04:00
Adrien Béraud 246af2f065 value_cache: expire value if expiration is now 2018-08-11 21:27:18 -04:00
Adrien Béraud 57aba453b0 Merge pull request #325 from AmarOk1412/siteProxy
proxyserver: add stats endpoint for monitoring
2018-08-10 15:05:07 -04:00
Sébastien Blin f54fcd768f proxyserver: add stats endpoint for monitoring 2018-08-10 15:03:09 -04:00
Sébastien Blin 5b81476baf Merge pull request #326 from savoirfairelinux/tests
tests: add unit tests for certificate revocation
2018-08-09 17:11:20 -04:00
Adrien Béraud 5b510cadfb tests: add unit tests for certificate revocation 2018-08-09 14:51:02 -04:00
Adrien Béraud c794781644 update to version 1.7.4 2018-07-31 13:45:56 -04:00
Adrien Béraud 2ef4999b0f Merge pull request #322 from AmarOk1412/incorrectOk
dhtproxyclient: fix ok when a permanent PUT operations fails
2018-07-31 10:16:05 -04:00
Sébastien Blin 6069fba18f dhtproxyclient: fix ok when a permanent PUT operations fails 2018-07-31 09:42:23 -04:00
Adrien Béraud 37ddd8c7f9 update to version 1.7.3 2018-07-25 16:40:47 -04:00
Adrien Béraud 23057a3082 unit tests: fix race condition 2018-07-25 11:54:28 -04:00
Adrien Béraud dbdd3f8f63 Merge pull request #319 from AmarOk1412/fixLD
dhtrunner: don't use listeners structure without proxy client enabled
2018-07-25 11:32:55 -04:00
Sébastien Blin 751e79a250 dhtrunner: don't use listeners structure without proxy client enabled
The token used to cancel a listener was wrong. Indeed, tokenBGlobal
was used to get the linked listener, not to identify the listener
inside dhtrunner.
2018-07-25 11:28:46 -04:00
Adrien Béraud 7a961ffc51 Merge pull request #318 from atraczyk/master
build: replace WIN32_NATIVE macro with _MSC_VER
2018-07-23 14:01:17 -04:00
Andreas Traczyk bfada958b9 build: replace WIN32_NATIVE macro with _MSC_VER 2018-07-23 13:45:52 -04:00
Sébastien Blin 78d91a8e0d Merge pull request #316 from savoirfairelinux/proxy_server
dhtrunner: decrease max packet handling delay to 500ms
2018-07-13 14:37:09 -04:00
Adrien Béraud cd5dc38a57 dhtrunner: decrease max packet handling delay to 500ms
Allows for faster recovery in case of CPU contention
2018-07-13 14:29:59 -04:00
Sébastien Blin 1ff2eeb220 Merge pull request #313 from savoirfairelinux/proxy_server
Proxy server
2018-06-28 09:16:13 -04:00
Adrien Béraud ffbb9e23ef dht: show usage at the end, print max store size 2018-06-27 11:54:15 -04:00
Adrien Béraud af0a30c9c5 dhtrunner: drop oldest packet if queue is full 2018-06-26 20:41:04 -04:00
Sébastien Blin 97d5e3875d Merge pull request #312 from savoirfairelinux/dht_performance
Dht performance
2018-06-21 11:49:09 -04:00
Adrien Béraud 2509e8bc5c Revert "search: use pointer to SearchNode"
This reverts commit 3a41f2ce56.
2018-06-20 14:50:40 -04:00
Adrien Béraud e349912c07 search: improve canGet performance 2018-06-20 14:50:40 -04:00
Adrien Béraud a1fc266eac dhtrunner: add max rx queue size 2018-06-19 14:10:57 -04:00
Adrien Béraud 3e3679bebf dhtrunner: drop packet if processing took too long 2018-06-18 15:52:20 -04:00
Adrien Béraud e9cf16f361 cmake: allow to enable push notifications without proxy server 2018-06-15 21:09:37 -04:00
Adrien Béraud 3dca4db408 dhtrunner: don't setProxyServer in headers
Don't define setProxyServer in headers since it depends on a configuration option
2018-06-15 12:18:56 -04:00
Sébastien Blin fb6d290692 Merge pull request #309 from savoirfairelinux/searchnode
SearchNode: refresh token
2018-06-13 10:35:51 -04:00
Adrien Béraud 96c60d39ed proxy server: reschedule after using function 2018-06-12 18:19:12 -04:00
Adrien Béraud 3a41f2ce56 search: use pointer to SearchNode 2018-06-12 16:54:12 -04:00
Adrien Béraud 5bd88533fe SearchNode: refresh token in Query, Listen answers 2018-06-12 16:50:15 -04:00
Adrien Béraud c48e24403b Merge pull request #296 from AmarOk1412/resub
proxy: refresh puts and subscriptions when connectivity changes
2018-06-06 12:18:58 -04:00
Sébastien Blin 3cf2c092f2 proxy: remove useless convertion from InfoHash to InfoHash 2018-06-06 12:16:10 -04:00
Sébastien Blin aef8aa545b proxy: reschedule printStatsJob 2018-06-06 12:08:31 -04:00
Sébastien Blin 0c61a605ad proxy: refresh puts and subscriptions when connectivity changes 2018-06-06 11:29:40 -04:00
Sébastien Blin e6b247bead Merge pull request #307 from savoirfairelinux/crypto_tests
test: add crypto unit test
2018-06-06 10:05:10 -04:00
Sébastien Blin 6f1f18f128 Merge pull request #302 from savoirfairelinux/getnodeinfo
dhtrunner: add getNodeInfo()
2018-06-06 10:04:57 -04:00
Adrien Béraud f24458860d test: add crypto unit test 2018-06-06 01:12:18 -04:00
Adrien Béraud 07bed77714 proxy server: schedule task from outside thread 2018-06-05 19:43:56 -04:00
Adrien Béraud aa202b2cd8 dhtrunner: add getNodeInfo()
Allow to retrieve all dht stats in a single API call using
the new method getNodeInfo() and the JSON-serializable
new structure NodeInfo.
2018-06-05 19:43:56 -04:00
Adrien Béraud 4c89ce9d3f Merge pull request #303 from AmarOk1412/getNodeStats
dht_proxy_server: avoid mutex when getting /
2018-05-30 17:01:56 -04:00
Sébastien Blin 709a2c7b7c dht_proxy_server: avoid mutex when getting /
The dht_proxy_server should be always up, so getNodesStats will
be pretty always up-to-date. We can add it into a job and avoid
to wait for this method to finish (and this method use an
internal lock) to have a quick answer about the status of the proxy.

Note: the update is forced during the initialization of the proxy
2018-05-30 14:25:46 -04:00
Adrien Béraud b7e483078a proxy: fix typo 2018-05-25 10:26:58 -04:00
Adrien Béraud b2171d707a network engine: properly apply flag MSG_NOSIGNAL 2018-05-25 10:26:58 -04:00
Adrien Béraud 60db9fd9cd logs: reduce node expiration to debug level 2018-05-25 10:26:58 -04:00
Adrien Béraud e8989f1f79 network engine: handle EPERM 2018-05-24 16:07:16 -04:00
Adrien Béraud b7218bd1c9 Merge pull request #299 from savoirfairelinux/tests
travis: run CI with ASAN
2018-05-24 15:46:56 -04:00
Adrien Béraud 43aab40968 travis: run CI with ASAN 2018-05-24 15:31:52 -04:00
Sébastien Blin ed57b3bfa9 Merge pull request #300 from savoirfairelinux/leak
network engine: fix node leak during destruction
2018-05-24 15:14:22 -04:00
Adrien Béraud 9249f34c47 network engine: fix node leak during destruction 2018-05-24 15:01:23 -04:00
Sébastien Blin 57401e8d53 Merge pull request #297 from savoirfairelinux/logs
log: fix LogMethod copy
2018-05-24 14:55:06 -04:00
Adrien Béraud f5f71a0365 log: fix LogMethod copy 2018-05-24 11:57:12 -04:00
Adrien Béraud 1fe9f2fdb1 dhtnode: default-initialize dht config 2018-05-23 11:21:25 -04:00
Sébastien Blin 59d129b8ff Merge pull request #293 from savoirfairelinux/proxy_fixes
Proxy fixes
2018-05-17 14:47:16 -04:00
Adrien Béraud 5b5349d7ad proxy client: lock proxy info thread, catch detach exceptions 2018-05-17 11:34:25 -04:00
Adrien Béraud b2ba1ca002 proxy server: close socket if no token 2018-05-17 11:33:32 -04:00
Adrien Béraud 8606e87684 proxy client: allow concurrent proxy info requests (#292) 2018-05-11 15:47:24 -04:00
Adrien Béraud e4f640f11b update to version 1.7.2 2018-05-08 15:58:24 -04:00
Adrien Béraud e31d301d90 dhtrunner: run connectivityChanged() even when disconnected 2018-05-08 15:58:24 -04:00
Adrien Béraud 2a15435be3 Merge pull request #291 from AmarOk1412/fixPushIdle
proxy: set status to CONNECTED when receiving a push notifications
2018-05-08 13:46:59 -04:00
Adrien Béraud 44a411ba96 Merge pull request #279 from savoirfairelinux/testsproxy
tests: begin tests for dht_proxy_server
2018-05-08 13:46:42 -04:00
Sébastien Blin bf2f2369b1 proxy: set status to CONNECTED when receiving a push notifications
If a device receives a push notification, we can assume that the
proxy is up and running (because it sends a push notification).

Indeed, if the proxy is declared as disconnected, no operatons will
be executed when a push notification is received. This state is logic
when not using push notifications (because the local node is down),
but here, the status depends more on the proxy than the local node.
2018-05-08 13:35:13 -04:00
Adrien Béraud b8b1f61268 search: announce immediately if synced and not pending/completed 2018-05-07 17:43:31 -04:00
Adrien Béraud 63db2eafd9 dht: print detailed request state in search log 2018-05-07 17:43:31 -04:00
Adrien Béraud 68f52a815d proxy client: refactor (#289)
Factor various ways of sending listen requests.
2018-05-07 14:54:32 -04:00
Adrien Béraud 9f35acf559 dhtnode: continue cmd loop on connectivity change 2018-05-05 18:23:52 -04:00
Adrien Béraud d8e82ca7c4 dhtrunner: check dht before getting public addresses 2018-05-04 21:41:39 -04:00
Adrien Béraud 981bcfc0ba dht: handle error when sending listen 2018-05-02 14:26:24 -04:00
Adrien Béraud 4a49a53222 Revert "network engine: expire node on next run on network failure"
This reverts commit 8489433060.
2018-05-02 11:55:01 -04:00
Sébastien Blin 9f987e24fe Merge pull request #277 from savoirfairelinux/proxy_refresh
proxy client: independently resubscribe push listeners
2018-04-30 10:56:18 -04:00
Sébastien Blin 95f1d59a7f proxy: add comment for refresh job 2018-04-30 10:42:39 -04:00
Adrien Béraud a4fe27223f immessage: fix warning 2018-04-30 10:40:47 -04:00
Adrien Béraud 5408dc6f09 Merge pull request #287 from AmarOk1412/immsgwithdt
immessage: add support for custom datatypes
2018-04-27 13:34:23 -04:00
Adrien Béraud 35d4c1d332 Merge pull request #288 from AmarOk1412/restartListenerWithoutPush
proxy: restart listeners if the proxy server close the connection
2018-04-27 13:33:59 -04:00
Sébastien Blin c583b7284c tests: add testListen for DhtProxyTester 2018-04-26 17:05:23 -04:00
Sébastien Blin 2ce0c5c4c9 proxy: restart listeners if the proxy server close the connection
Detect if the proxy server close the connection linked to a listener and
relaunch listeners
2018-04-26 16:45:14 -04:00
Sébastien Blin 484194c114 immessage: add support for custom datatypes 2018-04-23 17:39:37 -04:00
Adrien Béraud b26b78c049 dhtrunner: fix warnings 2018-04-21 17:57:59 -04:00
Adrien Béraud 522a15c410 proxy client: refresh persistent put with margin 2018-04-21 17:57:59 -04:00
Adrien Béraud 6a981772fd proxy server: cleanup 2018-04-21 17:57:59 -04:00
Adrien Béraud cc37fb50e2 proxy client: take persistent put by reference 2018-04-21 17:44:45 -04:00
Adrien Béraud 1c9acfe001 proxy client: call opFailed on failure 2018-04-21 15:08:48 -04:00
Adrien Béraud c6cef856f0 proxy server: cleanup 2018-04-21 12:23:33 -04:00
Adrien Béraud 9f503dbb65 proxy client: loopSignal on put refresh notification 2018-04-21 12:22:58 -04:00
Adrien Béraud 7e4478123f proxy client: use time_point::max() on persistent put 2018-04-21 12:22:00 -04:00
Adrien Béraud e54d26aaf7 dhtrunner: handle push notification on main dht loop 2018-04-21 12:21:00 -04:00
Adrien Béraud ee749d1ea7 update to version 1.7.1 2018-04-20 22:21:15 -04:00
Adrien Béraud a0d77e7b19 Merge pull request #283 from savoirfairelinux/fixPush
proxy server, fix push listeners and avoid flooding nodes
2018-04-20 18:46:04 -04:00
Sébastien Blin 9421984a89 proxy: cancelPushListeners using clientId instead of token
All listeners uses a token equals to 0, we need to identify listeners
with client_id instead of a token.
2018-04-20 16:37:12 -04:00
Sébastien Blin 37ef1c2cff proxy: set clientId to listener
clientId was not properly set. so every time someone launch a node
and do a listen on a hash, a new listener is generated and it results
by flooding the node of push notifications.
2018-04-20 16:19:03 -04:00
Sébastien Blin 0a04a7f28d proxy: unsubscribe is now valid with token equals 0
Because we now have one listener for each client by hash, the token
is unnecessary here. Moreover, this check is invalid cause we use
a token equal to 0.
2018-04-20 15:25:57 -04:00
Sébastien Blin b47a85fe09 Merge pull request #282 from savoirfairelinux/op_time_cache
op cache: keep listeners alive for some time after cancel
2018-04-20 13:43:32 -04:00
Adrien Béraud 4b7b3cd518 dhtrunner: use proper token with cancelListen(future<token>) 2018-04-20 13:35:13 -04:00
Adrien Béraud 1a2d783c2a op cache: keep listeners alive for some time after cancel 2018-04-20 11:35:45 -04:00
Sébastien Blin 7f943e07a5 tests: begin tests for dht_proxy_server
Like dhtrunnertester add testGetPut for the dht_proxy_server.
2018-04-19 13:08:26 -04:00
Adrien Béraud f98658f10f proxy client: independently resubscribe push listeners 2018-04-19 11:32:22 -04:00
Adrien Béraud 8b6dcb1cd5 dhtnode: allow to trigger connectivity change 2018-04-19 11:31:08 -04:00
Adrien Béraud e140116fed proxy client: close old socket when restarting listeners 2018-04-19 11:31:08 -04:00
Sébastien Blin c16a65a055 Merge pull request #276 from savoirfairelinux/proxy_refresh
Proxy/subscribe: improve refresh/cancel behavior
2018-04-16 15:41:19 -04:00
Adrien Béraud da1b7d4615 proxy server: send refresh notification with margin 2018-04-16 15:05:28 -04:00
Adrien Béraud 7b3ce69b62 proxy client: send remote token on cancel 2018-04-16 15:04:57 -04:00
Adrien Béraud 8a52a7f72a build: add missing files, cleanup 2018-04-16 14:17:52 -04:00
Adrien Béraud abb9f9291b proxy server: avoid unneeded copy 2018-04-14 18:15:02 -04:00
Adrien Béraud e533f5686e proxy server: use std::lock to avoid deadlock 2018-04-14 18:14:42 -04:00
Adrien Béraud 4234908b69 proxy server: check refresh job 2018-04-13 15:59:46 -04:00
Adrien Béraud c10c4251b0 proxy server: print stats to stdout once in a while 2018-04-13 15:52:56 -04:00
Adrien Béraud 8b90c47379 proxy server: add logs 2018-04-13 15:06:49 -04:00
Sébastien Blin fae6b13897 Merge pull request #275 from savoirfairelinux/proxy
proxy server: catch exceptions in requests, always close connection
2018-04-13 14:17:04 -04:00
Adrien Béraud a48a965c1a proxy server: catch exceptions in requests, always close connection 2018-04-13 14:01:09 -04:00
Adrien Béraud ab0f4f6f17 proxy client: refresh now in case of refresh notification 2018-04-13 11:14:40 -04:00
Adrien Béraud e3114cd5b9 proxy client: catch name resolving exception 2018-04-13 11:09:34 -04:00
Adrien Béraud 8489433060 network engine: expire node on next run on network failure 2018-04-11 11:27:46 -04:00
Sébastien Blin 6594d90042 Merge pull request #273 from savoirfairelinux/proxy_single_push
proxy server: keep only one push listener per token/key
2018-04-11 10:24:14 -04:00
Adrien Béraud 7c5145bca5 dhtnode: don't maintain storage 2018-04-10 16:01:14 -04:00
Adrien Béraud e088cd10be proxy server: keep only one push listener per token.key.clientId 2018-04-10 16:01:14 -04:00
Adrien Béraud 6a2f61a0db dht: fix compilation warnings 2018-04-10 12:48:19 -04:00
Adrien Béraud 7b88a2122a proxy: always use string tokens 2018-04-10 12:48:19 -04:00
Sébastien Blin f9cf95d537 Merge pull request #272 from savoirfairelinux/proxy_client
Proxy client: multiple improvements and bug fixes
2018-04-09 12:21:29 -04:00
Adrien Béraud 4884306135 proxy client: restart listeners on reconnect
* track IPv4, IPv6 connectivity seperately
* properly restart listeners when connected
* get proxy info in parallel for multiple AF
2018-04-08 19:54:43 -04:00
Adrien Béraud fd11a4b3e4 proxy client: prevent callback during cancelAllListeners 2018-04-08 19:54:00 -04:00
Adrien Béraud b3c637536f proxy client: prevent use-after-free after destruction 2018-04-08 19:54:00 -04:00
Adrien Béraud 1436af0321 value cache: prevent callback copy on move 2018-04-08 19:54:00 -04:00
Adrien Béraud 1debe012c1 proxy client: restart listeners on connectivity change 2018-04-08 19:54:00 -04:00
Adrien Béraud 368a842d2e proxy client: don't block resolving address 2018-04-08 19:53:59 -04:00
Adrien Béraud d250e9b630 proxy client: avoid sending listen with push notifications 2018-04-08 19:53:59 -04:00
Adrien Béraud 3ff6863287 proxy client: add logs 2018-04-08 19:53:59 -04:00
Sébastien Blin 96621ea332 Merge pull request #271 from savoirfairelinux/proxy_client_use_after_free
proxy client: retrieve search from callback
2018-04-06 13:13:07 -04:00
Adrien Béraud 567fa1c703 proxy client: retrieve search from callback 2018-04-06 11:43:51 -04:00
Adrien Béraud 20ab71aba6 securedht: check public key 2018-04-05 14:23:15 -04:00
Adrien Béraud 1acace1b91 proxy client: add missing mutex, cleanup 2018-04-05 02:35:01 -04:00
Adrien Béraud 2f423fec48 crypto: check public key for null before pack or print 2018-04-05 02:33:58 -04:00
Adrien Béraud 7be550bf94 value cache: use single callback 2018-04-05 02:08:58 -04:00
Adrien Béraud a8c0340bf1 Merge pull request #269 from AmarOk1412/removeCallbackId
proxy: remove useless callback_id
2018-04-03 12:26:52 -04:00
Sébastien Blin 5b71af3cec proxy: remove useless callback_id
callback_id was used for token problems which are not present anymore.
Now token is sufficient and we can remove callback_id.
2018-04-03 10:43:56 -04:00
Adrien Béraud fcf7111872 scheduler: avoid possible overflow with buggy stdlib 2018-03-29 11:58:26 -04:00
Adrien Béraud 38ca7b851b Merge pull request #267 from AmarOk1412/cpuusage
scheduler: avoid overflow causing 100% cpu usage
2018-03-29 11:42:13 -04:00
Sébastien Blin 62bbce76f2 scheduler: avoid overflow causing 100% cpu usage 2018-03-29 11:40:04 -04:00
Adrien Béraud d9f6731de2 Merge pull request #265 from AmarOk1412/fixSplit
proxy_client: fix address split
2018-03-29 11:10:32 -04:00
Sébastien Blin 393a403ff2 proxy_client: fix address split 2018-03-29 11:00:33 -04:00
Adrien Béraud 62e4655d4f Merge pull request #264 from AmarOk1412/fixPublicAddr
dht_proxy_client: fix getPublicAdresss parsing
2018-03-28 16:44:34 -04:00
Sébastien Blin 60d43319e2 dht_proxy_client: fix getPublicAdresss
Retrieve all public ips (Ipv6 + v4). Has to resolve all proxy
address (so two get requests to get all ips)
2018-03-28 15:59:04 -04:00
Sébastien Blin 7d3c613347 Merge pull request #263 from savoirfairelinux/value_cache
Cache: improve value expiration handling
2018-03-28 10:11:12 -04:00
Adrien Béraud d2df93c75e network engine: send nodes in listen confirmation 2018-03-28 09:54:04 -04:00
Adrien Béraud 0edee443f5 cache: improve value expiration handling 2018-03-28 09:54:04 -04:00
Sébastien Blin 8c85f84b8a Merge pull request #261 from savoirfairelinux/dhtrunner_unit_test
tests: add initial unit test for DhtRunner
2018-03-21 11:38:05 -04:00
Adrien Béraud cea0d4f62e tests: add initial unit test for DhtRunner 2018-03-21 11:22:21 -04:00
Adrien Béraud 203150851f OpCache: keep cache alive during callback processing 2018-03-19 20:11:12 -04:00
Adrien Béraud 9a5ef25179 update to version 1.7.0rc1 2018-03-17 23:12:38 -04:00
Adrien Béraud a5137e8ac4 tests: fix build with autotools 2018-03-17 14:47:23 -04:00
Adrien Béraud c129a24492 travis: use 5 build configurations
Merge all push configurations to reduce build time
as Travis provides 5 free simultaneous builds.
The 'all' configuration is renamed 'push' to reflect the change
2018-03-17 14:40:50 -04:00
Adrien Béraud 8237f32bd5 travis: update Dockerfiles, change base OS to Ubuntu 16.04 2018-03-17 14:32:09 -04:00
Sébastien Blin 546e63edaf Merge pull request #258 from savoirfairelinux/value_cache
Add a value cache for each nodes. This cache avoids network packets by grouping LISTEN operations on the same hash.
2018-03-16 13:55:24 -04:00
Adrien Béraud 647de16f1c proxy client: implement getLocal(), getLocalById() 2018-03-16 13:34:41 -04:00
Adrien Béraud 2f4acd26d6 dhtinterface: add listen() callback to signal expired values 2018-03-16 13:34:41 -04:00
Adrien Béraud 48bb804792 proxy client: add cache for values and operations 2018-03-16 13:34:40 -04:00
Adrien Béraud 4261bd2c85 dhtinterface: remove resubscribe 2018-03-16 13:34:32 -04:00
Adrien Béraud 12db1f88dc dht: introduce cache for values and operations
Multiplex multiple listen operations on a single key through
a unique listen operation on the network.
2018-03-16 13:34:32 -04:00
Adrien Béraud 1617c79e5d network: add signaling for expired, refreshed values 2018-03-14 23:39:35 -04:00
Adrien Béraud 80b944d943 dhtnode: prevent crash in cancelListen 2018-03-14 23:39:35 -04:00
Adrien Béraud 74bfced9b9 Merge pull request #255 from AmarOk1412/tests
tests: add unit tests structure to opendht
2018-03-14 23:00:30 -04:00
Sébastien Blin 1c10872ea2 tests: add unit tests structure to opendht
+ Unit testing requires cppunit.
+ add options for CMake and Autotools to build opendht_unit_tests.
+ add sample tests for InfoHash
+ modify Dockerfiles and Travis build to run `make test`
+ Change lowbit signature to return an int instead of an unsigned.
2018-03-14 15:26:47 -04:00
Adrien Béraud 2b2e8c2a72 Merge pull request #260 from AmarOk1412/fixConnectivityStatus
proxy_client: avoid to call getConnectivityStatus() when destroying
2018-03-14 15:22:20 -04:00
Sébastien Blin 2315dc089a proxy_client: avoid to call getConnectivityStatus() when destroying
Because getConnectivityStatus is called each time an operation fails,
when destroying the proxy_client, we stop all operations so it fails.
2018-03-14 11:33:01 -04:00
Adrien Béraud d7c0e9af38 update to version 1.6.1 2018-03-06 17:30:07 -05:00
Adrien Béraud 460cf858d3 argon2: bump submodule to latest release 2018-03-06 17:24:09 -05:00
Adrien Béraud c81da2dd7d indexation: enable by default 2018-03-06 10:29:01 -05:00
Adrien Béraud b02f8e98c4 filter: add Value vector filter 2018-03-06 10:29:01 -05:00
Adrien Béraud ca9a367803 value: add TypeStore 2018-03-06 10:29:01 -05:00
Adrien Béraud 09f080220f Merge pull request #252 from AmarOk1412/fixDuplication
dht_proxy_client: fix getCallback for push notifications
2018-03-06 10:24:29 -05:00
Sébastien Blin 547fa2eff5 dht_proxy_client: fix getCallback for push notifications
Note: Also fix Value deserialization
2018-03-05 19:15:04 -05:00
Adrien Béraud 2a8f21d4aa Merge pull request #251 from AmarOk1412/fixcancelListen
proxyclient: avoid useless opFailed when correctly cancel a listen
2018-03-01 16:28:18 -05:00
Sébastien Blin 6f4283b7d5 proxyclient: avoid useless opFailed when correctly cancel a listen 2018-03-01 16:11:49 -05:00
Adrien Béraud babceb902a readme: fix typo 2018-02-28 21:53:52 -05:00
Adrien Béraud 26bd4e7141 readme: update 2018-02-28 21:37:29 -05:00
Sébastien Blin 1531e13ca4 build: make indexation optional 2018-02-28 08:17:09 -06:00
Adrien Béraud c9cbced0c8 build: make indexation optional 2018-02-27 21:48:49 -05:00
Adrien Béraud 2cf2112aec dhtnode: simplify macros 2018-02-27 21:33:48 -05:00
Adrien Béraud 012f6ed2f6 Merge pull request #247 from AmarOk1412/fixCancelListen
proxyserver: fix cancelListen and reduce push notifications number
2018-02-26 17:19:32 -05:00
Sébastien Blin fcac10c4c8 proxyserver: fix cancelListen and reduce push notifications number 2018-02-26 17:01:23 -05:00
Adrien Béraud f2b692c716 Merge pull request #245 from AmarOk1412/fixCancelListen
dhtproxy: fix cancelListen with pushNotifications
2018-02-26 15:37:00 -05:00
Sébastien Blin 22ef53acef dhtproxy: fix cancelListen with pushNotifications
Fill the body of the UNSUBSCRIBE method and fix dhtnode application
2018-02-26 15:25:48 -05:00
Adrien Béraud 2af70e6d50 Merge pull request #243 from AmarOk1412/fixPushBuild
pushnotifications: fix build without push notifications, improve travis script
2018-02-26 14:21:34 -05:00
Sébastien Blin 63c9c607bd pushnotifications: fix build without push notifications, improve travis script 2018-02-26 13:27:06 -05:00
Adrien Béraud cab0813b17 dht: reduce log verbosity 2018-02-24 15:15:49 -05:00
Adrien Béraud 06cc490ee4 listener: remove unused field 2018-02-24 15:05:14 -05:00
Adrien Béraud 6821988ddf node: use thread local random device 2018-02-24 14:30:40 -05:00
Adrien Béraud 8cce9fcb85 search: remove getNextStepTime 2018-02-23 13:50:25 -05:00
Adrien Béraud 56caae019c proxy server: add push notification ttl 2018-02-19 02:10:56 +01:00
Adrien Béraud f5afcbf62b proxy server: use high priority notifications
Normal priority notifications may be delayed.
2018-02-16 01:54:44 +01:00
Adrien Béraud 0957d30e86 y2038 bug: don't allow time wrap for certificate validity 2018-02-10 23:21:31 +01:00
Adrien Béraud 3a632b1544 proxy server: add logs 2018-02-10 14:31:23 +01:00
Adrien Béraud 2c0f4a897c dhtnode: fix cancelListen 2018-02-10 14:31:00 +01:00
Adrien Béraud be6a5671ed y2038 bug: change certificate duration to 10 years
A certificate duration of 20 years was making certificate expire
after 2038 which is not supported on many 32 bits platforms.
Reduce to 10 years, which gives another decade to deprecate 32-bits platforms.
2018-02-09 01:40:03 +01:00
Adrien Béraud 61ac297b1b crypto: add method to read Certificate activation date 2018-02-09 00:42:25 +01:00
Adrien Béraud da867dd07c Merge pull request #239 from kiddouk/fix/dhtnode-identity
Generates RSA pairs for dhtnode instead of EC cert
2018-02-08 13:05:46 +01:00
Sébastien Requiem 962249ec75 Generates RSA pairs for dhtnode instead of EC cert
* dhtnode was generating twice an EC cert which rendered encryption
impossible since opendht lib is expecting an RSA public key to encrypt
the data for the destination.

* fix savoirfairelinux/opendht#235
2018-02-08 10:56:17 +01:00
Adrien Béraud c03ba57895 dhtnode: use explicit unique_ptr constructor 2018-02-07 17:40:59 +01:00
Adrien Béraud e2224fac5a Merge pull request #209 from dctremblay/readme-update-gcc-version
README : update GCC required version from 4.8 to 5.2
2018-02-01 00:52:39 +01:00
Adrien Béraud 48aaaf1e5d Merge branch 'master' into readme-update-gcc-version 2018-02-01 00:51:41 +01:00
Adrien Béraud 80ee256712 update to version 1.6.0rc1
* added REST proxy client implementing the DHT API
* added optional support for push notifications through the proxy server,
  using the gorush REST API: https://github.com/appleboy/gorush#web-api
* DhtRunner: now able to use DhtProxyClient as a DHT node
* DhtRunner: can switch between local or proxy node during runtime
* SockAddr: added methods to handle IPv6-mapped IPv4 addresses
* iOS: handle SIGPIPE on UDP sockets by recreating sockets
* fixed occasional crash during packet processing
2018-01-31 18:57:54 +01:00
Adrien Béraud e274ffd83b headers: unify API across build options 2018-01-31 18:07:43 +01:00
Adrien Béraud bd9496e2ba crypto: fix build on GnuTLS 3.3 2018-01-26 15:10:07 -05:00
Adrien Béraud 4d4ba2be96 Merge pull request #234 from atraczyk/master
fix bad paths
2018-01-24 17:31:36 -05:00
atraczyk 680e30be9b fix bad paths 2018-01-24 17:30:21 -05:00
Adrien Béraud 233301c3f3 dhtrunner: use proxy by default if configured 2018-01-23 12:19:38 -05:00
Adrien Béraud 0db21772c1 Merge pull request #232 from atraczyk/sigpipe
dhtrunner: pass SockAddrs by value to startNetwork
2018-01-23 11:34:14 -05:00
Adrien Béraud e6a2d96622 net: restart socket in case of sigpipe 2018-01-23 11:34:14 -05:00
atraczyk e5d83d47be dhtrunner: don't pass SockAddrs by reference to startNetwork 2018-01-23 11:34:14 -05:00
Adrien Béraud 3d77c76a4d dhtrunner: restart listeners only if one exists 2018-01-23 11:31:12 -05:00
Adrien Béraud 043d5a7c7c dhtrunner: check dht instance in setLocalCertificateStore 2018-01-19 14:05:21 -05:00
Adrien Béraud 636eb1972d proxy client: improve robustness, switch behavior 2018-01-18 16:36:13 -05:00
Adrien Béraud 27a250d2c0 proxyclient: fall to disconnected in case of connectivity failure 2018-01-17 12:09:39 -05:00
Adrien Béraud 02f4c81f2a dhtrunner: improve proxy listen handling 2018-01-17 11:40:18 -05:00
Adrien Béraud 0420ebcce3 dhtinterface: pass listen filters by value 2018-01-17 11:40:18 -05:00
Adrien Béraud 15e3696b88 proxy client: fix build when push notifications are disabled 2018-01-13 16:16:19 -05:00
Adrien Béraud ca693a6ac1 pushNotificationReceived: take a map<string, string>
JSON is used for the DHT proxy protocol and to communicate with gorush.
Push notifications services might use any format, not necessarily JSON.
Push values are received as a map<string, string>, so receive them in
that format.
2018-01-12 13:20:07 -05:00
Adrien Béraud 1d6a307b6b proxy server: send data push message instead of notification 2018-01-11 17:01:10 -05:00
Adrien Béraud 227cca883c dhtrunner: start proxy ASAP, use local dht for node stats/import/export 2018-01-11 14:24:59 -05:00
Adrien Béraud ef82a7ecba proxy client: make proxy status check asynchronous 2018-01-11 14:24:59 -05:00
Adrien Béraud 6e9f2cda79 SockAddr: add isMappedIPv4, getMappedIPv4 2018-01-11 13:29:18 -05:00
Adrien Béraud 10b58c5ce7 SockAddr: add constructor from simple sockaddr* 2018-01-11 13:29:18 -05:00
Adrien Béraud ab731cd7d0 Merge pull request #228 from AmarOk1412/push_notifications_client
Add support for push notifications
2018-01-11 13:14:43 -05:00
Adrien Béraud a0d8f4734a dhtproxy: allow token refresh, set clientID (#6)
* add method to set the push token independently from other configuration,
  since the push token can be updated during runtime.
* allow to provide a "clientID" to be sent in push notifications,
  used to demultiplex push notifications to multiple OpenDHT nodes running
  on the same host. For instance Ring uses the accountID as the clientID
  to know which account received the push notification.
* use {"platform":"android"/"ios"} to communicate the platform instead of {"isAndroid":true/false}.
2018-01-10 16:32:57 -05:00
Adrien Béraud 237859d8c3 Merge branch 'master' into push_notifications_client 2017-12-20 17:51:01 +01:00
Adrien Béraud 24dec0682f Merge pull request #231 from AmarOk1412/fixLog
dht_interface: fix logger issues
2017-12-19 02:11:25 +01:00
AmarOk 4b46f6a821 dht_interface: fix logger issues
Make DHT_LOG static to use it in the whole library
2017-12-15 12:45:10 -06:00
Sébastien Blin 37a9a3d9da dhtproxy: inject push notifications in opendht
+ add the ability to inject push notifications in opendht to call
correct callbacks
+ if a timeout occurs and no cancelListen was called, relaunch the
listen operation
+ Pass devicekey to enable push notifications for DhtProxyClient
+ Update sockaddr to fix the build on all platforms

Note: update dhtnode
2017-12-12 15:03:02 -06:00
Sébastien Blin 75cca66d7e dhtproxy: support push notifications for mobile clients
+ Add SUBSCRIBE and UNSUBSCRIBE for DhtProxyServer
+ Add the ability to stop Listen via a timeout (and send a push
Notification for the client)
+ Add the ability to use gorush to send push notifications

Note: Update dhtnode
2017-12-12 10:24:54 -06:00
Adrien Béraud 762a1c7ad2 Merge pull request #220 from AmarOk1412/dhtproxyclient_merge
proxy: implement DhtProxyClient
2017-12-12 13:38:23 +01:00
AmarOk d19ba2cb41 proxyserver: add lock_guard to avoid to manually unlock 2017-12-06 14:43:28 -06:00
AmarOk 557323deff refactor: use new jsoncpp API
Use the latest jsoncpp API to remove depreciation warning.
2017-12-06 08:49:24 -06:00
AmarOk 29ffbf6aa7 dhtrunner: remove DhtRunner::getAddrInfo
Was replaced by SockAddr::resolve
2017-12-05 10:02:38 -06:00
Adrien Béraud aaa577d9e3 proxy_client: use atomic bool for shared state flags (#3) 2017-12-05 09:50:38 -06:00
Sébastien Blin 333c44dbd3 proxy_client: don't block for callback 2017-12-05 09:05:35 -06:00
Adrien Béraud 8243bc4c3f proxy_client: don't block for callback
Use shared flags to avoid blocking for the callback
while respecting the callback return value.
2017-12-05 15:51:39 +01:00
AmarOk b1a9742889 dhtproxyclient: add lock_guards for mutex and clean code 2017-12-04 09:42:37 -06:00
Adrien Béraud d2f91af946 node: use shared_ptr to manage Sockets 2017-12-02 16:03:27 +01:00
Sébastien Blin 5adc5b4c94 README: update Restbed dependency informations 2017-12-01 14:28:32 -05:00
Adrien Béraud f9d48cd15a Merge pull request #227 from atraczyk/master
Build: add new files to VS project and adjust filters
2017-11-30 00:17:29 +01:00
Sébastien Blin e7d8bc4275 proxyclient: erase finished operation threads 2017-11-29 14:44:02 -05:00
atraczyk 507326cebc Build: add new files to VS project and adjust filters 2017-11-29 13:46:07 -05:00
Adrien Béraud b24832e0e1 Merge pull request #226 from atraczyk/master
InfoHash: fix stream operator<< declaration
2017-11-29 17:14:03 +01:00
atraczyk 6cdcd183b4 InfoHash: fix stream operator<< declaration 2017-11-29 11:08:39 -05:00
Sébastien Blin eb750f5b7f proxy_client: execute callbacks in main thread 2017-11-27 17:51:33 -05:00
Sébastien Blin 5967c89c23 proxy: don't reinit dhtproxy multiple times and forward encrypted messages
+ Having a null dht_proxy_client can lead to using nullptr.
+ securedht should forward messages if we are using a proxy.
+ Protect callback segfault
2017-11-22 16:09:45 -05:00
Sébastien Blin 4a83b36dcf tools: add the ability to use a proxy for dhtchat 2017-11-21 13:37:18 -05:00
Sébastien Blin eb1f9d64e1 dhtproxyclient: add listen ability.
+ Fix LISTEN endpoint for DhtProxyServer
= DhtProxyServer use multiple worker threads
+ Add listen/cancelListen for DhtProxyClient
+ Add connectivityChanged.
2017-11-20 16:01:44 -05:00
Sébastien Blin cb72c104fd proxy: implement basic DhtProxyClient with the ability to get and put.
+ Add an abstract class to describe the Dht
+ Now, we can modify the Dht linked to a SecureDht. So we can choose
between the classic Dht and the Dht using a proxy.
+ Implement a basic client which can Get and Put values on the Dht using
the proxy.

Note: Update dhtnode to have the ability to use the DhtProxyClient.
Todo: Implement Listen, ping, connectivityChanged for the client.
2017-11-20 15:45:29 -05:00
Adrien Béraud 5fde50be4a dhtrunner: use const char* for setopt value
fix build on Win32
2017-11-17 19:34:31 +01:00
Adrien Béraud 1c16e6f38d update to version 1.5.0
* added REST server implementing OpenDHT proxy API
* tools: added simple Web client using the proxy server
* tools: allow dhtnode to run a proxy server
* tools: allow dhtnode to use any string as key
* InfoHash: added operator bool()
* minor performance improvement
* SockAddr: fix endianness issue
* net: fix incorrect reported address parsing
* minor memory leak fixes
2017-11-17 18:51:45 +01:00
Adrien Béraud 6790d1ec5c SockAddr: set service to null if string is empty 2017-11-17 18:31:28 +01:00
Adrien Béraud 4dc1847978 autotools: fix build without proxy server 2017-11-17 16:42:04 +01:00
Adrien Béraud 3a61692618 net: set MSG_NOSIGNAL if possible 2017-11-17 02:20:31 +01:00
Adrien Béraud 6f9afac0a5 dhtrunner: cleanup 2017-11-17 02:12:03 +01:00
Adrien Béraud b17c7c2965 dht: reserve address vector size 2017-11-17 02:06:32 +01:00
Adrien Béraud 6d238836ad dht: return empty search on error 2017-11-17 01:01:47 +01:00
Adrien Béraud 5115fab9e6 dht: increase max searches limit 2017-11-16 16:49:59 +01:00
Adrien Béraud 93498ecf0b tools: JS node: cleanup 2017-11-14 21:55:03 +01:00
Adrien Béraud 72d790953a tools: JS node: allow to set the proxy address 2017-11-14 20:58:18 +01:00
Adrien Béraud 72b556a09b tools: JS node: cleanup 2017-11-14 19:38:55 +01:00
Adrien Béraud 747f86f8f4 dhtrunner: use SockAddr::resolve 2017-11-10 17:59:05 -05:00
Adrien Béraud 161769f4ec SockAddr: use host endianess for bitwise-shift operations 2017-11-10 17:48:36 -05:00
Adrien Béraud 9948079c97 SockAddr: add resolve() 2017-11-10 17:48:36 -05:00
Adrien Béraud 607e5eeccf tools: use https url 2017-11-10 17:29:24 -05:00
Adrien Béraud 111ac57b6f tools: JS node: add listen support 2017-11-09 12:23:30 -05:00
Adrien Béraud 153641dde5 tools: add JavaScript proxy node 2017-11-08 15:20:06 -05:00
Adrien Béraud 113bebabd4 DhtRunner: remove log 2017-11-08 15:14:01 -05:00
Adrien Béraud b549055034 DhtRunner: use SockAddr 2017-11-08 15:12:43 -05:00
Adrien Béraud 7d7410b472 dhtnode: allow to use arbitrary string as key
Key will be h(key).
2017-11-08 15:12:43 -05:00
Adrien Béraud d7aaa4ae56 proxy server: add Access-Control-Allow-Origin 2017-11-08 15:12:43 -05:00
Adrien Béraud 5a049f89f3 cmake: find Jsoncpp using pkgconfig 2017-11-08 15:12:43 -05:00
Sébastien Blin 65e88f2fa6 build: toInfoHash->to 2017-11-08 15:07:04 -05:00
Adrien Béraud 4430b1e616 Merge pull request #217 from AmarOk1412/dhtproxy
Communicate with OpenDHT through a REST API
2017-11-08 14:35:31 -05:00
Sébastien Blin e2c534df5a add std::bind, fix put, avoid overflow on base64 2017-11-08 14:33:07 -05:00
Sébastien Blin 2ca2835c9b add options method handler 2017-11-08 12:14:44 -05:00
Sébastien Blin bbe922dd7d remove headers, fix HTTP status, fix get / 2017-11-07 16:08:55 -05:00
Sébastien Blin 38ad5b9ef2 add --proxyserver option for dhtnode 2017-11-06 16:49:46 -05:00
Sébastien Blin 67ba435ba6 base64: take the old implementation from ring-daemon 2017-11-06 16:24:00 -05:00
Sébastien Blin 6413571301 clean code 2017-11-06 12:53:35 -05:00
Adrien Beraud 0dccae68e6 InfoHash: make false in case of parsing error 2017-11-03 16:03:11 -04:00
Adrien Beraud 92320cef59 InfoHash: throw in case of invalid input string 2017-11-03 14:03:34 -04:00
Adrien Beraud bf4e838e20 InfoHash: return stream in operator>> 2017-11-03 14:00:49 -04:00
Adrien Beraud 88b4233bda python: update InfoHash bool operator 2017-11-03 14:00:49 -04:00
Adrien Beraud e9eb97ea9a InfoHash: improve hex parsing performance 2017-11-02 17:42:45 -04:00
Adrien Beraud 0e865976f9 InfoHash: unify with Hash<N> 2017-11-02 14:28:09 -04:00
Adrien Beraud 87dc080bbf crypto: add raw hash function 2017-11-02 14:25:46 -04:00
Sébastien Blin 9abc88f378 add --enable-proxy-server option for autotools 2017-11-01 17:11:14 -04:00
Adrien Beraud 834d62e6e9 InfoHash: use bool operator where relevent 2017-11-01 16:28:17 -04:00
Sébastien Blin 61a148e83f update README.md 2017-11-01 14:52:29 -04:00
Sébastien Blin 8e43775394 update dhtnode + clean code 2017-11-01 14:52:29 -04:00
Sébastien Blin 8344138bc8 add optional + clean start/stop 2017-11-01 14:52:29 -04:00
Sébastien Blin dc66b3847a make code for DHT Proxy Server optionnal 2017-11-01 14:52:29 -04:00
Sébastien Blin d608da4307 cmake: add optionnal dependencies for proxy 2017-11-01 14:52:29 -04:00
Sébastien Blin 7ddd6629e3 add getFiltered 2017-11-01 14:52:29 -04:00
Sébastien Blin 20abc3e495 add LISTEN endpoint 2017-11-01 14:52:29 -04:00
Sébastien Blin c4ba8670e4 add Putxxx value endpoints 2017-11-01 14:52:29 -04:00
Sébastien Blin a3348c85d6 value to JSON and begin to clean endpoints 2017-11-01 14:52:29 -04:00
Sébastien Blin ca465d7159 set timeout to a high value + add jsoncpp 2017-11-01 14:52:29 -04:00
Sébastien Blin 1413d32ee6 add listen endpoint 2017-11-01 14:52:29 -04:00
Sébastien Blin 58fdfa9452 add get hash endpoint 2017-11-01 14:51:36 -04:00
Sébastien Blin 6f641073ae proxy put and putEncrypted 2017-11-01 14:51:36 -04:00
Sébastien Blin 32153b11ab proxy putSigned 2017-11-01 14:51:36 -04:00
Sébastien Blin e33ac02351 test restbed 2017-11-01 14:51:36 -04:00
Adrien Beraud dc99919338 InfoHash: add explicit operator bool() 2017-11-01 11:59:11 -04:00
Adrien Béraud fcaaa01b2d network engine: add "value update" message type 2017-10-30 13:12:16 -04:00
Adrien Béraud 8cd3ff9fc4 network engine: remove unused constant 2017-10-30 13:12:16 -04:00
Adrien Béraud 0a130c7045 dht: update permanent state on announce 2017-10-30 13:12:16 -04:00
Adrien Béraud eb9f314356 dhtnode: allow to perform and cancel persistent put 2017-10-30 13:12:16 -04:00
Adrien Béraud a401aea132 dht: simplify searchSendAnnounceValue 2017-10-30 13:12:16 -04:00
Adrien Béraud 41ebbe21d4 node cache: expire nodes on destructions
Expiring nodes on cache destruction allow to cancel
any remaining request before the dht instance is destructed,
since Node instances might remain alive after the dht instance
is destroyed.
2017-10-30 13:12:16 -04:00
Adrien Béraud 6378840d33 dhtnode: allow to cancel a listen operation 2017-10-30 13:12:16 -04:00
Adrien Béraud 64f0aa1532 parsed message: don't override the reported address family 2017-10-30 13:12:16 -04:00
Adrien Béraud 63366722a9 dht: reduce verbosity of storage log 2017-10-21 18:01:32 +02:00
Adrien Béraud cd17858ae1 dht: periodic cleanup of unused quota entries 2017-10-21 18:00:46 +02:00
Adrien Béraud f4ebbc6651 update to version 1.4.1
* updated MSVC project
* bug fixes
2017-10-21 01:30:12 +02:00
Adrien Béraud 464339822b Merge pull request #215 from AmarOk1412/typoPeriod
rate_limiter: typo fix, 'Perdiod'->'Period'
2017-10-20 23:56:02 +02:00
Sébastien Blin fe09146609 rate_limiter: typo fix, 'Perdiod'->'Period' 2017-10-20 14:51:35 -04:00
Adrien Béraud a789ffe7ae dht: prevent use-after-free of socket callback 2017-10-20 17:46:27 +02:00
Adrien Béraud 476fbb1160 network: use full 32-bits of transaction IDs
We used to use the first 16 bits for the message type.
2017-10-20 17:42:28 +02:00
Adrien Béraud 4501217c21 Merge pull request #214 from atraczyk/master
remove vs2015 based constexpr error, update vs project files
2017-10-19 01:19:43 +02:00
atraczyk 207675a181 remove vs2015 based constexpr error, update vs project files 2017-10-18 17:50:19 -04:00
Adrien Béraud cf6447dc80 NetworkEngine: use proper type for constant 2017-10-17 19:22:15 +02:00
Adrien Béraud 775eb2e599 update to version 1.4.0
* improved Doxygen documentation
* cmake: add support to build documentation
* cmake: improve build on macOS
* API change: storage policies, getPublicAddress now use SockAddr
* NodeExport: added msgpack serialization
* fixed issue that could cause occasional request failures
* minor bug fixes
* minor performance improvements
2017-10-17 18:37:08 +02:00
Adrien Béraud 376486e64f node: use full range of socket IDs 2017-10-17 15:25:09 +02:00
Adrien Béraud 63013bf374 SearchNode: prevent copy, check request access 2017-10-17 03:17:52 +02:00
Adrien Béraud 488aa771a9 Node: don't expire existing requests 2017-10-16 17:12:33 +02:00
Adrien Béraud 6bc2f19a36 dht: log total number of nodes in onGetValuesDone 2017-10-16 17:12:33 +02:00
Adrien Beraud 2dd94fbfe8 cmake: use CMAKE_THREAD_LIBS_INIT as library 2017-10-16 01:26:40 +02:00
Adrien Béraud be2b9fd7dc NodeCache: handle end() lower_bound for non-empty map 2017-10-15 15:57:14 +02:00
Adrien Béraud 9d4e6e0984 rate limiter: use deterministic maintenance
Using deterministic maintenance sets an upper bound
to the size of the address map.
2017-10-15 01:18:32 +02:00
Adrien Beraud 4856a6b424 PublicKey: getId compatible with HASH_LEN = 32 2017-10-13 15:43:56 +02:00
Adrien Béraud 7df375fc75 NodeCache: fix invalid pointer access 2017-10-13 15:40:09 +02:00
Adrien Béraud 63e0c1266a dht: use OpStatus in put
Factorize shared pointers.
2017-10-13 02:07:14 +02:00
Adrien Béraud 1a54aff7bc storage policies: use SockAddr
API-breaking change to use const SockAddr& instead of sockaddr*.
2017-10-13 01:10:09 +02:00
Adrien Béraud f2b9f8eeda dht: move bucket time update to routing table 2017-10-13 01:10:09 +02:00
Adrien Béraud e9f007025f node: make most fields private 2017-10-13 01:10:09 +02:00
Adrien Béraud 6ce1531e1f node: make id const 2017-10-12 15:44:34 +02:00
Adrien Béraud 84a45c4f91 dht: factorize shared pointer dereference 2017-10-12 15:44:14 +02:00
Adrien Béraud e20ae56cab dht: support client mode
In client mode, a node won't store data
and won't participate in routing.
2017-10-12 15:44:14 +02:00
Adrien Béraud 4ce0168916 network engine: move ParsedMessage to separate file 2017-10-11 23:51:44 +02:00
Adrien Béraud 024dd42e5a dht: remove processMessage 2017-10-11 17:36:20 +02:00
Adrien Béraud 98ec789526 nertwork engine: move tid management to Node 2017-10-11 17:36:20 +02:00
Adrien Béraud 3bb5e7ee12 network engine: move transaction ownership to Node 2017-10-11 17:36:20 +02:00
Adrien Béraud 8c529b7d7f request: add getTid(), getSocket() 2017-10-11 13:47:53 +02:00
Adrien Béraud be7494961c network engine: move socket management to Node 2017-10-11 02:23:56 +02:00
Adrien Béraud bdb0bef0ee network engine: move RequestAnswer out of class 2017-10-11 02:22:03 +02:00
Adrien Béraud 73f26e120d doc: improve documentation 2017-10-10 18:16:33 +02:00
Adrien Béraud 9f4b16e4f5 cmake: add doxygen documentation support
Automatically build documentation if doxygen is found.
2017-10-10 17:45:34 +02:00
Adrien Béraud 323ad774e5 value: restore stream state after change 2017-10-09 15:14:20 +02:00
Adrien Béraud d0bcd39341 IpServiceAnnouncement: use SockAddr 2017-10-09 15:06:34 +02:00
Adrien Béraud 42125367d7 SockAddr: add documentation 2017-10-09 14:46:35 +02:00
Adrien Béraud d87a4ef28c InfoHash: add operator== 2017-10-07 11:35:56 +02:00
Adrien Béraud a3f4388556 InfoHash: increase toFloat precision 2017-10-07 11:35:56 +02:00
Adrien Béraud 97ee4b6fea dht: move onNewNode to RoutingTable 2017-10-07 11:35:56 +02:00
Adrien Béraud 0abd288958 SockAddr: factorize setters 2017-10-05 14:09:56 +02:00
Adrien Béraud 131073e211 SockAddr: cleanup 2017-09-27 11:36:42 +02:00
Adrien Béraud 078c4f064a cmake: use Threads package 2017-09-26 16:42:33 +02:00
Adrien Béraud f17a4e66f5 cmake: add flag to enable address sanitizer and stack protector 2017-09-26 16:35:38 +02:00
Adrien Béraud dd13ebb6d1 cmake: use private linking for private dependencies
Users of the OpenDHT shared library don't need to link
against GnuTLS or Nettle.
2017-09-26 16:34:18 +02:00
Adrien Béraud 1c45f34262 SockAddr: use pointer to sockaddr
Save memory and reduce copies by using a pointer
to a sockaddr structure of the right size instead of
using a full sockaddr_storage structure for every address.
2017-09-26 16:30:29 +02:00
Adrien Beraud a82f575232 NodeExport: add ostream operator 2017-08-30 10:48:49 +02:00
Adrien Beraud 1d84b34cf6 value: avoid checking failbit directly
failbit is implementation defined, use the bool operator instead.
2017-08-30 10:46:30 +02:00
Adrien Beraud bedb51bf52 crypto: add EC curve identity generation 2017-08-28 12:03:15 -04:00
Adrien Béraud 1b9e9452c4 NodeExport: add msgpack serialization 2017-08-28 12:02:09 -04:00
Adrien Beraud 3bdaf2e20b update to version 1.3.6
Bugfix release.
2017-08-11 14:54:31 -04:00
Adrien Beraud a1d67b881b python: fix invalid pointer access 2017-08-11 12:44:40 -04:00
Adrien Beraud c40750f6e4 dht: use proper value type to compute expiration 2017-08-10 15:00:34 -04:00
David Côté-Tremblay f69d6426bd README : GCC required version from 4.8 to 5.4 2017-08-10 11:52:46 -04:00
Adrien Béraud 63b40d3e3a cmake: check library paths 2017-07-22 11:25:40 -04:00
Adrien Béraud 21f5918af8 cmake: use version 3.1, cleanup 2017-07-22 10:59:36 -04:00
Adrien Beraud 6989236985 update to version 1.3.5
Bugfix release.
2017-07-20 00:49:29 -04:00
Adrien Beraud 1efa120010 dhtcluster: allow to resize cluster 2017-07-20 00:47:47 -04:00
Adrien Béraud a99ca1cf05 Merge pull request #205 from atraczyk/master
add listener.h, search.h, and storage.h to VS project
2017-07-19 19:03:14 -04:00
atraczyk 8fc8209731 add listener.h, search.h, and storage.h to VS project 2017-07-19 18:39:49 -04:00
Adrien Beraud 6f3eafc5ee dht: set refill time even when no nodes where found 2017-07-16 23:30:58 -04:00
Adrien Beraud 83d1cb97c8 dht: cleanup sendCachedPing 2017-07-16 23:30:58 -04:00
Adrien Beraud 477799a2b9 dht: remove unused method 2017-07-16 23:30:58 -04:00
Adrien Beraud 7e8c9ce944 dht: use SockAddr& in makeToken 2017-07-16 23:30:58 -04:00
Adrien Beraud 6decb6609a dht: use uint64_t to store secret 2017-07-16 23:30:58 -04:00
Adrien Beraud f1e7cd897d dht: use crypto::hash 2017-07-16 18:11:06 -04:00
Adrien Beraud 9bfaa224bc dht: move set_nonblocking to NetworkEngine 2017-07-16 18:10:49 -04:00
Adrien Beraud 5657661249 dht: move Search out of the Dht class 2017-07-16 17:46:54 -04:00
Adrien Beraud e69d61d8c7 dht: move request to src 2017-07-16 17:45:24 -04:00
Adrien Beraud 729c055f5b scanner: fix reset and IPv6 print issue 2017-07-16 16:23:18 -04:00
Adrien Beraud 61f91d626b dht: move Storage, Listener out of the Dht class 2017-07-16 15:04:18 -04:00
Adrien Beraud 732d10713d dht: minor coverity fixes 2017-07-16 13:39:14 -04:00
Adrien Beraud 15e5fa433b network engine: handle EAFNOSUPPORT 2017-07-15 23:46:33 -04:00
Adrien Beraud 43ff0e9e52 network engine: handle EAGAIN, ENETUNREACH
Handle a few common error codes from send():
* EAGAIN: reschedule without increasing retry count.
  This prevent nodes from failing on slow/very slow connections.
* ENETUNREACH, EHOSTUNREACH: expire the node immediately instead
  of waiting for an answer, to expire IPv6 nodes quickly if no
  IPv6 network is available.
2017-07-15 23:36:33 -04:00
Adrien Beraud cf32e78f1b scanner: enable logging, use rbegin() instead of prev(end()) 2017-07-15 23:25:17 -04:00
Adrien Beraud f170726b4b scanner: make steps asynchronously from UI 2017-07-15 23:24:19 -04:00
Adrien Beraud ebb20bdf0c python: NodeSet: return insertion status 2017-07-15 14:17:51 -04:00
Adrien Beraud 2ca7302352 ice candidates: reduce lifetime to 1 minute 2017-07-13 09:58:03 -04:00
Adrien Beraud 8a123f9f68 network: prevent sending packets larger than 1280 bytes 2017-07-12 11:24:58 -04:00
Adrien Béraud 7e92eb6192 Merge pull request #202 from atraczyk/master
clean up vs2015 project files and add a build script
2017-07-11 11:41:10 -04:00
atraczyk 56edf1720c clean up vs2015 project files and add a build script 2017-07-11 10:51:50 -04:00
Adrien Beraud 7c32dc49b1 update to version 1.3.4
Bugfix release that also adds SystemD modules
2017-06-30 01:32:23 +02:00
Adrien Beraud 5cb5ab019f routing table: fix invalid iterator access
When calling findClosestNodes with an key referencing the first bucket,
the itp iterator could point to before-begin() and dereference it.
2017-06-29 13:07:31 +02:00
Adrien Beraud 42fa09a6fa dhtnode: graceful signal handling in service and daemon modes 2017-06-29 10:20:31 +02:00
Adrien Beraud 673884a409 dhtnode: add service mode
Service mode is similar to the daemon mode but:
* doesn't fork
* logs to stdout/stderr by default
  instead of syslog
2017-06-29 09:57:55 +02:00
Simon Désaulniers ec6296e44b http_server: enable WHERE filtering for GET method 2017-06-27 09:59:01 +02:00
Simon Désaulniers b96d0de8a2 python: make use of Filter, Where in DhtRunner.get 2017-06-27 09:59:01 +02:00
Simon Désaulniers 98c4e39ed1 python: expose queries to API 2017-06-26 17:56:44 -04:00
Simon Désaulniers 9c483880cb value: prevent queries redundant information 2017-06-22 18:39:25 -04:00
Simon Désaulniers ae7e298946 http_server: put values, specific user_type,vid 2017-06-22 18:39:18 -04:00
Simon Désaulniers 7197c1fbb6 python: expose user_type member of Value 2017-06-22 17:42:57 -04:00
Adrien Béraud c10e04d526 Merge pull request #195 from GrossoMoreira/patch-1
Avoid dereferencing an iterator to 'end()'
2017-06-20 14:21:29 +02:00
Pedro Moreira ee883492ee Avoid dereferencing an iterator to 'end()'
*h.end() only works on VS 2015 with
_SECURE_SCL=0
_ITERATOR_DEBUG_LEVEL=0

Also, if these flags are used when compiling opendht, it seems that any client program that wants to link against opendht also needs the same flags enabled, which is a terrible requirement to force on a client.

The proposed change makes the code a bit cleaner and doesn't require any preprocessor tricks.
2017-06-20 13:19:29 +02:00
Adrien Beraud 2ed99db9b1 pkg-config: add argon2 dependency when not using included version 2017-06-18 22:14:27 +02:00
Adrien Beraud c11dcf5d76 dhtcluster: add systemd module 2017-06-01 18:35:43 +02:00
Adrien Beraud 4132e990ec dhtcluster: log cleanup 2017-06-01 18:28:33 +02:00
Adrien Beraud 76eba8c235 dhtcluster: add service mode
The service mode is like the daemon mode
but doesn't fork.
2017-06-01 18:27:12 +02:00
Adrien Beraud e1ac26773b dhtcluster: install with tools 2017-06-01 17:20:29 +02:00
Adrien Beraud 339ea70230 python/cluster: rename to dhtcluster 2017-06-01 17:19:50 +02:00
Adrien Beraud 943a39178c python/cluster: add syslog support
Use syslog in daemonized mode
2017-06-01 15:57:34 +02:00
Adrien Beraud ae0cb58a5c python/cluster: remove unused methods 2017-06-01 15:56:18 +02:00
Adrien Beraud dd116d8ad8 python/cluster: add clean stop on signal 2017-06-01 15:53:41 +02:00
Adrien Beraud 74c3c5bc87 systemd service: use pkg-config to find proper install location 2017-05-30 13:47:30 +02:00
Adrien Beraud b6bfa14872 systemd service: bind on port 4222 by default 2017-05-30 13:22:58 +02:00
Adrien Beraud 50a769c8fb dhtnode: add systemd service
Install a systemd service when configured
with -DOPENDHT_SYSTEMD (CMake only).
2017-05-30 12:41:47 +02:00
Adrien Beraud 39a254ce9f log: add syslog support
Add support to log using standard syslog,
add related option in dhtnode.
dhtnode will use syslog by default
when starting in daemon mode and
no logfile is defined.
2017-05-30 12:20:09 +02:00
Adrien Beraud 3aa720fe1f python/cluster: bind on ::0 by default on IPv6 2017-05-23 17:59:05 +02:00
Adrien Beraud 7908a1d2ea update to version 1.3.3
Minor bugfix release
2017-05-13 17:51:28 -04:00
Adrien Beraud 37d8481e28 crypto: handle null certificate in getCopy(), getChain() 2017-05-13 17:18:00 -04:00
Adrien Beraud 44822f944b update to version 1.3.2
* crypto API improvements
* python bindings improvements
* implement first python unit tests
* minor bug fixes
2017-05-11 14:05:38 -04:00
Adrien Béraud 406a1c1152 Merge pull request #192 from atraczyk/master
MSVC: decouple argon2 dependency
2017-05-03 11:30:01 -04:00
atraczyk f9939ce336 decouple argon2 dependency 2017-05-03 11:26:45 -04:00
Adrien Beraud d9bced965b crypto: add TrustList move operator, prevent copy 2017-05-01 16:26:12 -04:00
Adrien Beraud 4d78aea05b unit tests: add crypto unit tests 2017-04-27 04:46:08 +02:00
Adrien Beraud 9b42afa9ca implement first simple unit tests 2017-04-27 04:45:59 +02:00
Adrien Beraud aa5b8b84a8 python: add TrustList wrapper 2017-04-27 04:45:59 +02:00
Adrien Beraud d0a8a92a56 crypto: add GnuTLS trust list wrapper 2017-04-27 04:45:59 +02:00
Adrien Beraud cf82f74e15 python: add PrivateKey::generateEC support 2017-04-27 04:45:59 +02:00
Adrien Beraud a952ddec53 python: add crypto encrypt/decrypt 2017-04-27 03:34:04 +02:00
Adrien Beraud fa7efd086f python: add Identity PrivateKey getter
Refactor Identity and PrivateKey to use
shared_ptr<PrivateKey> and retrieve the
key from Identity.
2017-04-27 03:34:04 +02:00
Adrien Beraud 8e28e86caf python: improve wrapper for crypto::Certificate
Add Certificate issuer, getName and revoke
2017-04-27 03:34:04 +02:00
Adrien Beraud 65de9622fb crypto: add Certificate::getChainWithRevocations 2017-04-26 16:43:06 +02:00
Adrien Beraud 210c4b2077 crypto: fix memory leak in RevocationList::getPacked() 2017-04-26 16:42:33 +02:00
Adrien Beraud e8cb635b3a crypto: add getChain() 2017-04-22 19:48:32 +02:00
Adrien Beraud f41c8fef99 crypto: unify API across GnuTLS versions
Throw an exception if GnuTLS is too old
instead of not providing the API.

Also consistently throw in case of hash error,
and return 0 for an empty hash, for both
PublicKey and Certificate.
2017-04-20 17:07:21 +02:00
Adrien Beraud 02147b0b16 update to version 1.3.1 2017-04-14 17:12:54 +02:00
Adrien Beraud 79e266aac6 crypto: don't build getLongID() with old gnutls 2017-04-14 16:57:58 +02:00
Adrien Beraud 9d75ed14b4 infohash: add to_c_str(), improve toString() performance 2017-04-10 15:48:04 +02:00
Adrien Beraud fcca618c48 infohash: improve getRandom performance
Generate random hash in 32 bits chunks
instead of 8 bits chunks.
2017-04-10 15:48:04 +02:00
Adrien Beraud 73bcebf355 license cleanup 2017-04-10 01:43:20 +02:00
Adrien Beraud 057443e4a0 python/tools: update pingpong 2017-04-10 01:12:31 +02:00
Adrien Beraud 99f8c2950b python: rename bootstrap(sockaddr) to ping 2017-04-10 01:12:00 +02:00
Adrien Beraud 4132c63faf def: fix typo 2017-04-09 17:22:18 +02:00
Adrien Béraud 7f2b5a44ff Merge pull request #186 from sim590/search-step-after-announce
dht: fix searchstep not scheduled after announcing
2017-04-05 20:12:23 +02:00
Adrien Beraud 7db0c15483 tools: catch exceptions 2017-04-05 18:35:19 +02:00
Adrien Beraud 2fc7cc57a9 default types: fix uninitialized fields 2017-04-05 18:15:34 +02:00
Adrien Beraud 4970a2aee5 infohash: throw exception with error message 2017-04-05 18:15:02 +02:00
Adrien Beraud 25b6df5355 removeExpiredNode: cleanup 2017-04-05 17:52:34 +02:00
Adrien Beraud 732479736b select: cleanup 2017-04-05 17:52:34 +02:00
Adrien Beraud 696ac1bbd5 network engine: print error if send fails
for now just print an error
2017-04-05 17:52:34 +02:00
Adrien Béraud 3b2e5a13bf Merge pull request #185 from savoirfairelinux/feature/pht
pht: prevent unneeded use of shared_ptr
2017-04-04 16:31:44 +02:00
Simon Désaulniers 26a7aec7cc dht: fix searchstep not scheduled after announcing 2017-04-03 17:39:15 -04:00
Adrien Beraud b73a50bace pht: prevent unneeded use of shared_ptr
Prefer a const reference instead of shared_ptr if the shared_ptr
is not used and argument type is not changed in the method.

This allows to prevent useless shared_ptr allocations.

In getRealPrefix, use OpState to track state instead of using many
different shared_ptr.
2017-04-03 19:10:49 +02:00
Adrien Beraud 70ccbe4e40 value: remove FieldSelectorDescription
FieldSelectorDescription is just Value::Field and
adds nothing on top of it.

Remove it in favor of Value::Field.
2017-04-03 19:10:01 +02:00
Adrien Beraud 6bb00ab732 Merge pull request #175 from sim590/argon2-submodule
argon2: use as submodule (reverted from commit c424eb9160) (reverted from commit 3c45e1996d)
2017-03-30 21:24:49 +02:00
Adrien Béraud 2e279852cd Merge pull request #178 from sim590/benchmark-ifname-error
benchmark: fix invalid ifname error
2017-03-30 17:06:03 +02:00
Adrien Béraud 09b4e71dc5 Merge pull request #182 from atraczyk/master
fixes the contrib paths for the Visual Studio build
2017-03-30 00:48:02 +02:00
atraczyk b40713596c ignore MSVC\contrib\build and add argon2 path to project 2017-03-29 18:25:10 -04:00
atraczyk c5485a795a Merge branch 'master' of github.com:atraczyk/opendht 2017-03-29 17:57:19 -04:00
atraczyk b7c5d4a550 clean up solution 2017-03-29 17:55:18 -04:00
Adrien Beraud 0aa1c9e42d argon2: try to fix build on MSVC 2017-03-29 18:27:19 +02:00
Adrien Beraud 5823e98c76 rng: add missing header 2017-03-29 03:07:09 +02:00
Adrien Beraud 3c45e1996d Merge pull request #175 from sim590/argon2-submodule
argon2: use as submodule (reverted from commit c424eb9160)
2017-03-29 02:51:06 +02:00
Adrien Beraud e2ce496779 crypto: add Certificate::getCopy() 2017-03-29 00:22:19 +02:00
Adrien Beraud 4540be7460 python: add more crypto bindings 2017-03-28 17:33:04 +02:00
Adrien Beraud 7c85b74de6 sockaddr: convert port to network/host byte order 2017-03-28 16:38:28 +02:00
Adrien Beraud fccd569059 python: allow to get bound address for any family 2017-03-28 16:32:55 +02:00
Adrien Beraud 768bfa5d44 python: add SockAddr support 2017-03-28 16:25:17 +02:00
Adrien Beraud ff6e38571d dhtrunner: add method to bootstrap with a single SockAddr 2017-03-28 15:44:09 +02:00
Simon Désaulniers 0a5a609322 benchmark: fix invalid ifname error
Two instructions were mutually misordered.
2017-03-27 23:35:55 -04:00
Adrien Béraud c424eb9160 Merge pull request #175 from sim590/argon2-submodule
argon2: use as submodule
2017-03-27 15:46:55 +02:00
Adrien Beraud 501ba77ec7 docker: add missing dep 2017-03-24 13:42:18 +01:00
Adrien Beraud dc23ee0c7a docker: update dependencies 2017-03-24 03:51:43 +01:00
Adrien Beraud e98f06e84a python: fix scanner 2017-03-24 03:51:15 +01:00
Simon Désaulniers 19c36284dc argon2: use as submodule 2017-03-22 17:18:23 -04:00
Adrien Béraud 358d8bd7b3 Merge pull request #176 from sim590/tools-help
tools: add help -h flag for dhtscanner, dhtchat
2017-03-16 03:20:22 +01:00
Simon Désaulniers c17508862c tools: add help -h flag for dhtscanner, dhtchat 2017-03-15 22:11:25 -04:00
Adrien Beraud 2277a4959c crypto: pack/unpack certificate after generation
make sure the certificate can be fully used after generation
2017-03-15 19:08:06 +01:00
Adrien Beraud d5427df9eb build: allow to use argon2 system library
allow to use system argon2 library, use system library by default:
* add --with(out)-argon2 configure options
* add -DOPENDHT_ARGON2=(On/Off) cmake option

also bump argon2 to latest git
2017-03-13 14:58:25 +01:00
Adrien Beraud 36206a80fc rng: add missing include 2017-03-08 17:50:26 +01:00
Adrien Beraud ab7d175322 network engine: make buffer length depend on HASH_LEN 2017-03-07 23:14:25 +01:00
Adrien Beraud 802528266a crypto: add secure_vector and SecureBlob 2017-03-07 23:00:10 +01:00
Adrien Beraud 95d98f4659 rng: add getSeededRandomEngine
Add a routine to seed a pseudo-engine to
use the full range of possible internal states
by using seed_seq.
2017-03-07 17:08:46 +01:00
Adrien Beraud 4176302a03 crypto: add PublicKey::toString() 2017-03-07 17:08:46 +01:00
Adrien Béraud b3119cce13 Update README.md 2017-03-07 16:14:58 +01:00
atraczyk 9987485f63 clean up solution 2017-02-17 18:15:54 -05:00
Adrien Béraud b08b2f14f2 sockaddr: add missing header and typedef 2017-02-17 12:09:33 -05:00
Adrien Béraud 1e7ba56aeb Merge pull request #174 from sim590/announce-status-fix
dht: standardize announce status check
2017-02-16 23:01:10 +01:00
Simon Désaulniers faf23195a4 dht: standardize announce status check
Fixes a bug where some callbacks wouldn't be called when a dummy request was
inserted to cancel some operation while not using the
net::Request::State::COMPLETED flag as per 19c47ec.
2017-02-16 16:29:21 -05:00
Adrien Béraud 0d66b9435f dht: print IPv6 search log 2017-02-16 11:49:38 -05:00
Adrien Béraud 49353e2d5c dht: replace expired node only when bucket is full 2017-02-10 00:38:51 -05:00
Adrien Béraud c4d5621f67 network: treat loopback address as sender address
When learning about nodes in an answer,
we used to drop nodes with loopback address.
Address is now replaced by the packet sender
address and the port is preserved.
2017-02-10 00:10:11 -05:00
Adrien Béraud aa2227bdfc SockAddr: add utility methods 2017-02-09 23:49:06 -05:00
Adrien Béraud 34908d573f network engine: use make_shared 2017-02-08 14:14:06 -05:00
Adrien Béraud 469774037e Merge pull request #169 from savoirfairelinux/crypto_checks
crypto: make Certificate::isCA() more restrictive
2017-02-07 23:27:15 +01:00
Adrien Béraud 93c5ad7cbc crypto: make Certificate::isCA() more restrictive 2017-02-07 16:51:16 -05:00
Adrien Béraud 03d52e4284 Merge pull request #170 from sim590/dht-random-id
dht: randomize id in Dht layer
2017-02-07 22:08:57 +01:00
Simon Désaulniers 9d83ee169b dht: randomize id in Dht layer 2017-02-07 15:58:04 -05:00
Adrien Béraud 43b181ebbf python: add bindings for network, maintain_storage 2017-01-25 11:57:42 -05:00
Adrien Béraud ac65ca5177 add shortcut Sp for std::shared_ptr 2017-01-24 23:38:31 -05:00
Adrien Béraud 42671be21e Merge pull request #168 from sim590/announce-op-fixes
Announce op fixes
2017-01-20 11:19:33 -05:00
Simon Désaulniers efa6930de2 dht: fix multiple put on a single search segfault
"Iterators pointing to an element between the new logical end and the physical
end of the range are still dereferenceable, but the elements themselves have
unspecified values (as per MoveAssignable post-condition)."

- http://en.cppreference.com/w/cpp/algorithm/remove
2017-01-20 02:40:05 -05:00
Simon Désaulniers 19c47ec781 dht: correctly tell if value is announced
* A value should be considered announced if all good nodes up to a count of
  TARGET_NODES have been tried in the search .
* Bug fix where SearchNode::isAnnounced criteria was not consistent with
  announce operation.
2017-01-20 02:39:59 -05:00
Adrien Béraud 435cd554e6 securedht: add getLongId() 2017-01-19 12:09:12 -05:00
Adrien Béraud 10c70ebd12 hash: add string I/O 2017-01-19 12:08:49 -05:00
Adrien Béraud 7da3ff1bba hash: add support for SHA256 public key fingerprints 2017-01-18 16:08:31 -05:00
Adrien Béraud a222e30428 update to version 1.3.0 2017-01-17 16:44:02 -05:00
Adrien Béraud bd822fce19 dht: don't stop node insertion on expired search 2017-01-17 16:43:32 -05:00
Adrien Béraud cabe9dbeb5 dht: declare StorageBucket as class 2017-01-16 17:53:21 -05:00
Adrien Béraud 99b7a07350 sockaddr: make ipCmp comparator const 2017-01-16 17:51:59 -05:00
Adrien Béraud 756e0bd3d8 dht: cleanup paginate
Reduce indentation level by 4,
add code documentation,
remain under 120 chars wide.
2017-01-15 19:02:15 -05:00
Adrien Béraud 9b0ce12b5f Update README.md 2017-01-15 02:18:37 -05:00
Adrien Béraud e29c2df002 Merge pull request #166 from sim590/license-notice
update license notice (2017)
2017-01-15 02:15:10 -05:00
Simon Désaulniers b03a8b5b50 update license notice (2017) 2017-01-13 17:27:29 -05:00
Adrien Béraud 32f5175d68 dht: expire storage just on time 2017-01-13 16:06:46 -05:00
Adrien Béraud 7d3a54db57 dht: storage rate limiting 2017-01-13 16:06:46 -05:00
Adrien Béraud 3fb7c2acfe Merge pull request #165 from atraczyk/master
msvc: change contrib repo sources
2017-01-11 14:48:56 -05:00
atraczyk bce5d35b51 msvc: change contrib repo sources 2017-01-11 14:37:22 -05:00
Adrien Béraud b6dca5ccd6 dht: use new NodeStats structure to provide stats 2017-01-10 23:34:56 -05:00
Adrien Béraud 23b2712400 dht: use SHA265 instead of SHA512 for the op token
The op token is renewed regularly (around every 30 minutes),
so SHA256 provides enough security for this non-sensitive token.
SHA256 takes 32 bytes instead of 64 bytes for SHA512,
and the token is included in every listen requests,
renewed every 30 seconds, and every answer to get.
In the context of limited bandwith usage, using SHA256 seems more appropriate.
This change is backward and forward compatible.
2017-01-10 23:34:56 -05:00
Adrien Béraud 63bec73885 default types: make TrustRequest a map, add confirm field 2017-01-10 14:24:42 -05:00
Simon Désaulniers af5e0c8982 node: remove expired flag when a node reaches us 2017-01-09 14:40:42 -05:00
Adrien Béraud 5a7c8753e1 python/tools: use asyncio in pingpong test 2017-01-09 14:40:06 -05:00
Adrien Béraud 19fdec96ca dht: remove getStatus with get 2017-01-09 14:38:51 -05:00
Adrien Béraud 2208a06232 dht: clear acked with announce
Clear the search node acked when clearing
the corresponding announce, after checking
the announce status for all announces.
2017-01-09 00:06:54 -05:00
Adrien Béraud 2cfcaf3909 Merge pull request #164 from sim590/connectivity-changes
routing_table: complete connecting state resolution
2017-01-04 14:04:37 -05:00
Simon Désaulniers 620868b5d6 routing_table: complete connecting state resolution
After a connectivity change, the DHT would enter the "connecting" state in order
to try to resolve good nodes. However, the previous algorithm would
probabilistically increase time for completion each time a node would fail to
resolve. We now avoid this by prioritizing non-expired nodes in the process.
Also, a subtle error would sensibly stop the process for 30 minutes due to using
the Node::NODE_EXPIRE_TIME constant instead of Node::MAX_RESPONSE_TIME.
2017-01-03 17:48:40 -05:00
Adrien Béraud e7295bac7b crypto: prevent signing certificates with a non-CA certificate 2017-01-02 16:16:28 -05:00
Adrien Béraud 38aa86de2a crypto/crl: add getIssuerName, getIssuerUID 2016-12-29 11:19:27 -05:00
Adrien Béraud fdf476a3f3 cmake: generate opendhtConfigVersion.cmake 2016-12-29 11:18:45 -05:00
Adrien Béraud 22f27a6cc0 cmake: generate opendhtConfig.cmake 2016-12-28 18:19:16 -05:00
Adrien Béraud c72ea8ce77 tools/scanner: don't use a certificate 2016-12-09 02:41:40 -05:00
Adrien Béraud ea168353b9 tools/scanner: use urllib3 streaming 2016-12-09 02:41:12 -05:00
Adrien Béraud 79b9c4838e Merge pull request #161 from savoirfairelinux/yomgui1-patch-1
remove InfoHash::toCString()
2016-12-06 18:35:56 -05:00
Guillaume Roguez d6e86ebcc9 remove InfoHash::toCString()
Implementation of InfoHash::toCString() is broken
2016-12-06 18:28:14 -05:00
Adrien Béraud 197aaa47f0 crypto: prevent duplicate CRLs, reimport after signing 2016-12-06 16:59:54 -05:00
Adrien Béraud ad234004aa crypto: store CRLs in a set 2016-12-05 15:43:00 -05:00
Adrien Béraud a88e6a4c5f crypto: make CRL default expiration same as certificate 2016-12-02 12:59:03 -05:00
Adrien Béraud c776dad96f crypto: add Certificate::getExpiration() 2016-12-02 12:58:10 -05:00
Adrien Béraud 31fedd529b crypto: add CRL msgpack serialization 2016-12-01 18:42:26 -05:00
Adrien Béraud e9adff9dc5 crypto: add CRL move operator, export as DER 2016-11-30 17:30:09 -05:00
Adrien Béraud bfd58a204b crypto: add CRL import/export methods 2016-11-30 16:31:29 -05:00
Adrien Béraud 867bcf1514 crypto: add EC key generation 2016-11-29 18:04:25 -05:00
Adrien Béraud fb882ee440 crypto: add revocation list 2016-11-29 18:03:49 -05:00
Adrien Béraud 215d3d2847 http server: add cmd arguments 2016-11-29 13:31:40 -05:00
Adrien Béraud 43a345ba0c python: add HTTP server to access the DHT 2016-11-29 12:08:33 -05:00
Adrien Béraud f73f5e2798 log: cosmetics 2016-11-29 01:27:42 -05:00
Istvan 3724670fcc Log.cpp added to src/MakeFile.am 2016-11-29 00:50:47 -05:00
Istvan e7db64bd74 Log functions are moved to log.cpp
Log functions are moved to the log.cpp
in order to avoid multiple definitions
of the logger functions.
2016-11-29 00:50:47 -05:00
Adrien Béraud 9c29b8a29e Merge pull request #160 from sim590/fix-include-dep
buildtools: add def.h to include files
2016-11-28 01:49:30 -05:00
Adrien Béraud c22f0e4d43 Update Makefile.am 2016-11-28 01:48:26 -05:00
Adrien Béraud 4e2b11c24c Update CMakeLists.txt 2016-11-28 01:47:33 -05:00
Simon Désaulniers 8c34e927ea buildtools: add def.h to include files 2016-11-27 23:28:23 -05:00
Adrien Béraud 8a5de47aa0 hide symbols by default (#140) 2016-11-23 18:27:24 -05:00
Adrien Béraud 7f84c1e397 utils: remove useless definitions 2016-11-23 15:12:37 -05:00
Adrien Béraud 65c915fd9d value: print hex value data contiguously 2016-11-23 11:01:14 -05:00
Adrien Béraud 0fd4f73ab1 network monitor: access proper dictionary key 2016-11-23 11:00:11 -05:00
Adrien Béraud 01117567b1 cmake: adapt pkg-config paths to GNUInstallDirs 2016-11-22 10:43:01 -05:00
Adrien Béraud d68cc5cf40 Merge pull request #156 from sim590/cython-robust-check
autoconf: robustly check for cython3
2016-11-21 15:10:40 -05:00
Simon Désaulniers 6db16be2fa autoconf: robustly check for cython3 2016-11-14 21:07:36 -05:00
Adrien Béraud 5166b1add9 tools: add network monitor
The network monitor allows to regularly
check the status of an OpenDHT network,
by performing listen and put operations at
random places on the DHT.

This first version exit with status code 1
if the test fails.
2016-11-10 01:03:29 -05:00
Adrien Béraud 9fadcc907c python: add default port for bootstrap 2016-11-10 00:58:35 -05:00
Adrien Béraud 42171efc3f dht: send values to all sockets for a node
We used to send values once to a given node,
however the receiving node may have canceled
or dropped the request since then,
so we now send the values for every socket and
the optimization will happen on the sending side.
2016-11-09 21:53:43 -05:00
Adrien Béraud 206f12648f Merge pull request #155 from aviau/patch-1
Multi-Arch support
2016-11-09 13:10:08 -05:00
Alexandre Viau ecd0573c4d Multi-Arch support 2016-11-09 11:30:17 -05:00
Simon Désaulniers 2d9f6241a9 net: don't close socket on listen renew 2016-11-08 16:07:15 -05:00
Adrien Béraud 77ee50f5a6 Merge pull request #154 from savoirfairelinux/c_str
infohash: add helper to C string format conversion
2016-11-08 15:48:05 -05:00
Guillaume Roguez 297c37e609 infohash: add helper to C string format conversion
This const void* convertion method helps a lot with programs
that need to print the hash with a printf() like function.
2016-11-08 15:26:13 -05:00
Simon Désaulniers 9bb1ab43eb net.h: moved to include/opendht/ 2016-11-08 14:52:09 -05:00
Adrien Béraud cd36b13c30 dht: prevent infinite loop in expireStorage() 2016-11-07 16:56:08 -05:00
Adrien Béraud 5d63084627 Merge pull request #152 from sim590/listen-consistency
Listen consistency
2016-11-07 10:33:05 -05:00
Simon Désaulniers ab7d1d6582 dht,net: introduce socket, support multiple listen
Since the initial implementation of listen operation, multiple listen requests
from a single node on a same hash was not possible without singular
inconsistencies. The flaw was coming from the fact that nodes receiving listen
request could not differentiate between listen refresh request and a new
independent listen request.

This patch introduces the new net::Socket structure which in time will enable
remote nodes to send update for a storage while differentiating between
concurrent listen requests. A socket has a unique identifier which consists of a
transaction id as defined in the OpenDHT protocol.
2016-11-07 06:44:15 -05:00
Simon Désaulniers 77ea6d8c2f net: create net namespace, moving relevant structs 2016-11-05 19:29:00 -04:00
Simon Désaulniers b5cd629160 dht: callback if no storage maintenance 2016-11-04 09:15:10 -04:00
Adrien Béraud 39467c8b71 tools: add python cluster runner commands 2016-11-02 02:32:06 -04:00
Adrien Béraud 87740e3b38 tools: add python node cluster runner 2016-11-01 03:14:26 -04:00
Adrien Béraud 19848a9b72 python: encode log file name 2016-11-01 03:13:56 -04:00
Adrien Béraud 36e9998fe2 scanner: use urllib3 2016-11-01 03:13:56 -04:00
Adrien Béraud b2529c241e log: flush on new line 2016-11-01 03:13:56 -04:00
Adrien Béraud 83c47037d2 dht: remove unimplemented declaration 2016-11-01 03:13:56 -04:00
Adrien Béraud 125b6f9236 dht: make storage maintenance optional, default disabled 2016-10-31 14:43:56 -04:00
Adrien Béraud e260ba6b78 infohash: remove misused restrict 2016-10-31 12:35:50 -04:00
Simon Désaulniers eafb934e85 bump version to 1.2.1 2016-10-28 18:49:09 -04:00
Adrien Béraud c3d3da20f6 Merge pull request #146 from sim590/permanent-put-enhancement
dht: make reannounce margin bigger, safer
2016-10-28 16:24:07 -04:00
Adrien Béraud 6036ccdbaa dht: try inserting new nodes smarter (#150)
Attempt closest search and nearby searches
until we are too far instead of trying every
search.
2016-10-28 15:46:27 -04:00
Simon Désaulniers 9404a4d069 dht: make reannounce margin bigger, safer
Reannouncing margin going from 5 seconds to 10 seconds.
2016-10-28 15:24:09 -04:00
Adrien Béraud 274621dcec dht: add searches(sa_family) 2016-10-27 18:12:05 -04:00
Adrien Béraud 2ab756906d dht: getSearchLog for a specific search 2016-10-27 16:51:21 -04:00
Adrien Béraud 2b3f63443f dht: maintain each storage independently
Schedule every storage maintenance independently,
to improve performance when there are a lot of storages.
2016-10-27 14:21:52 -04:00
Adrien Béraud c71f960948 python: add ping-pong simple test 2016-10-26 18:07:06 -04:00
Adrien Béraud 9d3514e087 dhtrunner: don't run ops if disconnected and bootstraping 2016-10-26 17:50:30 -04:00
Adrien Béraud 6703e039b1 network_engine: deserialize proper number of fields 2016-10-26 17:50:30 -04:00
Adrien Béraud 29b81750ad Merge pull request #148 from atraczyk/master
bump visual studio support
2016-10-26 12:48:51 -04:00
atraczyk d6fff53f6b bump visual studio support 2016-10-26 10:28:05 -04:00
Simon Désaulniers 7ee6281426 log: display time before each line in log 2016-10-25 16:40:48 -04:00
Adrien Béraud 28a5740c37 argon2: bump source 2016-10-25 16:40:48 -04:00
Adrien Béraud 09a3332cf0 Merge pull request #147 from savoirfairelinux/feature/log_filter
log: add filters
2016-10-24 16:55:23 -04:00
Adrien Béraud f584c4849b dht: unify creation date normalisation 2016-10-24 02:09:38 -04:00
Adrien Béraud e3663c995a log: add storage filter 2016-10-24 02:09:38 -04:00
Adrien Béraud 1d62b3ca64 log: add InfoHash filter
* filter log entries with new method setLogFilter
* filter by node id, search or infohash
* add optional parameter to 'log' in dhtnode
2016-10-24 02:09:38 -04:00
Adrien Béraud 3af04a4259 securedht: use default max expiration for putSigned 2016-10-23 17:23:39 -04:00
Adrien Béraud 78d98822a5 securedht: use default max expiration for putEncrypted 2016-10-23 16:47:37 -04:00
Adrien Béraud 8c04ddc66b dht use proper value type to compute expiration 2016-10-23 14:58:15 -04:00
Adrien Béraud 5277b8d23e dht: storage refresh returns bool 2016-10-23 03:23:17 -04:00
Simon Désaulniers 86fea49178 doc: add pdf compiled of tex file 2016-10-21 19:00:08 -04:00
Simon Désaulniers 5b1242f786 bump version
* several clang related bug fixes;
* connectivity changes related enhancements;
* new "refresh" protocol primitive (not exposed to API);
* "permanent put" operation fixes/enhancements;
* fixed general efficiency issues;
2016-10-21 18:56:45 -04:00
Simon Désaulniers a8cfdbe762 doc: add connectivity loss search analysis tex file 2016-10-21 18:07:11 -04:00
Adrien Béraud 70b1ebae0b dht: fix scheduler job edition on clang 2016-10-21 17:44:39 -04:00
Adrien Béraud 9dc6004329 network engine: cancel request when clearing listen status 2016-10-19 13:58:18 -04:00
Adrien Béraud d4bd17a2dc dhtrunner: use a second condition variable for bootstrap 2016-10-19 13:34:33 -04:00
Simon Désaulniers 6c73e5fa5c dht: less cases clear values, storage maintenance 2016-10-19 11:53:47 -04:00
Simon Désaulniers 24edfb8eaf dht: uniformly sync SearchNodes reannouncing
Historically, the next announce timing was based on the last acknowledgement
received from a SearchNode. This behavior was invalid since the 'refresh'
operation. In fact, for a given value that was "refreshed", its creation time
would differ from the announcer's info. Therefor, all search node's
reannouncing timings would differ, hence causing inconsistency on the network.
2016-10-19 11:53:47 -04:00
Adrien Béraud 4ef5a2216e dht: revert to previous onNewNode behavior 2016-10-19 01:27:19 -04:00
Adrien Béraud 0d646eb244 network engine: log cleanup 2016-10-19 01:01:51 -04:00
Adrien Béraud 757fea37f3 Merge pull request #142 from sim590/fix-permanent-put-time-info
dht: appropriate time info in permanent put ops
2016-10-18 14:26:21 -04:00
Simon Désaulniers 09e41cc9f2 dht: appropriate time info in permanent put ops 2016-10-18 14:20:43 -04:00
Adrien Béraud 71ad92e286 dht: log cleanup 2016-10-17 17:55:22 -04:00
Adrien Béraud d4f3d3aa98 dht: add missing iterator 2016-10-17 17:14:30 -04:00
Simon Désaulniers c0612a1b2c dht: use "refresh" operation for permanent put 2016-10-17 11:56:54 -04:00
Simon Désaulniers 6743cbbf50 dht: introduce "refresh" operation
This operation requests a node to refresh a value's time_point information of
its lifetime begining. This is intended to fix the *permanent put* operation
which has been having syncing issues since the introduction of an enhanced and
lighter put operation.
2016-10-17 11:56:54 -04:00
Adrien Béraud da1bdf9d4c dht: retry nodes more aggressively in case of failure 2016-10-16 22:36:52 -04:00
Adrien Béraud 96da4cd85d build: make logs optional at build time 2016-10-16 22:36:42 -04:00
Adrien Béraud f233340cb2 node: clear reply_time on reset 2016-10-16 22:36:36 -04:00
Adrien Béraud cfb817d37f dht: add buckets() utility 2016-10-16 22:36:30 -04:00
Adrien Béraud 9440c03048 dht: log cleanup 2016-10-16 22:36:24 -04:00
Adrien Béraud aa611bde50 network engine: cleanup 2016-10-15 20:07:37 -04:00
Adrien Béraud 7af856508e dht: make connectivityChanged family dependent 2016-10-15 19:13:15 -04:00
Adrien Béraud aaed64039a dht: fix compilation on clang 2016-10-12 15:02:02 -04:00
Adrien Béraud 7c5e8c3234 sockaddr: add missing include for Win32 2016-10-12 14:38:39 -04:00
Adrien Béraud a56bf3f115 dhtrunner: handle null callback in pingNode 2016-10-12 13:25:00 -04:00
Adrien Béraud 2d2fa9cfa9 OpenDHT 1.1.0
* automatic connection loss recovery
* dhtrunner: asynchronous DNS lookup for bootstrap
* handle values up to 64k
* better support for large values on macOS
* dht: add callback to pingNode
* fix compilation with recent clang versions
2016-10-11 17:36:12 -04:00
Adrien Béraud 9f11930f3d fix compilation on latest clang 2016-10-11 16:34:40 -04:00
Adrien Béraud 013b1dfe2e Merge pull request #138 from sim590/connectivity-changes-detect
search: detect connectivity changes
2016-10-11 16:01:59 -04:00
Simon Désaulniers 733f699ff2 search: detect connectivity changes
The number of bad nodes is limited in order to help determine presence of
connectivity changes. See https://github.com/savoirfairelinux/opendht/issues/137
for details.

According to the tables, 25 is a good average value for big networks. If the
network is small, normal search expiration process will handle the situation.
2016-10-11 15:54:37 -04:00
Adrien Béraud a366d502a2 fix compilation on latest clang 2016-10-11 15:50:49 -04:00
Adrien Béraud eed8ffc792 Merge pull request #139 from savoirfairelinux/recover-from-network-changes
dhtrunner: recover from network changes
2016-10-11 11:57:31 -04:00
Adrien Béraud 998547e1a1 Merge pull request #136 from savoirfairelinux/feature/value_fragment
network: transmit large values in multiple packets
2016-10-11 11:57:18 -04:00
Simon Désaulniers 8567b7ad84 network_engine: expire requests when clearing NE
This is to prevent any thread relying on network_engine's callback to block
forever just like the Dht::sendPing's callback.
2016-10-10 01:51:26 -04:00
Adrien Béraud 64118404fe dhtrunner: recover from network changes
Using a list of bootstrap nodes, we recover from network loss by pinging those
nodes continuously until connected.
Written with Simon Désaulniers.
2016-10-10 01:51:26 -04:00
Simon Désaulniers bb74dc846c dht/dhtrunner: enable callback for pingNode 2016-10-10 00:23:53 -04:00
Adrien Béraud 659d893dee network: transmit large values in multiple packets 2016-10-09 16:22:33 -04:00
Simon Désaulniers e3f371c2d8 bump version 2016-10-06 08:27:00 -04:00
Adrien Béraud f53c7a6785 dht: keep track of storage usage in maintainStorage 2016-10-04 03:09:00 -04:00
Adrien Béraud 261c193b50 Merge pull request #133 from sim590/sync-enhancements
dht: bug fixes, timing computation enhancements
2016-09-24 19:07:05 -04:00
Simon Désaulniers dc0b650aa3 dht: make sure we are synced before sending put 2016-09-23 19:27:59 -04:00
Simon Désaulniers 87cf6faedd dht/node: don't allow more than 3 auth errors 2016-09-23 19:27:59 -04:00
Simon Désaulniers ca6aa6706d dht/value: make 'find_node' queries satisfied by any queries
'find_node' requests don't ask for values. Then, the idea of a Query makes less
sense, but since we still need those to map status to network engine requests,
we introduce dummy queries which with the field Query::none. Those queries will
then only serve as key to network engine's requests.
2016-09-23 19:27:58 -04:00
Simon Désaulniers 16e55416a6 network_engine: fix bug token not sent for listen 2016-09-23 19:27:58 -04:00
Simon Désaulniers 3e24058175 dht: fix SearchNode's getListenTime computation
When no listen request have been sent yet, getListenTime should tell it's okay
to send pending listen request.
2016-09-23 19:27:55 -04:00
Simon Désaulniers d1c2b20b28 dht: canGet must allow sending when no token 2016-09-23 13:48:04 -04:00
Adrien Béraud ccd0cbd8f2 add per IP rate limiting (#131) 2016-09-21 15:44:20 -04:00
Adrien Béraud e5213674e3 value: fix compilation on older clang 2016-09-20 17:02:29 -04:00
Adrien Béraud b9cc848810 cmake: remove OPENDHT_DEBUG flag
Replace with -DCMAKE_BUILD_TYPE=Debug
2016-09-20 00:04:39 -04:00
Adrien Béraud 65bdfaf22b autotools: fix 'make dist' 2016-09-18 13:55:14 -04:00
Adrien Béraud de31d836b4 Merge pull request #132 from savoirfairelinux/feature/map_storage
dht: use a map for storage
2016-09-18 13:02:03 -04:00
Adrien Béraud 25b339956e tools: gnutls cleanup 2016-09-16 01:43:58 -04:00
Adrien Béraud 23bb6e7a45 dht: use a map for storage 2016-09-16 01:29:33 -04:00
Adrien Béraud b44f7ec653 Merge pull request #130 from savoirfairelinux/feature/sockaddr
introduce SockAddr to store IP addresses
2016-09-15 23:46:57 -04:00
Adrien Béraud 6d38c18572 introduce SockAddr to store IP addresses 2016-09-15 01:38:26 -04:00
Simon Désaulniers 8eaf78bfe2 bump version 2016-09-14 19:06:51 -04:00
Simon Désaulniers dc836b38a6 build: use -pedantic-errors flag in autotools 2016-09-14 19:06:20 -04:00
Adrien Béraud b01f8d079b Merge pull request #128 from sim590/concurrent-queries
[dht] concurrent queries
2016-09-14 18:12:47 -04:00
Simon Désaulniers 6f7ac21a85 dht: refactor code, terminating a Search (isDone)
More code encapsulated in objects method is better for keeping consistent
behavior.
2016-09-14 18:06:25 -04:00
Simon Désaulniers 7c5db84f33 dht: take multiple queries into account
The code preceding this would just not take multiple concurrent queries for a
same search into account. This is a bug fix for a bad behavior since the
queries.
2016-09-14 18:06:23 -04:00
Simon Désaulniers 4fecb2066b dht: SearchNode::canGet criteria using 'update'
The criteria has been rewritten (again) exploiting the idea behind the parameter
'update' to take into account the case where we have new distinct requests to
send, then bypass some checks.
2016-09-14 18:06:12 -04:00
Adrien Béraud eabdddcfb3 dht: fix warnings 2016-09-08 18:02:17 -04:00
Adrien Béraud ceab27d723 value: optimize chainAll for empty filters 2016-09-08 17:22:34 -04:00
Adrien Béraud a9cc669a95 dht: clarify code 2016-09-08 15:52:18 -04:00
Simon Désaulniers 927c835b8f dht: call all announce callback appropriately 2016-09-08 12:24:35 -04:00
Simon Désaulniers 5415eaaf60 dht: consider probe query in announce time 2016-09-08 12:24:35 -04:00
Simon Désaulniers ec587f9b58 dht: make sure search can be flagged "done" 2016-09-08 12:24:35 -04:00
Simon Désaulniers babfed73f3 dht: use SearchNode::acked for next announce time 2016-09-08 12:24:35 -04:00
Simon Désaulniers 2c0ce576e3 dht: enable data persistence 2016-09-08 12:24:35 -04:00
Simon Désaulniers 8f2cc937c5 dht: introduce light put
The 'put' operation will now first check if nodes already store the value we
have to announce. If so, we don't announce it to that node.
2016-09-08 12:24:35 -04:00
Adrien Béraud c9f6567128 Merge pull request #127 from sim590/insert-node-export-fix
dht: Dht::insertNode has to really insert
2016-09-07 16:43:28 -04:00
Simon Désaulniers d60672e8ba dht: remove unnecessary return value 2016-09-07 16:15:06 -04:00
Simon Désaulniers fd4cce4883 NetworkEngine: insertNode tells routing table 2016-09-07 15:54:16 -04:00
Adrien Béraud df15d3d48e Merge pull request #126 from savoirfairelinux/wip/crypto
crypto: drop support for GnuTLS < 3.3
2016-09-07 00:10:36 -04:00
Adrien Béraud 76fd216386 crypto: drop support for GnuTLS < 3.3 2016-09-06 17:18:16 -04:00
Adrien Béraud 48735aad94 build/cmake: use proper indentation 2016-09-06 17:16:33 -04:00
Adrien Béraud 91a1471de5 build/autotools: fix build flags 2016-09-06 17:16:33 -04:00
Adrien Béraud 047ba76ff1 Merge pull request #125 from savoirfairelinux/wip/crypto
crypto: add length parameters
2016-09-06 13:50:38 -04:00
Adrien Béraud e57eb63c87 securedht: don't complain about certificate announcement 2016-09-06 12:06:30 -04:00
Adrien Béraud 8461f4018d crypto: avoid using std::to_string 2016-09-06 12:06:30 -04:00
Adrien Béraud c33c2e7e95 crypto: add key, hash length parameters 2016-09-06 12:06:30 -04:00
Adrien Béraud e5a9a2af4c Merge pull request #124 from aberaud/master
dht: fail pending operations before clearing them
2016-09-06 10:49:33 -04:00
Adrien Béraud 7919ca8de1 dht: fail pending operations before clearing them 2016-09-02 14:30:08 -04:00
Adrien Béraud 00ef660952 dht: hide more internal structures 2016-09-02 14:30:08 -04:00
Adrien Béraud 862a03713b opendht: version 1.0
* add Prefix Hash Tree (PHT) for data indexation (Nicolas Reynaud, Simon Désaulniers)
* add Queries (Simon Désaulniers)
* add long-term data persistance (Simon Désaulniers)
* add data pagination (Simon Désaulniers)
* reduced bandwith usage
2016-09-01 18:02:23 -04:00
Adrien Béraud 89d0d2f109 pht: fix compilation with pedantic 2016-09-01 18:02:23 -04:00
Adrien Béraud 3283e34dcf pht: rebase over queries 2016-09-01 18:02:23 -04:00
kaldoran 34c6b264df Add filter of duplicate value 2016-09-01 18:02:23 -04:00
kaldoran 2d8fe502f2 Fix print of the lookup output 2016-09-01 18:02:23 -04:00
kaldoran 73df308250 Adding ZCurve algorithm 2016-09-01 18:02:23 -04:00
kaldoran cdca40cb59 Rework prefix [add flags] and prepare prefix 2016-09-01 18:02:23 -04:00
kaldoran 2a3c301314 dht: Fix get and put at the same time on a same node
When the put is performed just after a get, then the get will not include the value which was in the put.
2016-09-01 18:02:23 -04:00
kaldoran 6f4923da2e dht: fix some typo 2016-09-01 18:02:23 -04:00
kaldoran ae26a2b39a Update of algorithm, by using new feature of api 2016-09-01 18:02:23 -04:00
kaldoran 48c40c8a27 pht: correction on the algorithm of complet node splitting 2016-09-01 18:02:23 -04:00
kaldoran a4a4eee495 pht: introduction of complet node splitting 2016-09-01 18:02:23 -04:00
kaldoran d185428d1d [Python] Draw benchmark graph in a better way #104 2016-09-01 18:02:23 -04:00
kaldoran 6855aaa6f4 Correction of error on SwapBit 2016-09-01 18:02:23 -04:00
kaldoran 2aee4f418f Correction of the size of the prefix, now size does not include the size of the padding 2016-09-01 18:02:23 -04:00
kaldoran 95aef01a59 Pht : Fix out of range in isActiveBit function 2016-09-01 18:02:23 -04:00
kaldoran d2ccde4859 pht: bit padding when the key is too short 2016-09-01 18:02:23 -04:00
Simon Désaulniers 7ab64ea0e6 pht: validKey must check for key field value len 2016-09-01 18:02:23 -04:00
Simon Désaulniers fe1b8b88e1 pht: provide simpler lookup callback
From a user point of view, the structure Prefix doesn't make sense really. It's
better to provide a simpler callback function signature for the user then.
2016-09-01 18:02:23 -04:00
Simon Désaulniers b6832869b1 pht: moved some defs in cpp file 2016-09-01 18:02:23 -04:00
Simon Désaulniers 6da8d39a0e python: update cython wrapper and python benchmark
API changed when the keys pec was added. This commit updates python code
according to the new API.
2016-09-01 18:02:23 -04:00
Simon Désaulniers f8cf1316ad pht: add key spec, handling maximum prefix length
This commit adds the new KeySpec in the Pht constructor signature so that all
keys used inside a same PHT structure have the same maximal length.
2016-09-01 18:02:23 -04:00
Simon Désaulniers 736606a845 pht: a Key is rather map str:Blob not str:Prefix 2016-09-01 18:02:23 -04:00
Simon Désaulniers cba240e15e pht: fix invalid comparison, inexact match lookup 2016-09-01 18:02:23 -04:00
Adrien Béraud eb90fffb5e update for API changes 2016-09-01 18:02:23 -04:00
kaldoran 041e280bde benchmark: timing pht insert operations 2016-09-01 18:02:23 -04:00
kaldoran 33fae1cb66 pht: add prefix cache 2016-09-01 18:02:23 -04:00
Simon Désaulniers 4e8408e225 python: lock before launching pht insert in test 2016-09-01 18:02:23 -04:00
Simon Désaulniers e85a423f6a Revert "[Bug] Correction of function commonBits" 2016-09-01 18:02:23 -04:00
kaldoran 532cb40665 Correction of error on commonBits 2016-09-01 18:02:23 -04:00
kaldoran dd58b0497e Correction of prefix, sometime some bit remain at they default value 2016-09-01 18:02:23 -04:00
Kaldoran cc070c80ba Fix the autotool Makefile, missing pht include
Fix indentation for pull request #37

Fix include error, and use only needed file in pht

Fix implementation of function in pht
2016-09-01 18:02:23 -04:00
Simon Désaulniers e332dae576 python: insert test show entries for each prefix 2016-09-01 18:02:23 -04:00
Simon Désaulniers 727fd4e98b fix typo in tests 2016-09-01 18:02:23 -04:00
Simon Désaulniers 5a5f7012d8 add pht insert test 2016-09-01 18:02:23 -04:00
Simon Désaulniers 5a239cddf7 pht: fix insert always to root bug
This makes the pht node recover all indexed data on a DHT node (maximum
MAX_NODE_ENTRY_COUNT per node) so that the pht node can be aware if it has to
split its data in the leaf.
2016-09-01 18:02:23 -04:00
Simon Désaulniers c4928553ba python: fix successive deref on cython object 2016-09-01 18:02:23 -04:00
Simon Désaulniers 48b0cff08e pht: fix multiple DoneCallBack calls 2016-09-01 18:02:23 -04:00
Simon Désaulniers c8fcffbe6b fix possible out of range error in Prefix ctor 2016-09-01 18:02:23 -04:00
Simon Désaulniers 63c4eeb9c9 cover empty leaf case in inexact match lookup
In case this is inexact match lookup and we end up on an empty leaf (diffrent
than the root), the search goes on in the leaf's sibling subtree.
2016-09-01 18:02:23 -04:00
Simon Désaulniers d45f777099 pht tools 2016-09-01 18:02:23 -04:00
Simon Désaulniers 9c4035dd8f add inexact match lookup
This is meant to enable random lookup queries.
2016-09-01 18:02:23 -04:00
Simon Désaulniers acc2b71c86 base pht indexation 2016-09-01 18:02:23 -04:00
Nicolas 09d849c93d Update README.md 2016-09-01 17:46:04 -04:00
Nicolas 1be1ad88c6 Update README.md 2016-09-01 17:43:10 -04:00
Nicolas 8ecaf25339 Move logo in the right position 2016-09-01 17:41:33 -04:00
Adrien Béraud 7a6dce4727 securedht: don't complain about certificate announcement (reverted from commit 85a9dbafc6) 2016-09-01 17:12:28 -04:00
Adrien Béraud b357ffb0e6 add logo 2016-09-01 17:10:59 -04:00
Adrien Béraud 517bd5f22b opendht: add logo 2016-09-01 12:49:26 -04:00
Adrien Béraud d1d0a67d35 dht: fix public address sorting 2016-09-01 12:46:39 -04:00
Adrien Béraud 85a9dbafc6 securedht: don't complain about certificate announcement 2016-09-01 12:46:39 -04:00
Nicolas 79390f72fa Merge pull request #121 from sim590/benchmark-msgpack-ipc
[benchmark] new msgpack ipc
2016-08-31 16:25:21 -04:00
Simon Désaulniers b7a37dd771 benchmark: msgpack with callback based IPC 2016-08-31 15:47:05 -04:00
Simon Désaulniers b24d1ccc8b benchmark: removing anormal behavior from normal test 2016-08-31 15:37:30 -04:00
Simon Désaulniers 4f53e10e7e benchmark: enable traffic_plot for "delete" test 2016-08-31 15:37:30 -04:00
Simon Désaulniers a608ad3cf6 benchmark: send new distinct values during test
During totallyNormalTest, an initial set of values would be put on the dht.
Then, random values from this same set would be put over time, but since values
would already be there, no put were really made.
2016-08-31 15:37:29 -04:00
Simon Désaulniers a135f81073 benchmark: create function for displaying plot 2016-08-31 15:37:15 -04:00
Nicolas 2da48557ff Merge pull request #120 from sim590/fix-timing-loops
dht: send find_node before sending 'listen'.
2016-08-30 16:14:22 -04:00
Simon Désaulniers 73686debaf dht: before sending 'listen', send find_node
Since pagination, a bug was making the listen feature unusable running in
infinite loop. This also makes more sense than sending 'get' since the listen
request is paired with a Query defining the values that have to be fetched.
2016-08-30 15:51:50 -04:00
Adrien Béraud 97950621cd crypto: check max data size for sign 2016-08-25 00:42:50 -04:00
Adrien Béraud b3401828e4 dht: set "connecting" state when waiting for a ping 2016-08-25 00:42:50 -04:00
Nicolas 0a7d4a68b3 Merge pull request #119 from sim590/find-node-timings
dht: cover bad cases in SearchNode::canGet
2016-08-22 19:16:19 -04:00
Simon Désaulniers 8d7deffa6a dht: properly find pending satisfying query
In SearchNode::canGet, we don't send a 'get' request to a search node if a
satisfying query for the query we want to send is already pending. This patch
honors this behavior.
2016-08-22 18:45:29 -04:00
Simon Désaulniers 669c08210e dht: erase find node request status when done
This was memory leak and produced inconsistency in SearchNode::canGet timings.
2016-08-22 18:26:53 -04:00
Adrien Béraud 27a3231a55 argon2: bump source 2016-08-18 10:10:03 -04:00
Seva Ivanov 86ce695939 cython: change shared_ptr invocation to libcpp.memory 2016-08-16 10:27:34 -04:00
Adrien Béraud 2759a136df infohash: add istream operator overload 2016-08-16 10:27:31 -04:00
Adrien Béraud 690682408b build with -pedantic-errors, fix pedantic build errors 2016-08-16 10:26:44 -04:00
Nicolas bfdb8a24e9 Merge pull request #113 from sim590/value-pagination-fix
dht: value pagination fix
2016-08-15 19:35:33 -04:00
Simon Désaulniers e9bf042ac5 dht: document SearchNode::canGet 2016-08-15 13:44:52 -04:00
Simon Désaulniers 5aab3078c8 dht: properly handle pagination timings 2016-08-15 12:13:16 -04:00
Simon Désaulniers 1ac5840bb1 dht: let nodes expire properly
The line with `srn->getStatus[query]->setExpired()` in searchNodeGetExpired was
messign with the node expiration process.
2016-08-14 22:08:52 -04:00
Simon Désaulniers 426b3d6834 dht: pagination queries should be in SearchNode
Pagination queries must to be kept in seperate list per node. Otherwise, two
searches could be blocking each others or generating unwanted behavior.
2016-08-11 12:27:04 -04:00
Nicolas 97b573c182 Merge pull request #110 from sim590/value-pagination
dht: Value pagination using queries
2016-08-09 17:27:00 -04:00
Simon Désaulniers 5c41cbb964 dht: value pagination
Instead of literally asking to a node all values for givent `h`, we first ask
for all ids the node has. Then, we concurently and individually ask for each
values that match each id we recovered in our first request.
2016-08-09 15:43:55 -04:00
Simon Désaulniers e192e3beaf better indentation and comments 2016-08-09 15:42:05 -04:00
Adrien Béraud 5dacb50d63 Merge pull request #108 from sim590/search-refill-from-cache
dht: unify bootstrapSearch and refill method using node cache
2016-08-09 14:41:23 -04:00
Adrien Béraud 86d837b5a9 Merge pull request #106 from sim590/get-timings
[dht] rework get timings after queries in master
2016-08-09 14:23:13 -04:00
Adrien Béraud 6454a6dc3f Merge pull request #109 from kaldoran/fix_put-get
dht: Fix, get does not include the put value if its performed just after it.
2016-08-08 18:10:05 -04:00
kaldoran bbd1200ad7 dht: Fix get and put at the same time on a same node
When the put is performed just after a get, then the get will not include the value which was in the put.
2016-08-08 17:50:56 -04:00
Adrien Béraud aa59242843 readme: add IRC link 2016-08-07 00:13:18 -04:00
Simon Désaulniers c04ede4909 dht: unify bootstrapSearch and refill method
Since bootstrapSearch was rewritten to use the node cache, it made it clear that
refill should be rewritten as such. However, then bootstrapSearch becomes
irrelevant.

An enhancement to refill is that it will let insertNode review its whole list
of nodes and then let it insert nodes up to SEARCH_NODES nodes. The previous
method would not garantee this behavior since, most of the times, it would pass
less than SEARCH_NODES nodes to insertNode.
2016-08-06 21:14:17 -04:00
Adrien Béraud a1eaf2e83c Merge pull request #107 from sim590/minor-search-refactor
dht: more accurate name for requested nodes count
2016-08-05 23:03:25 -04:00
Simon Désaulniers a21d4d4adc queries: fix deserialization bug
Only the first two entries of the array would be accessed in a consistent way.
Therefor, only the two first field value index would be returned.
2016-08-05 21:20:58 -04:00
Simon Désaulniers f0a92d999c dht: more accurate name for requested nodes count
The number of currently requested nodes, formerly named currentGetRequests, was
renamed since it was not accurately describing the behavior. The number we are
counting is not the number of 'get' requests, but rather the number of nodes
being requested simultaneously.
2016-08-05 21:19:46 -04:00
Simon Désaulniers 28a3498a69 dht: fixing timing in SearchNode::canGet
When a 'get' request associated with a certain 'query' has been sent, we don't
want to send it again, i.e. we don't care if it's pending or not as soon as it
has been sent.
2016-08-05 21:17:58 -04:00
Simon Désaulniers 7eb5d892f1 search: isDone computes using Request interface
There's no need to compute with time since the network engine gives us the
information we need.
2016-08-05 21:17:11 -04:00
Simon Désaulniers f6cd79952c node_cache: fix bad condition in getCachedNodes 2016-08-05 13:07:14 -04:00
Adrien Béraud 9c1a0ae27f freenode: fix typo 2016-08-05 10:23:08 -04:00
Simon Désaulniers 29c1a955d0 readme: add freenode irc opendht channel 2016-08-04 18:33:56 -04:00
Nicolas b366432a8a Merge pull request #103 from sim590/sendlisten-loop
dht: fix sendListen loop bug
2016-08-04 10:25:22 -04:00
Simon Désaulniers af8bfdc1c1 dht: fix sendListen loop bug
Each time a 'listen' request is sent to the network engine, we track this
request in the upper layer with a map<shared_ptr<Query>, shared_ptr<Request>>.
At some point, this map has to be maintained or totally cleared. However, it was
done wrong, hence the sendListen loop. Clearing a pair <Query, Request> has to
be done when the API user cancels a 'listen' operation.
2016-08-03 18:49:37 -04:00
Simon Désaulniers 88040ad467 dht: display debug info according to query impact 2016-08-03 18:49:10 -04:00
Simon Désaulniers a35e67bcdf Merge pull request #101 from kaldoran/optimize_search
dht: bootstrap from node cache instead of routing table
2016-08-03 15:31:07 -04:00
kaldoran df3317a5b2 dht: bootstrap from cache instead of routing table 2016-08-03 10:04:02 -04:00
kaldoran 33f95c00a9 NodeCache: getNode takes bool not int
Since this was old code which use int as bool I edit that for a bool [and change related code]
2016-08-02 18:57:20 -04:00
Adrien Béraud 7383505dcc value: increase max value size to 16KiB 2016-08-01 10:47:21 -04:00
Adrien Béraud 2c9a29af0e docker: add python, lto, msgpack 2.0 2016-08-01 01:18:37 -04:00
Adrien Béraud 5847273b79 travis: add llvm docker build 2016-07-29 21:37:43 -04:00
Adrien Béraud 98204991ec travis with docker 2016-07-29 21:37:43 -04:00
Adrien Béraud b8e10bfe15 const shared_ptr 2016-07-29 21:37:07 -04:00
Adrien Béraud 132fe66699 dhtnode: cleanup 2016-07-29 15:49:43 -04:00
Adrien Béraud a28fc4dfb1 tools: remove optional arguments 2016-07-29 15:39:50 -04:00
Nicolas 7721aa5643 api: Add value creation timepoint (#97) 2016-07-28 17:03:11 -04:00
Nicolas 68707aff17 dht: prevent outdated store of value 2016-07-28 16:58:04 -04:00
Adrien Béraud 3ecbc9adff Merge pull request #95 from sim590/consistent-so-versionning
autotools: versionning consistent with CMake
2016-07-25 17:09:56 -04:00
Simon Désaulniers b5a7a0ca31 autotools: versionning consistent with CMake 2016-07-25 17:03:57 -04:00
Nicolas 2362db8528 Merge pull request #94 from sim590/storage-unique-ptr
dht: make main store a vector<unique_ptr<Storage>>
2016-07-22 17:02:21 -04:00
Simon Désaulniers 62835bdc54 dht: make main store a vector<unique_ptr<Storage>>
Since the elements inside are going to be moved constantly during the life of
the node, this design is better. Also, it works around a crash when the store is
resized (elements inside moved) at some point (always happenned the 3rd time)
for some reason. This bug was known when compiled with LLVM >7.3.0 (>clang-703.0.31).
2016-07-22 16:57:46 -04:00
Nicolas fe1cf209f1 Merge pull request #93 from sim590/select-consistency
dht: return consistent query from local storage
2016-07-19 16:47:44 -04:00
Simon Désaulniers 2f72563b1f dht: return consistent query from local storage
When querying from local storage with SELECT f, a FieldValueIndex with empty
fields was returned without considering the SELECT statement requiring only a
field "f".
2016-07-19 15:52:21 -04:00
Simon Désaulniers 0d754d6ca8 doc: clarify dhtnode usage 2016-07-19 14:00:34 -04:00
Simon Désaulniers f474f6499b value: missing return, errors on non-gcc
Gcc understands the syntax without return value, but this confuses other
compilers.
2016-07-18 14:18:37 -04:00
Adrien Béraud 97baacf609 Merge pull request #79 from sim590/queries
[DHT] Queries: remote values filtering
2016-07-11 20:23:15 +02:00
Simon Désaulniers 0fa8cfdb71 tools: enable queries in dhtnode 2016-07-10 19:26:13 +02:00
Simon Désaulniers 78c7cae7e9 dhtrunner: add query in dhtrunner API 2016-07-10 19:26:13 +02:00
Simon Désaulniers a4834efd37 dht: use queries in dht 2016-07-10 19:26:13 +02:00
Simon Désaulniers 07e4435a07 value: add Query relevant structures 2016-07-10 19:26:04 +02:00
zorun 9f93771771 doc: Fix install path of man page (#90)
Man pages go in /usr/share/man

  http://www.pathname.com/fhs/pub/fhs-2.3.html#USRSHAREMANMANUALPAGES
2016-07-02 14:32:43 +02:00
Simon Désaulniers a533807fcf doc: add missing CMakeLists.txt 2016-07-02 01:20:46 +02:00
Simon Désaulniers 49129ec1b2 tools: specify optional arg syntax -o[ARG] 2016-06-30 01:33:14 +02:00
Simon Désaulniers 803354552f build-tools: distribute dhtnode.1 manpage 2016-06-30 00:58:04 +02:00
Simon Désaulniers fa6c365679 doc: fix typos in dhtnode manpage 2016-06-29 20:57:30 +02:00
Adrien Béraud 6ac1ae3527 Merge pull request #84 from sim590/dhtnode-user-experience
[dhtnode] user experience
2016-06-28 14:55:27 -04:00
Simon Désaulniers 29834b714e dhtnode: manpage and add all options in help text 2016-06-28 18:51:40 +02:00
Simon Désaulniers bba27adf4d dhtnode: fix getopt optional arg parsing 2016-06-27 21:14:54 +02:00
Simon Désaulniers e3a280d7a9 Merge pull request #82 from aviau/typos
fixed typos
2016-06-27 19:46:17 +02:00
aviau 63f1a736f4 fixed typos 2016-06-27 19:33:52 +02:00
Simon Désaulniers 0f8720c433 Merge pull request #80 from aviau/powerful
readme: fix typo s/powerfull/powerful/
2016-06-27 15:39:55 +02:00
aviau 7a6263b940 typo: powerfull ->powerful 2016-06-27 15:29:35 +02:00
Adrien Béraud b09e3df2e2 add network id to distinguish different networks 2016-06-21 03:06:47 -04:00
Adrien Béraud 041a9e0e7f Clarify GPLv3 "or any later version" licence 2016-06-20 11:47:21 -04:00
235 changed files with 42249 additions and 13724 deletions

No files matched your search

+99
View File
@@ -0,0 +1,99 @@
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignEscapedNewlines: DontAlign
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- forever # avoids { wrapped to next line
- foreach
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 150
PenaltyBreakBeforeFirstCallParameter: 300
PenaltyBreakComment: 500
PenaltyBreakFirstLessLess: 400
PenaltyBreakString: 600
PenaltyExcessCharacter: 50
PenaltyReturnTypeOnItsOwnLine: 300
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++17
TabWidth: 4
UseTab: Never
+1
View File
@@ -0,0 +1 @@
Checks: '-*,clang-diagnostic-*,performance-*,bugprone-*,llvm-*,clang-analyzer-*,misc-*,-llvm-namespace-comment,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-llvm-header-guard,-llvm-include-order,-bugprone-suspicious-string-compare'
+15
View File
@@ -0,0 +1,15 @@
{
"name": "C++",
"build": {
"dockerfile": "../docker/DockerfileDepsLlvm",
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools"
]
}
},
"forwardPorts": [4222],
}
+1
View File
@@ -0,0 +1 @@
custom: ['https://jami.net/donate/']
+22
View File
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: "docker"
directory: "/docker"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "vcpkg"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "cargo"
directory: "/rust"
schedule:
interval: "weekly"
+177
View File
@@ -0,0 +1,177 @@
name: C/C++ CI
env:
LLHTTP_VERSION: "v9.2.1"
RESTINIO_VERSION: "0.7.8.1"
EXPECTED_LITE_URL: "https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp"
UBUNTU_FULL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
UBUNTU_MESON_DEPS: "ninja-build libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-dev python3-setuptools python3-pip libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
UBUNTU_MINIMAL_DEPS: "libncurses5-dev libreadline-dev nettle-dev libfmt-dev libgnutls28-dev libcppunit-dev libmsgpack-dev libargon2-dev"
DEBIAN12_DEPS: "git libtool pkg-config wget cmake libncurses5-dev libreadline-dev nettle-dev libasio-dev libgnutls28-dev libuv1-dev python3-pip python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev libfmt-dev libmsgpack-dev libargon2-dev"
on: [push, pull_request]
jobs:
build-ubuntu-meson:
name: Ubuntu/GCC Meson build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Dependencies
run: |
echo "Installing Ubuntu meson dependencies:"
sudo apt update
sudo apt install -y $UBUNTU_MESON_DEPS
- name: Install Python dependencies
run: sudo pip3 install meson Cython
- name: Configure with Meson
run: meson setup build .
- name: Build with Ninja
run: cd build && ninja
build-ubuntu-minimal:
name: Ubuntu/GCC minimal build
runs-on: ubuntu-latest
strategy:
matrix:
cxx_standard: [17, 20, 23]
steps:
- uses: actions/checkout@v6
- name: Install Minimal Dependencies
run: |
echo "Installing Ubuntu minimal dependencies:"
sudo apt-get update
sudo apt-get install -y $UBUNTU_MINIMAL_DEPS
- name: Configure project with CMake
run: |
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
-DOPENDHT_C=Off -DBUILD_TESTING=On \
-DOPENDHT_PEER_DISCOVERY=Off -DOPENDHT_PYTHON=Off \
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=Off -DOPENDHT_PROXY_CLIENT=Off
- name: Build
run: cd build && make
- name: Run Unit tests
run: ctest --output-on-failure --test-dir build
build-debian12:
name: Debian 12/GCC build
runs-on: ubuntu-latest
container:
image: debian:12
volumes:
- .:/workspace
options: --workdir /workspace
env:
DEBIAN_FRONTEND: noninteractive
steps:
- uses: actions/checkout@v6
- name: Install Dependencies
run: |
apt-get update
apt-get install -y $DEBIAN12_DEPS
- name: Build llhttp dependency
run: |
mkdir llhttp
wget "https://github.com/nodejs/llhttp/archive/refs/tags/release/${LLHTTP_VERSION}.tar.gz" -O llhttp.tar.gz
tar -xzf llhttp.tar.gz -C llhttp --strip-components=1
cd llhttp && cmake -DCMAKE_INSTALL_PREFIX=/usr . && make -j2 && make install
cd ../ && rm -rf llhttp*
- name: Install expected-lite header
run: |
mkdir -p /usr/local/include/nonstd
wget "${EXPECTED_LITE_URL}" -O /usr/local/include/nonstd/expected.hpp
- name: Build restinio dependency
run: |
mkdir restinio && cd restinio
wget "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2"
tar -xjf restinio-${RESTINIO_VERSION}.tar.bz2
cd restinio-${RESTINIO_VERSION}/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr/local \
-DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off \
-DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
make install
cd ../../ && rm -rf restinio*
- name: Configure project with CMake
run: |
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug \
-DOPENDHT_C=On -DBUILD_TESTING=On \
-DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off \
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On
- name: Build
run: cd build && make
build-macos:
name: macOS/Clang build
runs-on: macos-15
strategy:
matrix:
cxx_standard: [17, 20, 23]
steps:
- uses: actions/checkout@v6
- name: Install Homebrew Dependencies
run: brew install msgpack-cxx asio gnutls nettle readline fmt jsoncpp argon2 openssl cppunit
- name: Install expected-lite header
run: |
sudo mkdir -p /usr/local/include/nonstd
sudo wget "${EXPECTED_LITE_URL}" -O /usr/local/include/nonstd/expected.hpp
- name: Build restinio dependency
run: |
mkdir restinio && cd restinio
wget "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2"
tar -xjf restinio-${RESTINIO_VERSION}.tar.bz2
cd restinio-${RESTINIO_VERSION}/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr/local \
-DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off \
-DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
make -j2 && sudo make install
cd ../../ && rm -rf restinio*
- name: Configure project with CMake
run: |
mkdir build && cd build
# Set Homebrew OpenSSL paths
export PATH="/opt/homebrew/opt/openssl@3/bin:$PATH"
export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@3/include"
export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig"
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \
-DOPENDHT_DOWNLOAD_DEPS=ON \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
-DCMAKE_CXX_STANDARD_REQUIRED=ON \
-DOPENDHT_C=On -DBUILD_TESTING=On \
-DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off \
-DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
- name: Build
run: cd build && make
+42
View File
@@ -0,0 +1,42 @@
name: Clang Static Analysis
on: [push, pull_request]
jobs:
clang-analyzer:
name: Clang Static Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: deps
run: |
sudo apt update && \
sudo apt install libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
libfmt-dev libmsgpack-dev libargon2-dev libasio-dev \
llvm llvm-dev clang clang-tools && \
sudo apt remove gcc g++
- name: expected-lite
run: |
sudo mkdir /usr/include/nonstd
sudo wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
- name: restinio
run: |
mkdir restinio && cd restinio
wget https://github.com/Stiffstream/restinio/releases/download/v0.7.8.1/restinio-0.7.8.1.tar.bz2
ls -l && tar -xjf restinio-0.7.8.1.tar.bz2
cd restinio-0.7.8.1/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
make -j2 && sudo make install
cd ../../ && rm -rf restinio*
- name: cmake
run: |
mkdir build && cd build && \
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DOPENDHT_C=On -DOPENDHT_DOWNLOAD_DEPS=ON -DOPENDHT_PEER_DISCOVERY=On -DOPENDHT_PYTHON=Off -DOPENDHT_TOOLS=On -DOPENDHT_PROXY_SERVER=On -DOPENDHT_PROXY_CLIENT=On -DOPENDHT_PUSH_NOTIFICATIONS=On
- name: scan-build
run: cd build && scan-build --status-bugs make
+41
View File
@@ -0,0 +1,41 @@
name: "CodeQL Advanced"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: 'ubuntu-latest'
permissions:
security-events: write
packages: read
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: c-cpp
build-mode: autobuild
- language: actions
build-mode: none
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
+108
View File
@@ -0,0 +1,108 @@
name: Python Package
permissions:
contents: read
on:
release:
types: [published]
push:
pull_request:
workflow_dispatch:
jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest]
steps:
- uses: actions/checkout@v6
# Run locally with: pipx run cibuildwheel --platform linux python
- name: Build wheels
uses: pypa/cibuildwheel@v3.4.0
with:
package-dir: python
- uses: actions/upload-artifact@v6
with:
name: opendht-wheels-${{ matrix.os }}
path: ./wheelhouse/*.whl
build_wheels_windows:
name: Build wheels on Windows
runs-on: windows-latest
env:
VCPKG_VERSION: "2025.07.25"
VCPKG_INSTALLATION_ROOT: "C:\\vcpkg"
VCPKG_DISABLE_METRICS: "1"
VCPKG_DEFAULT_TRIPLET: x64-windows-release
VCPKG_INSTALLED_DIR: ${{ github.workspace }}\vcpkg_installed
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}\vcpkg_binary_cache
steps:
- uses: actions/checkout@v6
- name: Cache vcpkg installed packages
id: cache-vcpkg
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ env.VCPKG_DEFAULT_TRIPLET }}-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}-${{ hashFiles('.github/workflows/windows-build.yml') }}
- name: Setup vcpkg and install dependencies
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
run: |
New-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}" -ItemType Directory -Force
New-Item -Path "${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" -ItemType Directory -Force
vcpkg install `
--recurse `
--clean-after-build `
--triplet=${{ env.VCPKG_DEFAULT_TRIPLET }} `
--x-install-root=${{ env.VCPKG_INSTALLED_DIR }}
shell: pwsh
- name: Build wheels
run: |
pip install cython delvewheel build
cmake -S . -B build `
-DCMAKE_BUILD_TYPE=Release `
-DVCPKG_TARGET_TRIPLET=${{ env.VCPKG_DEFAULT_TRIPLET }} `
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_INSTALLATION_ROOT }}\scripts\buildsystems\vcpkg.cmake `
-DVCPKG_INSTALLED_DIR=${{ env.VCPKG_INSTALLED_DIR }} `
-DBUILD_TESTING=OFF `
-DOPENDHT_C=OFF `
-DOPENDHT_TOOLS=OFF `
-DOPENDHT_PYTHON=ON `
-DOPENDHT_DOCUMENTATION=OFF `
-DOPENDHT_PROXY_CLIENT=ON `
-DOPENDHT_PROXY_SERVER=ON
cd build
pipx run cibuildwheel python
shell: pwsh
- uses: actions/upload-artifact@v6
with:
name: opendht-wheels-win_amd64
path: ./build/wheelhouse/*.whl
publish:
runs-on: ubuntu-latest
needs: [build_wheels, build_wheels_windows]
steps:
- uses: actions/download-artifact@v7
with:
pattern: opendht-wheels-*
path: dist
merge-multiple: true
- name: Publish package
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
+523
View File
@@ -0,0 +1,523 @@
name: Release actions
on:
push:
tags:
- 'v*'
env:
REGISTRY: ghcr.io
IMAGE_NAME_DEPS: ${{ github.repository }}/opendht-deps
IMAGE_NAME: ${{ github.repository }}/opendht
IMAGE_NAME_DEPS_LLVM: ${{ github.repository }}/opendht-deps-llvm
IMAGE_NAME_LLVM: ${{ github.repository }}/opendht-llvm
IMAGE_NAME_DHTNODE: ${{ github.repository }}/dhtnode
IMAGE_NAME_ALPINE: ${{ github.repository }}/opendht-alpine
IMAGE_NAME_ALPINE_DEPS: ${{ github.repository }}/opendht-deps-alpine
jobs:
build-and-push-deps-image:
name: Dependency Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileDeps
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image:
name: OpenDHT Docker image
runs-on: ubuntu-latest
needs: build-and-push-deps-image
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-deps-image-llvm:
name: Dependency Docker image (LLVM)
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DEPS_LLVM }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileDepsLlvm
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-llvm:
name: OpenDHT Docker image (LLVM)
runs-on: ubuntu-latest
needs: build-and-push-deps-image-llvm
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LLVM }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileLlvm
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-dhtnode:
name: dhtnode Docker image
runs-on: ubuntu-latest
needs: build-and-push-image
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_DHTNODE }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileDhtnode
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-alpine-deps:
name: Alpine Deps Docker image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE_DEPS }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileDepsAlpine
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-and-push-image-alpine:
name: Alpine Docker image
runs-on: ubuntu-latest
needs: build-and-push-image-alpine-deps
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME_ALPINE }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/DockerfileAlpine
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-windows-msi:
name: Build Windows MSI Installer
runs-on: windows-latest
env:
VCPKG_VERSION: "2025.07.25"
VCPKG_INSTALLATION_ROOT: "C:\\vcpkg"
VCPKG_DISABLE_METRICS: "1"
VCPKG_DEFAULT_TRIPLET: x64-windows
VCPKG_INSTALLED_DIR: ${{ github.workspace }}\vcpkg_installed
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}\vcpkg_binary_cache
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up MSVC developer environment
uses: microsoft/setup-msbuild@v2
- name: Install WIX using .net tools
run: |
dotnet tool install --global wix --version 6.0.1
wix extension add --global WixToolset.UI.wixext/6.0.1
shell: pwsh
- name: Cache vcpkg installed packages
id: cache-vcpkg
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-x64-shared-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}-${{ hashFiles('.github/workflows/windows-build.yml') }}
- name: Setup vcpkg and install dependencies
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
run: |
New-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}" -ItemType Directory -Force
New-Item -Path "${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" -ItemType Directory -Force
vcpkg install `
--recurse `
--clean-after-build `
--triplet=x64-windows `
--x-install-root=${{ env.VCPKG_INSTALLED_DIR }} `
--x-feature=test
shell: pwsh
- name: Configure CMake for MSI
shell: pwsh
run: |
mkdir build -ErrorAction SilentlyContinue
cmake -B build `
-S . `
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake `
-DVCPKG_TARGET_TRIPLET=x64-windows `
-DVCPKG_INSTALLED_DIR=${{ env.VCPKG_INSTALLED_DIR }} `
-DVCPKG_MANIFEST_FEATURES=test `
-DCMAKE_BUILD_TYPE=Release `
-DOPENDHT_C=On `
-DOPENDHT_TOOLS=On `
-DOPENDHT_PYTHON=Off `
-DOPENDHT_DOCUMENTATION=OFF `
-DOPENDHT_PEER_DISCOVERY=On `
-DOPENDHT_PROXY_SERVER=On `
-DOPENDHT_PROXY_CLIENT=On `
-DOPENDHT_HTTP=On `
-DBUILD_TESTING=Off `
-DOPENDHT_CPACK=On `
-A x64
- name: Build with MSVC
shell: pwsh
run: |
cmake --build build --config Release --parallel $([System.Environment]::ProcessorCount)
# Copy vcpkg installed libraries to the build directory
Copy-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}\x64-windows\lib\*.lib" -Destination "build" -Force
Copy-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}\x64-windows\bin\*.dll" -Destination "build" -Force
- name: Package MSI with CPack
shell: pwsh
id: cpack_msi
run: |
cd build
cpack -C Release -G WIX
$msiFile = Get-ChildItem -Path . -Recurse -Filter *.msi | Select-Object -First 1
if ($msiFile) {
$msiOutputPath = "opendht-installer.msi" # Standardized artifact name
Copy-Item $msiFile.FullName -Destination $msiOutputPath
echo "msi_path=$msiOutputPath" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
Write-Host "MSI created at build/$msiOutputPath"
} else {
Write-Error "MSI file not found after cpack execution!"
exit 1
}
- name: Upload MSI Artifact
uses: actions/upload-artifact@v6
with:
name: opendht-windows-msi
path: build/${{ steps.cpack_msi.outputs.msi_path }} # Path to the MSI in the build directory
retention-days: 7
build-windows-dhtnode:
name: Build Windows dhtnode
runs-on: windows-latest
env:
VCPKG_VERSION: "2025.07.25"
VCPKG_INSTALLATION_ROOT: "C:\\vcpkg"
VCPKG_DISABLE_METRICS: "1"
VCPKG_DEFAULT_TRIPLET: x64-windows-static-release
VCPKG_INSTALLED_DIR: ${{ github.workspace }}\vcpkg_installed
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}\vcpkg_binary_cache
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up MSVC developer environment
uses: microsoft/setup-msbuild@v2
- name: Cache vcpkg static installed packages
id: cache-vcpkg-static
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-x64-static-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}-${{ hashFiles('.github/workflows/windows-build.yml') }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-x64-static-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-x64-static-
- name: Setup vcpkg and install static dependencies
if: steps.cache-vcpkg-static.outputs.cache-hit != 'true'
shell: pwsh
run: |
New-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}" -ItemType Directory -Force
New-Item -Path "${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" -ItemType Directory -Force
vcpkg install `
--recurse `
--clean-after-build `
--triplet=x64-windows-static-release `
--x-install-root=${{ env.VCPKG_INSTALLED_DIR }} `
--x-feature=test
- name: Configure CMake for Static Build
shell: pwsh
run: |
mkdir build_static -ErrorAction SilentlyContinue
cmake -B build_static `
-S . `
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake `
-DVCPKG_TARGET_TRIPLET=x64-windows-static-release `
-DVCPKG_INSTALLED_DIR=${{ env.VCPKG_INSTALLED_DIR }} `
-DVCPKG_MANIFEST_FEATURES=test `
-DCMAKE_BUILD_TYPE=Release `
-DBUILD_SHARED_LIBS=OFF `
-DOPENDHT_PROXY_CLIENT=ON `
-DOPENDHT_PROXY_SERVER=ON `
-DOPENDHT_C=ON `
-DOPENDHT_TOOLS=ON `
-DOPENDHT_DOCUMENTATION=OFF `
-DOPENDHT_PYTHON=OFF `
-DOPENDHT_PEER_DISCOVERY=ON `
-DOPENDHT_HTTP=ON `
-A x64
- name: Build Static dhtnode
shell: pwsh
run: |
cmake --build build_static --config Release --parallel $([System.Environment]::ProcessorCount)
- name: Upload Static dhtnode Artifact
uses: actions/upload-artifact@v6
with:
name: opendht-windows-dhtnode
path: |
build_static/**/*dhtnode.exe
retention-days: 7
create-github-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [build-windows-msi, build-windows-dhtnode]
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Download Windows MSI artifact
uses: actions/download-artifact@v7
with:
name: opendht-windows-msi
path: downloaded_artifacts/windows_msi
- name: Download Static dhtnode artifact
uses: actions/download-artifact@v7
with:
name: opendht-windows-dhtnode
path: downloaded_artifacts/static_dhtnode
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2
with:
draft: true
files: |
downloaded_artifacts/windows_msi/*.msi
downloaded_artifacts/static_dhtnode/**/*dhtnode.exe
+385
View File
@@ -0,0 +1,385 @@
name: Windows Build
permissions:
contents: read
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
env:
VCPKG_VERSION: "2026.01.16"
VCPKG_INSTALLATION_ROOT: "C:\\vcpkg"
VCPKG_DISABLE_METRICS: "1"
VCPKG_INSTALLED_DIR: ${{ github.workspace }}\vcpkg_installed
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}\vcpkg_binary_cache
jobs:
prepare-dependencies:
name: Prepare Windows Dependencies
runs-on: windows-latest
outputs:
vcpkg_cache_key: ${{ steps.generate_cache_key.outputs.key }}
strategy:
matrix:
arch: [x64]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up MSVC
uses: microsoft/setup-msbuild@v2
- name: Generate Cache Key
id: generate_cache_key
shell: pwsh
run: |
$key_value = "${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-shared-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}-${{ hashFiles('.github/workflows/windows-build.yml') }}"
echo "key=$key_value" >> $env:GITHUB_OUTPUT
- name: Cache vcpkg installed packages
id: cache-vcpkg
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ steps.generate_cache_key.outputs.key }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-shared-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-shared-
- name: Setup vcpkg and install dependencies
if: steps.cache-vcpkg.outputs.cache-hit != 'true'
run: |
New-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}" -ItemType Directory -Force
New-Item -Path "${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" -ItemType Directory -Force
vcpkg install `
--recurse `
--clean-after-build `
--triplet=${{ matrix.arch }}-windows `
--x-install-root=${{ env.VCPKG_INSTALLED_DIR }} `
--x-feature=test
shell: pwsh
prepare-static-dependencies:
name: Prepare Windows Static Dependencies
runs-on: windows-latest
outputs:
vcpkg_static_cache_key: ${{ steps.generate_static_cache_key.outputs.key }}
strategy:
matrix:
arch: [x64]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up MSVC
uses: microsoft/setup-msbuild@v2
- name: Generate Cache Key for Static Libs
id: generate_static_cache_key
shell: pwsh
run: |
$key_value = "${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-static-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}-${{ hashFiles('.github/workflows/windows-build.yml') }}"
echo "key=$key_value" >> $env:GITHUB_OUTPUT
- name: Cache vcpkg static installed packages
id: cache-vcpkg-static
uses: actions/cache@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ steps.generate_static_cache_key.outputs.key }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-static-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-static-
- name: Setup vcpkg and install static dependencies
if: steps.cache-vcpkg-static.outputs.cache-hit != 'true'
shell: pwsh
run: |
New-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}" -ItemType Directory -Force
New-Item -Path "${{ env.VCPKG_DEFAULT_BINARY_CACHE }}" -ItemType Directory -Force
vcpkg install `
--recurse `
--clean-after-build `
--triplet=${{ matrix.arch }}-windows-static-release `
--x-install-root=${{ env.VCPKG_INSTALLED_DIR }} `
--x-feature=test
build-windows:
name: Windows MSVC Build
runs-on: windows-latest
needs: prepare-dependencies
strategy:
matrix:
build_type: [Debug, Release]
arch: [x64]
cxx_standard: [17, 20, 23]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up MSVC
uses: microsoft/setup-msbuild@v2
- name: Restore vcpkg installed packages
id: cache-vcpkg-restore
uses: actions/cache/restore@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ needs.prepare-dependencies.outputs.vcpkg_cache_key }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-shared-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-shared-
- name: Configure CMake
shell: pwsh
run: |
mkdir build -ErrorAction SilentlyContinue
cmake -B build `
-S . `
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake `
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows `
-DVCPKG_INSTALLED_DIR=${{ env.VCPKG_INSTALLED_DIR }} `
-DVCPKG_MANIFEST_FEATURES=test `
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} `
-DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} `
-DCMAKE_CXX_STANDARD_REQUIRED=ON `
-DBUILD_TESTING=ON `
-DOPENDHT_PROXY_CLIENT=ON `
-DOPENDHT_PROXY_SERVER=ON `
-DOPENDHT_C=ON `
-DOPENDHT_TOOLS=ON `
-DOPENDHT_PYTHON=OFF `
-DOPENDHT_DOCUMENTATION=OFF `
-DOPENDHT_PEER_DISCOVERY=ON `
-DOPENDHT_HTTP=ON `
-A ${{ matrix.arch }}
- name: Build
run: |
cmake --build build --config ${{ matrix.build_type }} --parallel 4
# Copy vcpkg installed libraries to the build directory
Copy-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}\${{ matrix.arch }}-windows\lib\*.lib" -Destination "build" -Force
Copy-Item -Path "${{ env.VCPKG_INSTALLED_DIR }}\${{ matrix.arch }}-windows\bin\*.dll" -Destination "build" -Force
- name: Test
if: matrix.build_type == 'Release'
run: |
cd build
ctest --build-config ${{ matrix.build_type }} --output-on-failure --parallel 4
- name: Upload build artifacts
if: matrix.build_type == 'Release'
uses: actions/upload-artifact@v6
with:
name: opendht-windows-${{ matrix.arch }}-cxx${{ matrix.cxx_standard }}-${{ matrix.build_type }}
path: |
build/**/*.exe
build/**/*.dll
build/**/*.lib
retention-days: 7
build-windows-static:
name: Windows Static MSVC Build
runs-on: windows-latest
needs: prepare-static-dependencies
strategy:
matrix:
build_type: [Release]
arch: [x64]
cxx_standard: [17, 20, 23]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up MSVC
uses: microsoft/setup-msbuild@v2
- name: Restore vcpkg static installed packages
id: cache-vcpkg-static-restore
uses: actions/cache/restore@v5
with:
path: |
${{ env.VCPKG_INSTALLED_DIR }}
${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
key: ${{ needs.prepare-static-dependencies.outputs.vcpkg_static_cache_key }}
restore-keys: |
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-static-${{ hashFiles('**/vcpkg.json', '**/vcpkg-configuration.json') }}
${{ runner.os }}-vcpkg-${{ env.VCPKG_VERSION }}-${{ matrix.arch }}-static-
- name: Configure CMake for Static Build
shell: pwsh
run: |
mkdir build -ErrorAction SilentlyContinue
cmake -B build `
-S . `
-DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake `
-DVCPKG_TARGET_TRIPLET=${{ matrix.arch }}-windows-static-release `
-DVCPKG_INSTALLED_DIR=${{ env.VCPKG_INSTALLED_DIR }} `
-DVCPKG_MANIFEST_FEATURES=test `
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} `
-DCMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} `
-DCMAKE_CXX_STANDARD_REQUIRED=ON `
-DBUILD_SHARED_LIBS=OFF `
-DBUILD_TESTING=ON `
-DOPENDHT_PROXY_CLIENT=ON `
-DOPENDHT_PROXY_SERVER=ON `
-DOPENDHT_C=ON `
-DOPENDHT_TOOLS=ON `
-DOPENDHT_PYTHON=OFF `
-DOPENDHT_DOCUMENTATION=OFF `
-DOPENDHT_PEER_DISCOVERY=ON `
-DOPENDHT_HTTP=ON `
-A ${{ matrix.arch }}
- name: Build Static
shell: pwsh
run: |
cmake --build build --config ${{ matrix.build_type }} --parallel 4
- name: Test Static Build
shell: pwsh
run: |
cd build
ctest --build-config ${{ matrix.build_type }} --output-on-failure --parallel 4
- name: Upload static build artifacts
uses: actions/upload-artifact@v6
with:
name: opendht-windows-static-${{ matrix.arch }}-cxx${{ matrix.cxx_standard }}-${{ matrix.build_type }}
path: |
build/**/*.exe
build/**/*.lib
retention-days: 7
build-windows-mingw:
name: Windows MinGW Build
runs-on: windows-latest
strategy:
matrix:
build_type: [Release]
#build_type: [Debug, Release]
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup MinGW
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-gcc
mingw-w64-x86_64-cmake
mingw-w64-x86_64-make
mingw-w64-x86_64-ninja
mingw-w64-x86_64-pkg-config
mingw-w64-x86_64-cppunit
mingw-w64-x86_64-readline
mingw-w64-x86_64-ncurses
mingw-w64-x86_64-gnutls
mingw-w64-x86_64-nettle
mingw-w64-x86_64-jsoncpp
mingw-w64-x86_64-fmt
mingw-w64-x86_64-asio
mingw-w64-x86_64-argon2
mingw-w64-x86_64-openssl
mingw-w64-clang-x86_64-msgpack-cxx
- name: Prepare dependencies from source (expected-lite, llhttp, restinio)
shell: msys2 {0}
env:
LLHTTP_VERSION: "v9.2.1"
RESTINIO_VERSION: "0.7.6"
EXPECTED_LITE_URL: "https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp"
run: |
MSYS2_SYSROOT=$(cygpath -u "$MSYSTEM_PREFIX")
# Install expected-lite header
mkdir -p ${MSYS2_SYSROOT}/include/nonstd
curl -L "${EXPECTED_LITE_URL}" -o ${MSYS2_SYSROOT}/include/nonstd/expected.hpp
# Build and install llhttp
mkdir llhttp
curl -L "https://github.com/nodejs/llhttp/archive/refs/tags/release/${LLHTTP_VERSION}.tar.gz" -o llhttp.tar.gz
tar -xzf llhttp.tar.gz -C llhttp --strip-components=1
cd llhttp
cmake -G "MinGW Makefiles" \
-DCMAKE_INSTALL_PREFIX=${MSYS2_SYSROOT} \
-DCMAKE_BUILD_TYPE=Release .
cmake --build . --parallel 2
cmake --install .
cd ..
rm -rf llhttp*
# Build and install restinio
mkdir restinio && cd restinio
curl -L "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2" -o restinio.tar.bz2
tar -xjf restinio.tar.bz2
cd restinio-${RESTINIO_VERSION}/dev
cmake -G "MinGW Makefiles" \
-DCMAKE_INSTALL_PREFIX=${MSYS2_SYSROOT} \
-DCMAKE_BUILD_TYPE=Release \
-DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off \
-DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
cmake --install .
cd ../../..
rm -rf restinio*
# Copy msgpack-cxx headers
mkdir -p ${MSYS2_SYSROOT}/include/msgpack
cp -r /clang64/include/msgpack/* ${MSYS2_SYSROOT}/include/msgpack/
cp /clang64/include/msgpack.hpp ${MSYS2_SYSROOT}/include/msgpack.hpp
- name: Build with MinGW
shell: msys2 {0}
run: |
mkdir build_mingw
cd build_mingw
cmake .. \
-G "MinGW Makefiles" \
-DHAVE_MSGPACKCXX=ON \
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-DBUILD_TESTING=ON \
-DOPENDHT_PROXY_CLIENT=ON \
-DOPENDHT_PROXY_SERVER=ON \
-DOPENDHT_C=ON \
-DOPENDHT_TOOLS=ON \
-DOPENDHT_PYTHON=OFF \
-DOPENDHT_DOCUMENTATION=OFF \
-DOPENDHT_PEER_DISCOVERY=ON \
-DOPENDHT_HTTP=ON
cmake --build . --parallel 4
#- name: Test MinGW Build
# shell: msys2 {0}
# run: |
# cd build_mingw
# ctest --output-on-failure --parallel 4
- name: Upload MinGW artifacts
if: matrix.build_type == 'Release'
uses: actions/upload-artifact@v6
with:
name: opendht-windows-mingw-${{ matrix.build_type }}
path: |
build_mingw/**/*.exe
build_mingw/**/*.dll
build_mingw/**/*.a
retention-days: 7
+47 -23
View File
@@ -19,29 +19,53 @@
*.exe
*.out
*.app
**/dhtnode
**/dhtchat
**/dhtscanner
# Autotools
/ac
Makefile
Makefile.in
/aclocal.m4
/autom4te.cache/
/config.*
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/m4/
/missing
/stamp-h?
.deps/
.dirstamp
.libs/
*.l[ao]
*~
# CMake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
*ConfigVersion.cmake
*.pc
# KDevelop
.kdev4/
*.kdev4
# VSCode
.vscode/*
# Visual Studio
.vs/
CMakeSettings.json
# Eclipse CDT
.cproject
.project
language.settings.xml
# Python
*.pyc
*.stamp
python/opendht.cpp
python/setup.py
python/dist/
wheelhouse/
*.egg-info/
# Doxygen
doc/Doxyfile
# git backup files
*.orig
# vim swap files
*.swp
*.swo
# build dir
build
build_dev
.DS_Store
build-*/
install/
vcpkg_installed/
-44
View File
@@ -1,44 +0,0 @@
sudo: false
services:
- docker
language: cpp
compiler:
- gcc
- clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-6
- g++-6
- libgnutls28-dev
- cmake
before_install:
- if [ $TRAVIS_OS_NAME == linux ] && [ $CXX == g++ ]; then export CXX=/usr/bin/g++-6 && export CC=/usr/bin/gcc-6; fi
- if [ $TRAVIS_OS_NAME == linux ]; then git clone https://github.com/msgpack/msgpack-c.git; fi
- if [ $TRAVIS_OS_NAME == linux ]; then cd msgpack-c && git checkout cpp-1.2.0 && mkdir build && mkdir -p $HOME/usr && cd build; fi
- if [ $TRAVIS_OS_NAME == linux ]; then cmake -DCMAKE_INSTALL_PREFIX=$HOME/usr -DMSGPACK_CXX11=ON -DMSGPACK_BUILD_EXAMPLES=OFF .. && make -j && make install && cd ../.. && pwd; fi
- if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install llvm36 && brew install msgpack && brew install gnutls && brew link --force llvm36; fi
before_script:
- if [ $TRAVIS_OS_NAME == linux ]; then travis_retry ./autogen.sh && ./configure --prefix=$HOME/usr; fi
- if [ $TRAVIS_OS_NAME == osx ]; then travis_retry ./autogen.sh && ./configure; fi
script:
- make -j
notifications:
email:
- adrien.beraud@savoirfairelinux.com
env:
- LANG="en_US.UTF-8"
os:
- osx
+54
View File
@@ -0,0 +1,54 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "dhtnode",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/tools/dhtnode",
"args": ["-v", "-p", "4222"],
"cwd": "${workspaceFolder}/build",
"environment": [],
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"linux": {
"MIMode": "gdb",
"externalConsole": false,
},
"osx": {
"MIMode": "lldb",
"externalConsole": true,
},
},
{
"name": "tests",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/opendht_unit_tests",
"cwd": "${workspaceFolder}/build",
"environment": [],
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "build",
"linux": {
"MIMode": "gdb",
"externalConsole": false,
},
"osx": {
"MIMode": "lldb",
"externalConsole": true,
},
}
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++17",
"C_Cpp.default.cStandard": "c11",
"C_Cpp.autoAddFileAssociations": false,
"cmake.configureOnOpen": false,
"cmake.configureOnEdit": false,
"editor.formatOnSave": true,
"files.eol": "\n",
}
+46
View File
@@ -0,0 +1,46 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/build"
},
"command": "make",
"args": ["-j4"],
"dependsOn": "cmake"
},
{
"label": "cmake",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/build"
},
"command": "cmake",
"args": [
"${workspaceRoot}",
"-DCMAKE_EXPORT_COMPILE_COMMANDS=On",
"-DCMAKE_BUILD_TYPE=Debug",
"-DBUILD_TESTING=On",
"-DOPENDHT_SANITIZE=On",
"-DOPENDHT_PROXY_CLIENT=On",
"-DOPENDHT_PROXY_SERVER=On",
"-DOPENDHT_C=On"
],
"dependsOn": "builddir"
},
{
"label": "builddir",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}"
},
"command": "mkdir",
"args": [
"-p",
"${workspaceRoot}/build"
]
},
]
}
+74
View File
@@ -0,0 +1,74 @@
# OpenDHT – Agent Instructions
## Build
### Primary: CMake (C++17)
```sh
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -GNinja
ninja
```
### Common CMake options
| Option | Default | Purpose |
|--------|---------|---------|
| `OPENDHT_TOOLS` | ON | CLI tools (dhtnode, dhtchat, …) |
| `OPENDHT_C` | OFF | C language bindings |
| `OPENDHT_PYTHON` | OFF | Python 3 Cython bindings |
| `OPENDHT_PROXY_SERVER` | OFF | REST API proxy server (requires RESTinio + llhttp) |
| `OPENDHT_PROXY_CLIENT` | OFF | REST API proxy client |
| `OPENDHT_PEER_DISCOVERY` | OFF | Multicast local peer discovery |
| `OPENDHT_PUSH_NOTIFICATIONS` | OFF | Push notification support |
| `OPENDHT_SANITIZE` | OFF | AddressSanitizer + stack protector |
### Alternative: Meson (C++20)
```sh
meson setup build . && cd build && ninja
```
### Run tests
```sh
# Full suite
ctest --output-on-failure --test-dir build
# Single test executable
./build/test_testName
```
## dhtnode
The `dhtnode` CLI tool is a simple DHT node implementation using `DhtRunner`.
---
## Commit
After implementing a feature or fixing a bug, commit your changes in clean, atomic commits with descriptive messages with format:
`topic: short description`
If any test are added or modified, commit them separately before the fix (if any).
---
## Architecture
OpenDHT is a Kademlia-based DHT library. The implementation is layered:
```
DhtRunner (public API — thread-safe, manages lifecycle & I/O threads)
└── SecureDht (GnuTLS crypto: signing, encryption, identity)
└── Dht (core DHT logic: routing, storage, find/get/put operations)
└── NetworkEngine (raw UDP sockets, message parsing, IPv4/IPv6)
```
- **`DhtRunner`** (`include/opendht/dhtrunner.h`, `src/dhtrunner.cpp`) — entry point for all users of the library. Wraps everything in a thread-pool and exposes async callbacks as well as blocking calls.
- **`Dht`** (`include/opendht/dht.h`, `src/dht.cpp`) — Kademlia protocol: routing table, k-buckets, value replication, expiry.
- **`SecureDht`** (`include/opendht/securedht.h`, `src/securedht.cpp`) — transparent encryption/signing layer on top of `Dht`. Identity is a GnuTLS certificate.
- **`NetworkEngine`** (`include/opendht/network_engine.h`, `src/network_engine.cpp`) — UDP socket layer, serializes/deserializes msgpack messages.
- **`RoutingTable`** (`include/opendht/routing_table.h`, `src/routing_table.cpp`) — Kademlia routing table with bucket splitting.
- **`Value`** (`include/opendht/value.h`) — the storable unit: binary blob, optional signature, optional encryption; typed via `ValueType`.
- **`InfoHash`** (`include/opendht/infohash.h`) — 20-byte SHA-1 identifier; alias `Hash<HASH_LEN>`.
Optional components (`DhtProxyServer`, `DhtProxyClient`, `PeerDiscovery`) are compiled in only when the corresponding CMake options are enabled.
---
+136
View File
@@ -0,0 +1,136 @@
# Build the library
The build is currently tested on GNU/Linux, macOS, and Windows.
## Unix-like systems (Linux, macOS, MSYS2/MinGW, etc.)
## Install dependencies
### Debian 13
```sh
# Install dependencies
sudo apt install pkg-config libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libargon2-dev libmsgpack-dev libssl-dev libfmt-dev libjsoncpp-dev libhttp-parser-dev libasio-dev libmsgpack-cxx-dev
# Install Python binding dependencies
sudo apt-get install cython3 python3-dev python3-setuptools python3-build
```
Optionally, install RESTinio to enable the OpenDHT proxy client and server:
```sh
mkdir /usr/include/nonstd
wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp -O /usr/include/nonstd/expected.hpp
wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.9/restinio-0.7.9.tar.bz2
tar -xjf restinio-0.7.9.tar.bz2
cd restinio-0.7.9/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off -DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system -DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
make && make install
```
To run openDHT on a different computer from the build computer, the following runtime dependencies are required:
```sh
sudo apt install libargon2-1 libjsoncpp26
```
### Ubuntu 24.04 and Debian 12
```sh
# Install dependencies
sudo apt install pkg-config libncurses5-dev libreadline-dev nettle-dev libgnutls28-dev libargon2-0-dev libmsgpack-dev libssl-dev libfmt-dev libjsoncpp-dev libhttp-parser-dev libasio-dev
# Install Python binding dependencies
sudo apt-get install cython3 python3-dev python3-setuptools python3-build
```
Optionally, install RESTinio to enable the OpenDHT proxy client and server:
```sh
mkdir /usr/include/nonstd
wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp -O /usr/include/nonstd/expected.hpp
wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.9/restinio-0.7.9.tar.bz2
tar -xjf restinio-0.7.9.tar.bz2
cd restinio-0.7.9/dev
cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off -DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system -DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system .
make && make install
```
### Fedora
```sh
# Install GnuTLS, Readline and msgpack-c
sudo dnf install readline-devel gnutls-devel msgpack-devel asio-devel libargon2-devel fmt-devel
# Install python binding dependencies
sudo dnf install python3-Cython python3-devel redhat-rpm-config
```
### macOS
```sh
brew install gnutls msgpack-cxx argon2 asio readline jsoncpp fmt
```
## Build
Using CMake:
```sh
# Clone the repository
git clone https://github.com/savoirfairelinux/opendht.git
# Build and install
cd opendht
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make -j$(nproc)
sudo make install
```
#### Example Configurations
Minimal build (libraries only):
```sh
cmake -DOPENDHT_TOOLS=OFF ..
```
Full-featured build with proxy support, Python, and C bindings:
```sh
cmake -DOPENDHT_PYTHON=ON \
-DOPENDHT_C=ON \
-DOPENDHT_PROXY_SERVER=ON \
-DOPENDHT_PROXY_SERVER_IDENTITY=ON \
-DOPENDHT_PROXY_CLIENT=ON \
-DOPENDHT_PUSH_NOTIFICATIONS=ON \
-DCMAKE_INSTALL_PREFIX=/usr ..
```
#### Common CMake options
| Option | Default | Purpose |
|--------|---------|---------|
| `OPENDHT_TOOLS` | ON | CLI tools (dhtnode, dhtchat, …) |
| `OPENDHT_C` | OFF | C language bindings |
| `OPENDHT_PYTHON` | OFF | Python 3 Cython bindings |
| `OPENDHT_PROXY_SERVER` | OFF | REST API proxy server (requires RESTinio + llhttp) |
| `OPENDHT_PROXY_CLIENT` | OFF | REST API proxy client |
| `OPENDHT_PEER_DISCOVERY` | OFF | Multicast local peer discovery |
| `OPENDHT_PUSH_NOTIFICATIONS` | OFF | Push notification support |
| `OPENDHT_SANITIZE` | OFF | AddressSanitizer + stack protector |
## Windows/MSVC
Building on Windows with MSVC is supported with VCPKG and CMake.
### Build with VCPKG in manifest mode
1. Install [VCPKG](https://github.com/microsoft/vcpkg) and required dependencies:
```ps1
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg; .\bootstrap-vcpkg.bat
```
2. Use CMake preset for vcpkg:
```ps1
cd opendht
cmake --preset=vcpkg_manifest .
cmake --build .
```
+908 -100
View File
File diff suppressed because it is too large. Load diff
+250
View File
@@ -0,0 +1,250 @@
{
"version": 2,
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build",
"hidden": true
},
{
"name": "unix-make",
"description": "Unix Makefiles",
"generator": "Unix Makefiles",
"inherits": "default",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": true
}
},
{
"name": "unix-make-full",
"description": "Unix Makefiles (Full build)",
"inherits": "unix-make",
"cacheVariables": {
"OPENDHT_C": true,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true,
"OPENDHT_PUSH_NOTIFICATIONS": true,
"OPENDHT_PYTHON": true,
"OPENDHT_INDEX": true,
"BUILD_TESTING": true,
"OPENDHT_EXAMPLES": true
}
},
{
"name": "unix-make-release",
"description": "Unix Makefiles (Release build)",
"inherits": "unix-make-full",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": true,
"BUILD_TESTING": false,
"OPENDHT_SANITIZE": false,
"OPENDHT_EXAMPLES": false
}
},
{
"name": "ninja",
"generator": "Ninja",
"inherits": "default",
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": true
}
},
{
"name": "ninja-release",
"inherits": "ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": true,
"BUILD_TESTING": false,
"OPENDHT_SANITIZE": false,
"OPENDHT_CPACK": true,
"OPENDHT_C": true,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true
}
},
{
"name": "msvc",
"generator": "Visual Studio 17 2022",
"inherits": "default",
"cacheVariables": {
"BUILD_TESTING": true,
"VCPKG_MANIFEST_FEATURES": "test",
"OPENDHT_PROXY_CLIENT": false,
"OPENDHT_PROXY_SERVER": false,
"OPENDHT_C": true
}
},
{
"name": "vcpkg_manifest",
"inherits": "msvc",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"BUILD_SHARED_LIBS": true,
"CMAKE_BUILD_TYPE": "Debug",
"VCPKG_MANIFEST_MODE": true
}
},
{
"name": "vcpkg_manifest_static",
"inherits": "vcpkg_manifest",
"cacheVariables": {
"BUILD_SHARED_LIBS": false,
"VCPKG_TARGET_TRIPLET": "x64-windows-static"
}
},
{
"name": "vcpkg_local",
"inherits": "msvc",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"BUILD_SHARED_LIBS": true,
"CMAKE_BUILD_TYPE": "Debug",
"BUILD_TESTING": true,
"VCPKG_MANIFEST_MODE": false
}
},
{
"name": "vcpkg_release",
"inherits": "vcpkg_manifest",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"VCPKG_TARGET_TRIPLET": "x64-windows-release",
"VCPKG_OVERLAY_TRIPLETS": "x64-windows-release;x64-windows-rel;x64-windows",
"BUILD_TESTING": false,
"OPENDHT_CPACK": true,
"OPENDHT_C": false
}
},
{
"name": "vcpkg_release_full",
"inherits": "vcpkg_release",
"cacheVariables": {
"BUILD_TESTING": false,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true,
"OPENDHT_C": true,
"OPENDHT_PYTHON": true,
"OPENDHT_CPACK": true,
"OPENDHT_DOCUMENTATION": false
}
},
{
"name": "vcpkg_release_static",
"inherits": "vcpkg_manifest_static",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"VCPKG_TARGET_TRIPLET": "x64-windows-static-release",
"BUILD_TESTING": false,
"OPENDHT_CPACK": true,
"OPENDHT_C": false
}
},
{
"name": "vcpkg_release_static_full",
"inherits": "vcpkg_manifest_static",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"VCPKG_TARGET_TRIPLET": "x64-windows-static-release",
"BUILD_TESTING": false,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true,
"OPENDHT_C": true,
"OPENDHT_CPACK": true,
"OPENDHT_DOCUMENTATION": false
}
},
{
"name": "vcpkg_release_local",
"inherits": "vcpkg_local",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"VCPKG_TARGET_TRIPLET": "x64-windows-release",
"VCPKG_OVERLAY_TRIPLETS": "x64-windows-release;x64-windows-rel;x64-windows",
"BUILD_TESTING": false,
"OPENDHT_CPACK": true,
"OPENDHT_C": false
}
},
{
"name": "vcpkg_release_local_full",
"inherits": "vcpkg_local",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"VCPKG_TARGET_TRIPLET": "x64-windows-release",
"VCPKG_OVERLAY_TRIPLETS": "x64-windows-release;x64-windows-rel;x64-windows",
"BUILD_TESTING": false,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true,
"OPENDHT_CPACK": true
}
},
{
"name": "vcpkg_release_static_local",
"inherits": "vcpkg_local",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": false,
"VCPKG_TARGET_TRIPLET": "x64-windows-static-release",
"VCPKG_OVERLAY_TRIPLETS": "x64-windows-static-release;x64-windows-static-rel;x64-windows-static",
"BUILD_TESTING": false,
"OPENDHT_CPACK": true,
"OPENDHT_C": false
}
},
{
"name": "vcpkg_release_static_local_full",
"inherits": "vcpkg_local",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"BUILD_SHARED_LIBS": false,
"VCPKG_TARGET_TRIPLET": "x64-windows-static-release",
"VCPKG_OVERLAY_TRIPLETS": "x64-windows-static-release;x64-windows-static-rel;x64-windows-static",
"BUILD_TESTING": false,
"OPENDHT_PROXY_CLIENT": true,
"OPENDHT_PROXY_SERVER": true,
"OPENDHT_CPACK": true
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default",
"hidden": true
},
{
"name": "unix-make",
"inherits": "default",
"configurePreset": "unix-make"
},
{
"name": "ninja",
"inherits": "default",
"configurePreset": "ninja"
},
{
"name": "msvc",
"inherits": "default",
"configurePreset": "msvc"
},
{
"name": "vcpkg-dev",
"inherits": "default",
"configurePreset": "vcpkg_manifest"
},
{
"name": "vcpkg-release-static",
"inherits": "default",
"configurePreset": "vcpkg_release_static_full",
"configuration": "Release"
},
{
"name": "vcpkg-release",
"inherits": "default",
"configurePreset": "vcpkg_release_full",
"configuration": "Release"
}
]
}
-674
View File
@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+7
View File
@@ -0,0 +1,7 @@
Copyright (c) 2014-2026 Savoir-faire Linux Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-248
View File
@@ -1,248 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
#output directories
DebugLib/
Debug/
ReleaseLib/
Release/
.config/
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.VC.VC.opendb
*.VC.db
*.db
*.filters
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
!config.h
-257
View File
@@ -1,257 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opendht", "opendht.vcxproj", "{711397CE-E5D5-467D-9457-8716C047E50C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
DebugDLL|x64 = DebugDLL|x64
DebugDLL|x86 = DebugDLL|x86
DebugDLLStaticDeps|x64 = DebugDLLStaticDeps|x64
DebugDLLStaticDeps|x86 = DebugDLLStaticDeps|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
ReleaseDLL|x64 = ReleaseDLL|x64
ReleaseDLL|x86 = ReleaseDLL|x86
ReleaseDLLStaticDeps|x64 = ReleaseDLLStaticDeps|x64
ReleaseDLLStaticDeps|x86 = ReleaseDLLStaticDeps|x86
ReleaseLTO|x64 = ReleaseLTO|x64
ReleaseLTO|x86 = ReleaseLTO|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.ActiveCfg = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.Build.0 = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.ActiveCfg = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.Build.0 = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.ActiveCfg = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.Build.0 = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.ActiveCfg = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.ActiveCfg = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.Build.0 = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.ActiveCfg = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.Build.0 = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.Build.0 = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.ActiveCfg = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.Build.0 = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.ActiveCfg = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.Build.0 = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.ActiveCfg = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.Build.0 = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.ActiveCfg = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.Build.0 = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.ActiveCfg = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.Build.0 = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.ActiveCfg = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.Build.0 = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.ActiveCfg = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.Build.0 = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.ActiveCfg = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.Build.0 = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.Build.0 = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.ActiveCfg = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.Build.0 = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.ActiveCfg = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.Build.0 = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.ActiveCfg = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.Build.0 = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.ActiveCfg = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.Build.0 = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.ActiveCfg = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.Build.0 = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.ActiveCfg = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.Build.0 = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.ActiveCfg = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.Build.0 = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.ActiveCfg = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.Build.0 = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.ActiveCfg = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.Build.0 = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.ActiveCfg = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.Build.0 = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.ActiveCfg = Debug|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.Build.0 = Debug|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.ActiveCfg = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.Build.0 = Release|x64
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
-224
View File
@@ -1,224 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\callbacks.cpp" />
<ClCompile Include="..\src\crypto.cpp" />
<ClCompile Include="..\src\default_types.cpp" />
<ClCompile Include="..\src\dht.cpp" />
<ClCompile Include="..\src\dhtrunner.cpp" />
<ClCompile Include="..\src\infohash.cpp" />
<ClCompile Include="..\src\network_engine.cpp" />
<ClCompile Include="..\src\node.cpp" />
<ClCompile Include="..\src\node_cache.cpp" />
<ClCompile Include="..\src\routing_table.cpp" />
<ClCompile Include="..\src\securedht.cpp" />
<ClCompile Include="..\src\utils.cpp" />
<ClCompile Include="..\src\value.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\opendht.h" />
<ClInclude Include="..\include\opendht\callbacks.h" />
<ClInclude Include="..\include\opendht\crypto.h" />
<ClInclude Include="..\include\opendht\default_types.h" />
<ClInclude Include="..\include\opendht\dht.h" />
<ClInclude Include="..\include\opendht\dhtrunner.h" />
<ClInclude Include="..\include\opendht\infohash.h" />
<ClInclude Include="..\include\opendht\log.h" />
<ClInclude Include="..\include\opendht\network_engine.h" />
<ClInclude Include="..\include\opendht\node.h" />
<ClInclude Include="..\include\opendht\node_cache.h" />
<ClInclude Include="..\include\opendht\request.h" />
<ClInclude Include="..\include\opendht\rng.h" />
<ClInclude Include="..\include\opendht\routing_table.h" />
<ClInclude Include="..\include\opendht\scheduler.h" />
<ClInclude Include="..\include\opendht\securedht.h" />
<ClInclude Include="..\include\opendht\utils.h" />
<ClInclude Include="..\include\opendht\value.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{711397CE-E5D5-467D-9457-8716C047E50C}</ProjectGuid>
<RootNamespace>opendht</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)..\..\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>opendhtd</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)..\..\</OutDir>
<IntDir>$(Platform)\$(Configuration)\</IntDir>
<TargetName>opendht</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)..\..\</OutDir>
<TargetName>opendhtd</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)..\..\</OutDir>
<TargetName>opendht</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
<SuppressStartupBanner>false</SuppressStartupBanner>
</ClCompile>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
<ProgramDataBaseFileName>$(OutDir)\lib\x86\$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)\lib\x86\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\..\include;..\include;..\include\opendht;..\..\msgpack-c\include;</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32_NATIVE;WIN32_LEAN_AND_MEAN;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4804;4800;4101;4267;4244;4503;</DisableSpecificWarnings>
<AdditionalOptions>-D_SCL_SECURE_NO_WARNINGS %(AdditionalOptions)</AdditionalOptions>
<ProgramDataBaseFileName>$(OutDir)\lib\x64\$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>mkdir $(OutDir)\include
mkdir $(OutDir)\include\opendht
copy ..\include\opendht\*.h $(OutDir)\include\opendht
copy ..\include\opendht.h $(OutDir)\include\</Command>
</PostBuildEvent>
<Lib>
<OutputFile>$(OutDir)\lib\x64\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
-292
View File
@@ -1,292 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opendht", "opendht.vcxproj", "{711397CE-E5D5-467D-9457-8716C047E50C}"
ProjectSection(ProjectDependencies) = postProject
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518} = {070FEF2B-0C3F-4F33-9D3C-53C7330BF518}
{122A2EA4-B283-4241-9655-786DE78283B2} = {122A2EA4-B283-4241-9655-786DE78283B2}
{6F610EE8-7F59-4191-AB88-F63843267C02} = {6F610EE8-7F59-4191-AB88-F63843267C02}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dependencies", "dependencies", "{71A1A9EC-1104-4335-A87E-AF8749FD5B34}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgmp", "..\..\gmp\MSVC\libgmp.vcxproj", "{02B94302-23D6-43EF-8865-95CDE99D5DC2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgnutls", "..\..\gnutls\MSVC\libgnutls.vcxproj", "{6F610EE8-7F59-4191-AB88-F63843267C02}"
ProjectSection(ProjectDependencies) = postProject
{02B94302-23D6-43EF-8865-95CDE99D5DC2} = {02B94302-23D6-43EF-8865-95CDE99D5DC2}
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518} = {070FEF2B-0C3F-4F33-9D3C-53C7330BF518}
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32} = {CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C} = {200F3D3C-8B84-46D8-953A-6C0EBD283B5C}
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B} = {CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libiconv", "..\..\libiconv\MSVC\libiconv.vcxproj", "{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhogweed", "..\..\nettle\MSVC\libhogweed.vcxproj", "{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}"
ProjectSection(ProjectDependencies) = postProject
{02B94302-23D6-43EF-8865-95CDE99D5DC2} = {02B94302-23D6-43EF-8865-95CDE99D5DC2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnettle", "..\..\nettle\MSVC\libnettle.vcxproj", "{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzlib", "..\..\zlib\MSVC\libzlib.vcxproj", "{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MessagePack", "..\..\msgpack-c\msgpack_vc8.vcxproj", "{122A2EA4-B283-4241-9655-786DE78283B2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
DebugDLL|x64 = DebugDLL|x64
DebugDLL|x86 = DebugDLL|x86
DebugDLLStaticDeps|x64 = DebugDLLStaticDeps|x64
DebugDLLStaticDeps|x86 = DebugDLLStaticDeps|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
ReleaseDLL|x64 = ReleaseDLL|x64
ReleaseDLL|x86 = ReleaseDLL|x86
ReleaseDLLStaticDeps|x64 = ReleaseDLLStaticDeps|x64
ReleaseDLLStaticDeps|x86 = ReleaseDLLStaticDeps|x86
ReleaseLTO|x64 = ReleaseLTO|x64
ReleaseLTO|x86 = ReleaseLTO|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLL|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.ActiveCfg = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x64.Build.0 = Debug|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLL|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.ActiveCfg = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x64.Build.0 = Release|x64
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLTO|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.ActiveCfg = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x64.Build.0 = Debug|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.ActiveCfg = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Debug|x86.Build.0 = Debug|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.ActiveCfg = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x64.Build.0 = Release|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.ActiveCfg = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.Release|x86.Build.0 = Release|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{02B94302-23D6-43EF-8865-95CDE99D5DC2}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.ActiveCfg = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x64.Build.0 = Debug|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.ActiveCfg = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Debug|x86.Build.0 = Debug|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x64.Build.0 = DebugDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.ActiveCfg = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x64.Build.0 = Release|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.ActiveCfg = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.Release|x86.Build.0 = Release|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{6F610EE8-7F59-4191-AB88-F63843267C02}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.ActiveCfg = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x64.Build.0 = Debug|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.ActiveCfg = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Debug|x86.Build.0 = Debug|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.ActiveCfg = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x64.Build.0 = Release|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.ActiveCfg = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.Release|x86.Build.0 = Release|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.ActiveCfg = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x64.Build.0 = Debug|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.ActiveCfg = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Debug|x86.Build.0 = Debug|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x64.Build.0 = DebugDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x64.Build.0 = DebugDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.DebugDLLStaticDeps|x86.Build.0 = DebugDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.ActiveCfg = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x64.Build.0 = Release|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.ActiveCfg = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.Release|x86.Build.0 = Release|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLLStaticDeps|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLLStaticDeps|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.ActiveCfg = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x64.Build.0 = Debug|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.ActiveCfg = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Debug|x86.Build.0 = Debug|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.ActiveCfg = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x64.Build.0 = Release|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.ActiveCfg = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.Release|x86.Build.0 = Release|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.ActiveCfg = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x64.Build.0 = Debug|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.ActiveCfg = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Debug|x86.Build.0 = Debug|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLL|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.ActiveCfg = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x64.Build.0 = DebugDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.ActiveCfg = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.DebugDLLStaticDeps|x86.Build.0 = DebugDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.ActiveCfg = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x64.Build.0 = Release|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.ActiveCfg = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.Release|x86.Build.0 = Release|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLL|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.ActiveCfg = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x64.Build.0 = ReleaseDLL|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.ActiveCfg = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseDLLStaticDeps|x86.Build.0 = ReleaseDLL|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.ActiveCfg = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x64.Build.0 = ReleaseLTO|x64
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.ActiveCfg = ReleaseLTO|Win32
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32}.ReleaseLTO|x86.Build.0 = ReleaseLTO|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x64.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Debug|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x64.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLL|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x64.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.ActiveCfg = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.DebugDLLStaticDeps|x86.Build.0 = Debug|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.Release|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x64.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLL|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x64.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseDLLStaticDeps|x86.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x64.Build.0 = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.ActiveCfg = Release|Win32
{122A2EA4-B283-4241-9655-786DE78283B2}.ReleaseLTO|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{02B94302-23D6-43EF-8865-95CDE99D5DC2} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{6F610EE8-7F59-4191-AB88-F63843267C02} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{CB8BB76F-D3FF-434E-A85E-7FFC0893EC9B} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{200F3D3C-8B84-46D8-953A-6C0EBD283B5C} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{070FEF2B-0C3F-4F33-9D3C-53C7330BF518} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{CA9A4A38-CC63-4BDB-8CFB-E058965DDA32} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
{122A2EA4-B283-4241-9655-786DE78283B2} = {71A1A9EC-1104-4335-A87E-AF8749FD5B34}
EndGlobalSection
EndGlobal
-71
View File
@@ -1,71 +0,0 @@
@ECHO OFF
SETLOCAL EnableDelayedExpansion
SET UPSTREAMURL=https://github.com/atraczyk
SET DEPENDENCIES=( ^
gmp, ^
gnutls, ^
nettle, ^
msgpack-c ^
)
SET PASSDEPENDENCIES=%~1
git status >NUL 2>&1
IF %ERRORLEVEL% EQU 128 (
git init
) ELSE (
IF %ERRORLEVEL% EQU 9009 (
ECHO git not installed.
EXIT /B 1
)
)
SET CURRDIR=%~dp1
cd ..\..
FOR %%I IN %DEPENDENCIES% DO (
ECHO !PASSDEPENDENCIES! | FINDSTR /C:"%%I" >NUL 2>&1 || (
CALL :cloneOrUpdateRepo "%%I" )
)
cd %CURRDIR% >NUL
GOTO exit
:cloneOrUpdateRepo
SET REPONAME=%~1
IF NOT EXIST "%REPONAME%" (
ECHO %REPONAME%: Existing folder not found. Cloning repository...
SET REPOURL=%UPSTREAMURL%/%REPONAME%.git
git clone !REPOURL! --quiet
cd %REPONAME%
git config --local core.autocrlf false
git rm --cached -r . --quiet
git reset --hard --quiet
cd ..\
)
SET PASSDEPENDENCIES=%PASSDEPENDENCIES% %REPONAME%
IF EXIST "%REPONAME%\MSVC\project_get_dependencies.bat" (
ECHO %REPONAME%: Found additional dependencies...
ECHO.
cd %REPONAME%\MSVC
project_get_dependencies.bat "!PASSDEPENDENCIES!" || GOTO exitOnError
cd ..\..
)
ECHO.
EXIT /B %ERRORLEVEL%
:exitOnError
cd %CURRDIR%
:exit
(
ENDLOCAL
SET PASSDEPENDENCIES=%PASSDEPENDENCIES%
)
ECHO %CMDCMDLINE% | FINDSTR /L %COMSPEC% >NUL 2>&1
IF %ERRORLEVEL% == 0 IF "%~1"=="" PAUSE
EXIT /B 0
-27
View File
@@ -1,27 +0,0 @@
AM_CXXFLAGS = -pthread
SUBDIRS = src
if ENABLE_TOOLS
SUBDIRS += tools
endif
if USE_CYTHON
SUBDIRS += python
endif
if HAVE_DOXYGEN
SUBDIRS += doc
endif
ACLOCAL_AMFLAGS = -I m4
DOC_FILES = \
README.md \
LICENSE
EXTRA_DIST = \
$(DOC_FILES)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = opendht.pc
+97 -38
View File
@@ -1,32 +1,41 @@
OpenDHT
===
A lightweight C++11 Distributed Hash Table implementation originally based on https://github.com/jech/dht by Juliusz Chroboczek.
<img src="https://raw.githubusercontent.com/savoirfairelinux/opendht/master/resources/opendht_logo_512.png" width="100" align="right">
<br>
<h1 style="margin-top:10px">
<a id="user-content-opendht-" class="anchor" href="/savoirfairelinux/opendht/blob/master/README.md#opendht-" aria-hidden="true"></a>OpenDHT
</h1>
* Light and fast C++11 Kademlia DHT library.
* Distributed shared key->value data-store
* Clean and powerfull distributed map API with storage of arbitrary binary values of up to 56 KB.
* Optional public key cryptography layer providing data signature and encryption (using GnuTLS).
* IPv4 and IPv6 support.
* Python binding.
![PyPI - Version](https://img.shields.io/pypi/v/opendht?style=flat)
Documentation
-
A lightweight C++17 Distributed Hash Table implementation.
OpenDHT provides an easy to use distributed in-memory data store.
Every node in the network can read and write values to the store.
Values are distributed over the network, with redundancy.
* Lightweight and scalable, designed for large networks and small devices
* High resilience to network disruption
* Public key cryptography layer providing optional data signature and encryption (using GnuTLS)
* IPv4 and IPv6 support
* Clean and powerful **C++17** map API
* Bindings for **C, Rust & Python 3**
* REST API with optional HTTP client+server with push notification support
## Documentation
See the wiki: <https://github.com/savoirfairelinux/opendht/wiki>
#### How to run a node
You can help contribute to the public network by running a stable node with a public IP address.
https://github.com/savoirfairelinux/opendht/wiki/Running-a-node-with-dhtnode
#### How-to build and install
Build instructions : <https://github.com/savoirfairelinux/opendht/wiki/Build-the-library>
Build instructions: see [BUILD.md](BUILD.md)
#### How-to build a simple client app
```bash
g++ main.cpp -std=c++11 -lopendht -lgnutls
```
Examples
-
## Examples
### C++ example
The `tools` directory includes simple example programs :
* `dhtnode`, a command line tool, mostly used for debuging, allowing to perform operations supported by the library (get, put etc.) with text values.
* `dhtnode`, a command line tool, allowing to run a DHT node and perform operations supported by the library (get, put etc.) with text values.
* `dhtchat`, a very simple IM client working over the dht.
Example program launching a DHT node, connecting to the network and performing some basic operations:
@@ -44,7 +53,7 @@ int main()
// Join the network through any running node,
// here using a known bootstrap node.
node.bootstrap("bootstrap.ring.cx", "4222");
node.bootstrap("bootstrap.jami.net", "4222");
// put some data on the dht
std::vector<uint8_t> some_data(5, 10);
@@ -66,41 +75,91 @@ int main()
return 0;
}
```
### Python 3 example
Install on Linux, macOS and Windows with:
```sh
pip install opendht
```
Using the simple, blocking API:
```python
import opendht as dht
node = dht.DhtRunner()
node.run()
# Join the network through any running node,
# Join the DHT network through any running node,
# here using a known bootstrap node.
node.bootstrap("bootstrap.ring.cx", "4222")
node.bootstrap("bootstrap.jami.net", "4222")
# blocking call (provide callback arguments to make the call non-blocking)
node.put(dht.InfoHash.get("unique_key"), dht.Value(b'some binary data'))
results = node.get(dht.InfoHash.get("unique_key"))
for r in results:
print(r)
for value in results:
print(value)
```
Dependencies
-
Or using asyncio:
```python
import asyncio
import opendht.aio as dht
async def dht_async_demo(key_str: str):
# Start a new node using an async context manager.
# It is also possible to call run()/await shutdown() manually.
async with dht.DhtRunner(
bootstrap=(("bootstrap.jami.net", "4222"),)
) as node:
# compute key hash
key = dht.InfoHash.get(key_str)
# put data, waiting for completion
await node.put(key, dht.Value(b'tata data'))
# get all values at key
results = await node.getAll(key)
for value in results:
print(value)
# same operation, but stream values as they come from the network
with node.get(key) as results:
async for value in results:
print(value)
# listen for change of values at key
with node.listen(key) as values:
async for value, expired in values:
print(value)
if value.data == b'tata data':
break
asyncio.run(dht_async_demo("unique_key"))
```
## Dependencies
Core dependencies:
- msgpack-c 1.2+, used for data serialization.
- GnuTLS 3.1+, used for cryptographic operations.
- GnuTLS 3.3+, used for cryptographic operations.
- Nettle 2.4+, a GnuTLS dependency for crypto.
- Build tested with GCC 4.8+ (GNU/Linux, Android, Windows with MinGW), Clang/LLVM (Linux, OS X).
- Build tested with Microsoft Visual Studio 2015
- {fmt} 9.0+, for log formatting.
Licence
-
Copyright (C) 2014-2016 Savoir-faire Linux Inc.
Optional dependencies for the REST API (DHT proxy client/server):
- (optional) restinio
- (optional) llhttp
- (optional) jsoncpp 1.7.4-3+
- (optional) simdutf
Licenced under the GNU General Public License version 3 (see COPYING for the full licence).
Build environment:
- Build tested with GCC 9+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
- Build tested with Microsoft Visual Studio 2019, 2022
This project is independent from another project called OpenDHT (Sean Rhea. Ph.D. Thesis, 2005), now extinct.
## License
Copyright (c) 2014-2026 Savoir-faire Linux Inc.
Donations
-
We gratefully accept Bitcoin donations to support OpenDHT development at: `bitcoin:3EykSd1An888efq4Bq3KaV3hJ3JQ4FPnwm`.
OpenDHT is released under the MIT License. See [LICENSE](LICENSE) for details.
## Acknowledgements
This project was originally based on https://github.com/jech/dht by Juliusz Chroboczek.
-1
View File
@@ -1 +0,0 @@
autoreconf --install --verbose -Wall
+692
View File
@@ -0,0 +1,692 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#include "opendht_c.h"
#include <opendht.h>
#include <opendht/log.h>
using ValueSp = std::shared_ptr<dht::Value>;
using PrivkeySp = std::shared_ptr<dht::crypto::PrivateKey>;
using PubkeySp = std::shared_ptr<const dht::crypto::PublicKey>;
using CertSp = std::shared_ptr<dht::crypto::Certificate>;
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
const char*
dht_version()
{
return dht::version();
}
// dht::InfoHash
inline dht_infohash
dht_infohash_to_c(const dht::InfoHash& h)
{
dht_infohash ret;
*reinterpret_cast<dht::InfoHash*>(&ret) = h;
return ret;
}
inline dht_pkid
dht_pkid_to_c(const dht::PkId& h)
{
dht_pkid ret;
*reinterpret_cast<dht::PkId*>(&ret) = h;
return ret;
}
const char*
dht_infohash_print(const dht_infohash* h)
{
return reinterpret_cast<const dht::InfoHash*>(h)->to_c_str();
}
void
dht_infohash_zero(dht_infohash* h)
{
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash {};
}
void
dht_infohash_random(dht_infohash* h)
{
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::getRandom();
}
void
dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size)
{
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::get(dat, dat_size);
}
void
dht_infohash_get_from_string(dht_infohash* h, const char* dat)
{
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::get((const uint8_t*) dat, (size_t) strlen(dat));
}
bool
dht_infohash_is_zero(const dht_infohash* h)
{
return !static_cast<bool>(*reinterpret_cast<const dht::InfoHash*>(h));
}
void
dht_infohash_from_hex(dht_infohash* h, const char* dat)
{
*h = dht_infohash_to_c(dht::InfoHash(std::string_view(dat, HASH_LEN * 2)));
}
void
dht_infohash_from_hex_null(dht_infohash* h, const char* dat)
{
*h = dht_infohash_to_c(dht::InfoHash(std::string_view(dat)));
}
const char*
dht_pkid_print(const dht_pkid* h)
{
return reinterpret_cast<const dht::PkId*>(h)->to_c_str();
}
// dht::Blob
void
dht_blob_delete(dht_blob* data)
{
delete reinterpret_cast<dht::Blob*>(data);
}
dht_data_view
dht_blob_get_data(const dht_blob* data)
{
dht_data_view view;
view.data = reinterpret_cast<const dht::Blob*>(data)->data();
view.size = reinterpret_cast<const dht::Blob*>(data)->size();
return view;
}
// dht::Value
dht_data_view
dht_value_get_data(const dht_value* data)
{
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
dht_data_view view;
view.data = vsp->data.data();
view.size = vsp->data.size();
return view;
}
dht_value_id
dht_value_get_id(const dht_value* data)
{
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return vsp->id;
}
dht_publickey*
dht_value_get_owner(const dht_value* data)
{
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return vsp->owner ? reinterpret_cast<dht_publickey*>(new PubkeySp(vsp->owner)) : nullptr;
}
dht_infohash
dht_value_get_recipient(const dht_value* data)
{
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return dht_infohash_to_c(vsp->recipient);
}
const char*
dht_value_get_user_type(const dht_value* data)
{
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return vsp->user_type.c_str();
}
void
dht_value_set_user_type(dht_value* data, const char* user_type)
{
(*reinterpret_cast<ValueSp*>(data))->user_type = user_type;
}
dht_value*
dht_value_with_id_new(const uint8_t* data, size_t size, uint64_t value_id)
{
return reinterpret_cast<dht_value*>(
new ValueSp(std::make_shared<dht::Value>(dht::ValueType::USER_DATA.id, data, size, value_id)));
}
dht_value*
dht_value_new(const uint8_t* data, size_t size)
{
return dht_value_with_id_new(data, size, 0);
}
dht_value*
dht_value_new_from_string(const char* str)
{
ValueSp value = std::make_shared<dht::Value>((const uint8_t*) str, strlen(str));
value->user_type = "text/plain";
return reinterpret_cast<dht_value*>(new ValueSp(std::move(value)));
}
dht_value*
dht_value_ref(const dht_value* v)
{
return reinterpret_cast<dht_value*>(new ValueSp(*reinterpret_cast<const ValueSp*>(v)));
}
void
dht_value_unref(dht_value* v)
{
delete reinterpret_cast<ValueSp*>(v);
}
// dht::crypto::PublicKey
dht_publickey*
dht_publickey_import(const uint8_t* dat, size_t dat_size)
{
try {
return reinterpret_cast<dht_publickey*>(
new PubkeySp(std::make_shared<const dht::crypto::PublicKey>(dat, dat_size)));
} catch (const dht::crypto::CryptoException& e) {
return nullptr;
}
}
void
dht_publickey_delete(dht_publickey* pk)
{
delete reinterpret_cast<PubkeySp*>(pk);
}
int
dht_publickey_export(const dht_publickey* pk, char* out, size_t* outlen)
{
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return pkey->pack((uint8_t*) out, outlen);
}
dht_infohash
dht_publickey_get_id(const dht_publickey* pk)
{
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return dht_infohash_to_c(pkey->getId());
}
dht_pkid
dht_publickey_get_long_id(const dht_publickey* pk)
{
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return dht_pkid_to_c(pkey->getLongId());
}
bool
dht_publickey_check_signature(
const dht_publickey* pk, const char* data, size_t data_size, const char* signature, size_t signature_size)
{
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return pkey->checkSignature((const uint8_t*) data, data_size, (const uint8_t*) signature, signature_size);
}
dht_blob*
dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_t data_size)
{
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
try {
auto rdata = std::make_unique<dht::Blob>();
*rdata = pkey->encrypt((const uint8_t*) data, data_size);
return (dht_blob*) rdata.release();
} catch (...) {
return nullptr;
}
}
// dht::crypto::PrivateKey
dht_privatekey*
dht_privatekey_generate(unsigned key_length_bits)
{
if (key_length_bits == 0)
key_length_bits = 4096;
return reinterpret_cast<dht_privatekey*>(
new PrivkeySp(std::make_shared<dht::crypto::PrivateKey>(dht::crypto::PrivateKey::generate(key_length_bits))));
}
dht_privatekey*
dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password)
{
try {
return reinterpret_cast<dht_privatekey*>(
new PrivkeySp(std::make_shared<dht::crypto::PrivateKey>(dat, dat_size, password)));
} catch (const dht::crypto::CryptoException& e) {
return nullptr;
}
}
int
dht_privatekey_export(const dht_privatekey* k, char* out, size_t* out_size, const char* password)
{
if (!out or !out_size or !*out_size)
return -1;
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
return key->serialize((uint8_t*) out, out_size, password);
}
dht_publickey*
dht_privatekey_get_publickey(const dht_privatekey* k)
{
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
return reinterpret_cast<dht_publickey*>(new PubkeySp(key->getSharedPublicKey()));
}
dht_blob*
dht_privatekey_decrypt(const dht_privatekey* k, const char* data, size_t data_size)
{
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
try {
auto rdata = std::make_unique<dht::Blob>();
*rdata = key->decrypt((const uint8_t*) data, data_size);
return (dht_blob*) rdata.release();
} catch (...) {
return nullptr;
}
}
void
dht_privatekey_delete(dht_privatekey* pk)
{
delete reinterpret_cast<PrivkeySp*>(pk);
}
// dht::crypto::Certificate
dht_certificate*
dht_certificate_import(const uint8_t* dat, size_t dat_size)
{
try {
return reinterpret_cast<dht_certificate*>(new CertSp(std::make_shared<dht::crypto::Certificate>(dat, dat_size)));
} catch (const dht::crypto::CryptoException& e) {
return nullptr;
}
}
void
dht_certificate_delete(dht_certificate* c)
{
delete reinterpret_cast<CertSp*>(c);
}
dht_infohash
dht_certificate_get_id(const dht_certificate* c)
{
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return dht_infohash_to_c(cert->getId());
}
dht_pkid
dht_certificate_get_long_id(const dht_certificate* c)
{
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return dht_pkid_to_c(cert->getLongId());
}
dht_publickey*
dht_certificate_get_publickey(const dht_certificate* c)
{
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return reinterpret_cast<dht_publickey*>(new PubkeySp(cert->getSharedPublicKey()));
}
#ifdef __cplusplus
} // extern "C"
// Function with internal C++ linkage
#endif
// dht::crypto::Identity
inline dht::crypto::Identity
dht_identity_from_c(const dht_identity* cid)
{
dht::crypto::Identity id {};
if (cid and cid->privatekey)
id.first = *reinterpret_cast<const PrivkeySp*>(cid->privatekey);
if (cid and cid->certificate)
id.second = *reinterpret_cast<const CertSp*>(cid->certificate);
return id;
}
inline dht_identity
dht_identity_to_c(const dht::crypto::Identity& id)
{
dht_identity cid {};
cid.privatekey = id.first ? reinterpret_cast<dht_privatekey*>(new PrivkeySp(id.first)) : NULL;
cid.certificate = id.second ? reinterpret_cast<dht_certificate*>(new CertSp(id.second)) : NULL;
return cid;
}
#ifdef __cplusplus
extern "C" {
#endif
OPENDHT_C_PUBLIC dht_identity
dht_identity_generate(const char* common_name, const dht_identity* ca)
{
return dht_identity_to_c(dht::crypto::generateIdentity(common_name, dht_identity_from_c(ca)));
}
OPENDHT_C_PUBLIC void
dht_identity_delete(dht_identity* id)
{
if (id->certificate) {
dht_certificate_delete(id->certificate);
id->certificate = NULL;
}
if (id->privatekey) {
dht_privatekey_delete(id->privatekey);
id->privatekey = NULL;
}
}
// config
void
dht_runner_config_default(dht_runner_config* config)
{
memset(config, 0, sizeof(dht_runner_config));
config->threaded = true;
}
// dht::DhtRunner
dht_runner*
dht_runner_new(void)
{
return reinterpret_cast<dht_runner*>(new dht::DhtRunner);
}
void
dht_runner_delete(dht_runner* runner)
{
delete reinterpret_cast<dht::DhtRunner*>(runner);
}
int
dht_runner_run(dht_runner* r, in_port_t port)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
try {
runner->run(port, {}, true);
} catch (...) {
return ENOTCONN;
}
return 0;
}
int
dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
try {
dht::DhtRunner::Config config;
config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(
&conf->dht_config.node_config.node_id);
config.dht_config.node_config.network = conf->dht_config.node_config.network;
config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
? std::string(conf->dht_config.node_config.persist_path)
: std::string {};
if (conf->dht_config.id.privatekey)
config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
if (conf->dht_config.id.certificate)
config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
config.threaded = conf->threaded;
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string {};
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string {};
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string {};
config.push_topic = conf->push_topic ? std::string(conf->push_topic) : std::string {};
config.push_platform = conf->push_platform ? std::string(conf->push_platform) : std::string {};
config.proxy_user_agent = conf->proxy_user_agent ? std::string(conf->proxy_user_agent) : std::string {};
config.peer_discovery = conf->peer_discovery;
config.peer_publish = conf->peer_publish;
if (conf->server_ca)
config.server_ca = *reinterpret_cast<const CertSp*>(conf->server_ca);
config.client_identity = dht_identity_from_c(&conf->client_identity);
dht::DhtRunner::Context context;
if (conf->log) {
context.logger = dht::log::getStdLogger();
}
runner->run(port, config, std::move(context));
} catch (...) {
return ENOTCONN;
}
return 0;
}
void
dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len, dht_done_cb done_cb, void* cb_user_data)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
if (done_cb) {
runner->bootstrap(dht::SockAddr(addr, addr_len),
[done_cb, cb_user_data](bool ok) { done_cb(ok, cb_user_data); });
} else {
runner->bootstrap(dht::SockAddr(addr, addr_len));
}
}
void
dht_runner_bootstrap(dht_runner* r, const char* host, const char* service)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
if (service)
runner->bootstrap(host, service);
else
runner->bootstrap(host);
}
void
dht_runner_get(dht_runner* r, const dht_infohash* h, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
runner->get(
*hash,
[cb, cb_user_data](std::shared_ptr<dht::Value> value) {
return cb(reinterpret_cast<const dht_value*>(&value), cb_user_data);
},
[done_cb, cb_user_data](bool ok) {
if (done_cb)
done_cb(ok, cb_user_data);
});
}
struct ScopeGuardCb
{
ScopeGuardCb(dht_shutdown_cb cb, void* data)
: onDestroy(cb)
, userData(data)
{}
~ScopeGuardCb()
{
if (onDestroy)
onDestroy((void*) userData);
}
private:
const dht_shutdown_cb onDestroy;
void const* userData;
};
dht_op_token*
dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto fret = new std::future<size_t>;
*fret = runner->listen(*hash,
[cb,
cb_user_data,
guard = done_cb ? std::make_shared<ScopeGuardCb>(done_cb, cb_user_data)
: std::shared_ptr<ScopeGuardCb> {}](
const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) {
for (const auto& value : values) {
if (not cb(reinterpret_cast<const dht_value*>(&value), expired, cb_user_data))
return false;
}
return true;
});
return (dht_op_token*) fret;
}
void
dht_runner_cancel_listen(dht_runner* r, const dht_infohash* h, dht_op_token* t)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto token = reinterpret_cast<std::future<size_t>*>(t);
runner->cancelListen(*hash, std::move(*token));
}
void
dht_op_token_delete(dht_op_token* token)
{
delete reinterpret_cast<std::future<size_t>*>(token);
}
void
dht_runner_put(
dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data, bool permanent)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->put(
*hash,
*value,
[done_cb, cb_user_data](bool ok) {
if (done_cb)
done_cb(ok, cb_user_data);
},
dht::time_point::max(),
permanent);
}
void
dht_runner_put_signed(
dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data, bool permanent)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->putSigned(
*hash,
*value,
[done_cb, cb_user_data](bool ok) {
if (done_cb)
done_cb(ok, cb_user_data);
},
permanent);
}
void
dht_runner_put_encrypted(dht_runner* r,
const dht_infohash* h,
const dht_infohash* to,
const dht_value* v,
dht_done_cb done_cb,
void* cb_user_data,
bool permanent)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto toHash = reinterpret_cast<const dht::InfoHash*>(to);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->putEncrypted(
*hash,
*toHash,
*value,
[done_cb, cb_user_data](bool ok) {
if (done_cb)
done_cb(ok, cb_user_data);
},
permanent);
}
void
dht_runner_cancel_put(dht_runner* r, const dht_infohash* h, dht_value_id value_id)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
runner->cancelPut(*hash, value_id);
}
void
dht_runner_shutdown(dht_runner* r, dht_shutdown_cb done_cb, void* cb_user_data)
{
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
runner->shutdown([done_cb, cb_user_data]() {
if (done_cb)
done_cb(cb_user_data);
});
}
bool
dht_runner_is_running(const dht_runner* r)
{
if (not r)
return false;
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
return runner->isRunning();
}
in_port_t
dht_runner_get_bound_port(const dht_runner* r, sa_family_t af)
{
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
return runner->getBoundPort(af);
}
dht_infohash
dht_runner_get_node_id(const dht_runner* r)
{
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
dht_infohash ret;
*reinterpret_cast<dht::InfoHash*>(&ret) = runner->getNodeId();
return ret;
}
dht_infohash
dht_runner_get_id(const dht_runner* r)
{
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
dht_infohash ret;
*reinterpret_cast<dht::InfoHash*>(&ret) = runner->getId();
return ret;
}
struct sockaddr**
dht_runner_get_public_address(const dht_runner* r)
{
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
auto addrs = const_cast<dht::DhtRunner*>(runner)->getPublicAddress();
if (addrs.empty())
return nullptr;
auto ret = (struct sockaddr**) malloc(sizeof(struct sockaddr*) * (addrs.size() + 1));
for (size_t i = 0; i < addrs.size(); i++)
ret[i] = addrs[i].release();
ret[addrs.size()] = nullptr;
return ret;
}
#ifdef __cplusplus
}
#endif
+214
View File
@@ -0,0 +1,214 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <opendht/def.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
typedef uint16_t sa_family_t;
typedef uint16_t in_port_t;
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
// Non-owning data view
struct OPENDHT_C_PUBLIC dht_data_view
{
const uint8_t* data;
size_t size;
};
typedef struct dht_data_view dht_data_view;
OPENDHT_C_PUBLIC const char* dht_version(void);
// dht::Blob
struct OPENDHT_C_PUBLIC dht_blob;
typedef struct dht_blob dht_blob;
OPENDHT_C_PUBLIC dht_data_view dht_blob_get_data(const dht_blob* data);
OPENDHT_C_PUBLIC void dht_blob_delete(dht_blob* data);
// dht::InfoHash
struct OPENDHT_C_PUBLIC dht_infohash
{
uint8_t d[HASH_LEN];
};
typedef struct dht_infohash dht_infohash;
OPENDHT_C_PUBLIC void dht_infohash_zero(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_random(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_from_hex(dht_infohash* h, const char* dat);
OPENDHT_C_PUBLIC void dht_infohash_from_hex_null(dht_infohash* h, const char* dat);
OPENDHT_C_PUBLIC void dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC void dht_infohash_get_from_string(dht_infohash* h, const char* str);
OPENDHT_C_PUBLIC const char* dht_infohash_print(const dht_infohash* h);
OPENDHT_C_PUBLIC bool dht_infohash_is_zero(const dht_infohash* h);
// dht::PkId
struct OPENDHT_C_PUBLIC dht_pkid
{
uint8_t d[32];
};
typedef struct dht_pkid dht_pkid;
OPENDHT_C_PUBLIC const char* dht_pkid_print(const dht_pkid* h);
// dht::crypto::PublicKey
struct OPENDHT_C_PUBLIC dht_publickey;
typedef struct dht_publickey dht_publickey;
OPENDHT_C_PUBLIC dht_publickey* dht_publickey_import(const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC void dht_publickey_delete(dht_publickey* pk);
OPENDHT_C_PUBLIC int dht_publickey_export(const dht_publickey* pk, char* out, size_t* out_size);
OPENDHT_C_PUBLIC dht_infohash dht_publickey_get_id(const dht_publickey* pk);
OPENDHT_C_PUBLIC dht_pkid dht_publickey_get_long_id(const dht_publickey* pk);
OPENDHT_C_PUBLIC bool dht_publickey_check_signature(
const dht_publickey* pk, const char* data, size_t data_size, const char* signature, size_t signature_size);
OPENDHT_C_PUBLIC dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_t data_size);
// dht::crypto::PrivateKey
struct OPENDHT_C_PUBLIC dht_privatekey;
typedef struct dht_privatekey dht_privatekey;
OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_generate(unsigned key_length_bits);
OPENDHT_C_PUBLIC dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password);
OPENDHT_C_PUBLIC int dht_privatekey_export(const dht_privatekey*, char* out, size_t* out_size, const char* password);
OPENDHT_C_PUBLIC dht_publickey* dht_privatekey_get_publickey(const dht_privatekey*);
OPENDHT_C_PUBLIC dht_blob* dht_privatekey_decrypt(const dht_privatekey*, const char* data, size_t data_size);
OPENDHT_C_PUBLIC void dht_privatekey_delete(dht_privatekey*);
// dht::crypto::Certificate
struct OPENDHT_C_PUBLIC dht_certificate;
typedef struct dht_certificate dht_certificate;
OPENDHT_C_PUBLIC dht_certificate* dht_certificate_import(const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC dht_infohash dht_certificate_get_id(const dht_certificate*);
OPENDHT_C_PUBLIC dht_pkid dht_certificate_get_long_id(const dht_certificate*);
OPENDHT_C_PUBLIC dht_publickey* dht_certificate_get_publickey(const dht_certificate*);
OPENDHT_C_PUBLIC void dht_certificate_delete(dht_certificate*);
struct OPENDHT_C_PUBLIC dht_identity
{
dht_privatekey* privatekey;
dht_certificate* certificate;
};
typedef struct dht_identity dht_identity;
OPENDHT_C_PUBLIC dht_identity dht_identity_generate(const char* common_name, const dht_identity* ca);
OPENDHT_C_PUBLIC void dht_identity_delete(dht_identity*);
// dht::Value
struct OPENDHT_C_PUBLIC dht_value;
typedef struct dht_value dht_value;
typedef uint64_t dht_value_id;
OPENDHT_C_PUBLIC dht_value* dht_value_new(const uint8_t* data, size_t size);
OPENDHT_C_PUBLIC dht_value* dht_value_with_id_new(const uint8_t* data, size_t size, uint64_t value_id);
OPENDHT_C_PUBLIC dht_value* dht_value_new_from_string(const char* str);
OPENDHT_C_PUBLIC dht_value* dht_value_ref(const dht_value*);
OPENDHT_C_PUBLIC void dht_value_unref(dht_value*);
OPENDHT_C_PUBLIC dht_data_view dht_value_get_data(const dht_value* data);
OPENDHT_C_PUBLIC dht_value_id dht_value_get_id(const dht_value* data);
OPENDHT_C_PUBLIC dht_publickey* dht_value_get_owner(const dht_value* data);
OPENDHT_C_PUBLIC dht_infohash dht_value_get_recipient(const dht_value* data);
OPENDHT_C_PUBLIC const char* dht_value_get_user_type(const dht_value* data);
OPENDHT_C_PUBLIC void dht_value_set_user_type(dht_value* data, const char* user_type);
// callbacks
typedef bool (*dht_get_cb)(const dht_value* value, void* user_data);
typedef bool (*dht_value_cb)(const dht_value* value, bool expired, void* user_data);
typedef void (*dht_done_cb)(bool ok, void* user_data);
typedef void (*dht_shutdown_cb)(void* user_data);
struct OPENDHT_C_PUBLIC dht_op_token;
typedef struct dht_op_token dht_op_token;
OPENDHT_C_PUBLIC void dht_op_token_delete(dht_op_token* token);
// config
struct OPENDHT_C_PUBLIC dht_node_config
{
dht_infohash node_id;
uint32_t network;
bool is_bootstrap;
bool maintain_storage;
const char* persist_path;
};
typedef struct dht_node_config dht_node_config;
struct OPENDHT_C_PUBLIC dht_secure_config
{
dht_node_config node_config;
dht_identity id;
};
typedef struct dht_secure_config dht_secure_config;
struct OPENDHT_C_PUBLIC dht_runner_config
{
dht_secure_config dht_config;
bool threaded;
const char* proxy_server;
const char* push_node_id;
const char* push_token;
const char* push_topic;
const char* push_platform;
const char* proxy_user_agent;
bool peer_discovery;
bool peer_publish;
dht_certificate* server_ca;
dht_identity client_identity;
bool log;
};
typedef struct dht_runner_config dht_runner_config;
OPENDHT_C_PUBLIC void dht_runner_config_default(dht_runner_config* config);
// dht::DhtRunner
struct OPENDHT_C_PUBLIC dht_runner;
typedef struct dht_runner dht_runner;
OPENDHT_C_PUBLIC dht_runner* dht_runner_new(void);
OPENDHT_C_PUBLIC void dht_runner_delete(dht_runner* runner);
/* Returns 0 on success, standard error code on failure */
OPENDHT_C_PUBLIC int dht_runner_run(dht_runner* runner, in_port_t port);
/* Returns 0 on success, standard error code on failure */
OPENDHT_C_PUBLIC int dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
OPENDHT_C_PUBLIC void dht_runner_ping(
dht_runner* runner, struct sockaddr* addr, socklen_t addr_len, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host, const char* service);
OPENDHT_C_PUBLIC void dht_runner_get(
dht_runner* runner, const dht_infohash* hash, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_op_token* dht_runner_listen(
dht_runner* runner, const dht_infohash* hash, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_cancel_listen(dht_runner* runner, const dht_infohash* hash, dht_op_token* token);
OPENDHT_C_PUBLIC void dht_runner_put(dht_runner* runner,
const dht_infohash* hash,
const dht_value* value,
dht_done_cb done_cb,
void* cb_user_data,
bool permanent);
OPENDHT_C_PUBLIC void dht_runner_put_signed(dht_runner* runner,
const dht_infohash* hash,
const dht_value* value,
dht_done_cb done_cb,
void* cb_user_data,
bool permanent);
OPENDHT_C_PUBLIC void dht_runner_put_encrypted(dht_runner* runner,
const dht_infohash* hash,
const dht_infohash* to,
const dht_value* value,
dht_done_cb done_cb,
void* cb_user_data,
bool permanent);
OPENDHT_C_PUBLIC void dht_runner_cancel_put(dht_runner* runner, const dht_infohash* hash, dht_value_id value_id);
OPENDHT_C_PUBLIC void dht_runner_shutdown(dht_runner* runner, dht_shutdown_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_node_id(const dht_runner* runner);
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_id(const dht_runner* runner);
OPENDHT_C_PUBLIC bool dht_runner_is_running(const dht_runner* runner);
OPENDHT_C_PUBLIC in_port_t dht_runner_get_bound_port(const dht_runner* runner, sa_family_t af);
/** Returns null-terminated array that must be freed after use as well as each element */
OPENDHT_C_PUBLIC struct sockaddr** dht_runner_get_public_address(const dht_runner* runner);
#ifdef __cplusplus
}
#endif
+126
View File
@@ -0,0 +1,126 @@
# atomic builtins are required for threading support.
INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
INCLUDE("${CMAKE_CURRENT_LIST_DIR}/DetermineGCCCompatible.cmake")
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() {
++z;
++y;
return ++x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
function(check_working_cxx_atomics64 varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
#include <cstdint>
std::atomic<uint64_t> x (0);
int main() {
uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics64)
# Check for (non-64-bit) atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)
elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
# First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if(HAVE_LIBATOMIC)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
else()
#message(FATAL_ERROR "Host compiler appears to require libatomic, but unable to find it.")
endif()
endif()
endif()
# Check for 64 bit atomic operations.
if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")
# First check if atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
if(HAVE_CXX_LIBATOMICS64)
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")
endif()
else()
#message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but unable to find it.")
endif()
endif()
endif()
# Set variable LLVM_ATOMIC_LIB specifying flags for linking against libatomic.
if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB)
# Use options --push-state, --as-needed and --pop-state if linker is known to support them.
# Use single option -Wl of compiler driver to avoid incorrect re-ordering of options by CMake.
if(LLVM_LINKER_IS_GNULD OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD OR LLVM_LINKER_IS_MOLD)
set(LLVM_ATOMIC_LIB "-Wl,--push-state,--as-needed,-latomic,--pop-state")
else()
set(LLVM_ATOMIC_LIB "-latomic")
endif()
else()
set(LLVM_ATOMIC_LIB)
endif()
## TODO: This define is only used for the legacy atomic operations in
## llvm's Atomic.h, which should be replaced. Other code simply
## assumes C++11 <atomic> works.
CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER
#include <windows.h>
#endif
int main() {
#ifdef _MSC_VER
volatile LONG val = 1;
MemoryBarrier();
InterlockedCompareExchange(&val, 0, 1);
InterlockedIncrement(&val);
InterlockedDecrement(&val);
#else
volatile unsigned long val = 1;
__sync_synchronize();
__sync_val_compare_and_swap(&val, 1, 0);
__sync_add_and_fetch(&val, 1);
__sync_sub_and_fetch(&val, 1);
#endif
return 0;
}
" LLVM_HAS_ATOMICS)
if( NOT LLVM_HAS_ATOMICS )
message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")
endif()
+13
View File
@@ -0,0 +1,13 @@
# Determine if the compiler has GCC-compatible command-line syntax.
if(NOT DEFINED LLVM_COMPILER_IS_GCC_COMPATIBLE)
if(CMAKE_COMPILER_IS_GNUCXX)
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( MSVC )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE OFF)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
elseif( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel" )
set(LLVM_COMPILER_IS_GCC_COMPATIBLE ON)
endif()
endif()
-64
View File
@@ -1,64 +0,0 @@
# - Try to find msgpack
# Once done this will define
# MSGPACK_FOUND - System has msgpack
# MSGPACK_INCLUDE_DIRS - The msgpack include directories
# MSGPACK_LIBRARIES - The libraries needed to use msgpack
if(NOT MSGPACK_USE_BUNDLED)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_search_module(PC_MSGPACK QUIET
msgpackc>=${Msgpack_FIND_VERSION}
msgpack>=${Msgpack_FIND_VERSION})
endif()
else()
set(PC_MSGPACK_INCLUDEDIR)
set(PC_MSGPACK_INCLUDE_DIRS)
set(PC_MSGPACK_LIBDIR)
set(PC_MSGPACK_LIBRARY_DIRS)
set(LIMIT_SEARCH NO_DEFAULT_PATH)
endif()
set(MSGPACK_DEFINITIONS ${PC_MSGPACK_CFLAGS_OTHER})
find_path(MSGPACK_INCLUDE_DIR msgpack/version_master.h
HINTS ${PC_MSGPACK_INCLUDEDIR} ${PC_MSGPACK_INCLUDE_DIRS}
${LIMIT_SEARCH})
if(MSGPACK_INCLUDE_DIR)
file(READ ${MSGPACK_INCLUDE_DIR}/msgpack/version_master.h msgpack_version_h)
string(REGEX REPLACE ".*MSGPACK_VERSION_MAJOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MAJOR "${msgpack_version_h}")
string(REGEX REPLACE ".*MSGPACK_VERSION_MINOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MINOR "${msgpack_version_h}")
string(REGEX REPLACE ".*MSGPACK_VERSION_REVISION +([0-9]+).*" "\\1" MSGPACK_VERSION_REVISION "${msgpack_version_h}")
set(MSGPACK_VERSION_STRING "${MSGPACK_VERSION_MAJOR}.${MSGPACK_VERSION_MINOR}.${MSGPACK_VERSION_REVISION}")
else()
set(MSGPACK_VERSION_STRING)
endif()
# If we're asked to use static linkage, add libmsgpack{,c}.a as a preferred library name.
if(MSGPACK_USE_STATIC)
list(APPEND MSGPACK_NAMES
"${CMAKE_STATIC_LIBRARY_PREFIX}msgpackc${CMAKE_STATIC_LIBRARY_SUFFIX}"
"${CMAKE_STATIC_LIBRARY_PREFIX}msgpack${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
list(APPEND MSGPACK_NAMES msgpackc msgpack)
find_library(MSGPACK_LIBRARY NAMES ${MSGPACK_NAMES}
# Check each directory for all names to avoid using headers/libraries from
# different places.
NAMES_PER_DIR
HINTS ${PC_MSGPACK_LIBDIR} ${PC_MSGPACK_LIBRARY_DIRS}
${LIMIT_SEARCH})
mark_as_advanced(MSGPACK_INCLUDE_DIR MSGPACK_LIBRARY)
set(MSGPACK_LIBRARIES ${MSGPACK_LIBRARY})
set(MSGPACK_INCLUDE_DIRS ${MSGPACK_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set MSGPACK_FOUND to TRUE
# if all listed variables are TRUE
find_package_handle_standard_args(Msgpack
REQUIRED_VARS MSGPACK_LIBRARY MSGPACK_INCLUDE_DIR
VERSION_VAR MSGPACK_VERSION_STRING)
+1 -1
View File
@@ -10,7 +10,7 @@
# READLINE_LIBRARIES - the Readline library plus the libraries it
# depends on
# Copyright (C) 2009
# Copyright (c) 2009
# ASTRON (Netherlands Institute for Radio Astronomy)
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
#
+14
View File
@@ -0,0 +1,14 @@
# header-only does not produce a library
if(NOT Restinio_FOUND)
find_path (Restinio_INCLUDE_DIR restinio
HINTS
"/usr/include"
"/usr/local/include"
"/opt/local/include")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Restinio DEFAULT_MSG Restinio_INCLUDE_DIR)
if (Restinio_INCLUDE_DIR)
set(Restinio_FOUND TRUE)
set(Restinio_INCLUDE_DIRS ${Restinio_INCLUDE_DIR})
endif()
endif()
+21
View File
@@ -0,0 +1,21 @@
# Windows utility functions and macros
# Determine Windows NT version for compatibility
# https://stackoverflow.com/a/40217291/9560245
macro(get_WIN32_WINNT version)
if(CMAKE_SYSTEM_VERSION)
set(ver ${CMAKE_SYSTEM_VERSION})
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
if("${verMajor}" MATCHES "10")
set(verMajor "A")
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
endif()
# Remove all remaining '.' characters.
string(REPLACE "." "" ver ${ver})
# Prepend each digit with a zero.
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
set(${version} "0x${ver}")
endif()
endmacro()
-107
View File
@@ -1,107 +0,0 @@
AC_INIT(opendht, 0.6.1)
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE([foreign subdir-objects])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [Build in debug mode, adds stricter warnings, disables optimization]))
AS_IF([test "x$enable_debug" = "xyes"],
[CXXFLAGS="${CXXFLAGS} -g -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -O0"],
[CXXFLAGS="${CXXFLAGS} -O3"])
AC_PROG_CXX
AM_PROG_AR
dnl Check for Doxygen
AC_ARG_ENABLE([doc], AS_HELP_STRING([--enable-doc], [Enable documentation generation (doxygen)]))
AS_IF([test "x$enable_doc" = "xyes"], [
AC_CHECK_PROGS([DOXYGEN], [doxygen])
AS_IF([test -z "$DOXYGEN"], [AC_MSG_WARN([Doxygen not found - continuing without Doxygen support])])
])
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
dnl Check for Python
AC_ARG_ENABLE([python], [AS_HELP_STRING([--disable-python], [Disble python binding])])
AS_IF([test "x$enable_python" != "xno"], [
AM_PATH_PYTHON([3.3],, [:])
AS_IF([test -n "$PYTHON"],[
AC_CHECK_PROGS([CYTHON], [cython3])
AS_IF([test -z "$CYTHON"],[AC_MSG_WARN([Cython not found - continuing without python support])])
AC_CHECK_PROGS([PIP], [pip3])
AS_IF([test -z "$PIP"],[AC_MSG_WARN([pip not found - continuing without python uninstall support])])
])
])
AM_CONDITIONAL([USE_CYTHON], [test -n "$CYTHON"])
AM_CONDITIONAL([HAVE_PIP], [test -n "$PIP"])
case "${host_os}" in
"")
SYS=unknown
;;
*android*)
SYS=android
;;
linux*)
SYS=linux
;;
darwin*)
SYS=darwin
;;
mingw32*)
SYS=mingw32
WIN32=1
AC_DEFINE([_POSIX_SOURCE], [1], [IEEE Std 1003.1.])
AC_DEFINE([_POSIX_C_SOURCE], [200809L], [IEEE Std 1003.1.])
AC_DEFINE([_XOPEN_SOURCE], [700], [POSIX and XPG 7th edition])
AC_DEFINE([_XOPEN_SOURCE_EXTENDED], [1], [XPG things and X/Open Unix extensions.])
AC_DEFINE([_BSD_SOURCE], [1], [ISO C, POSIX, and 4.3BSD things.])
LDFLAGS="${LDFLAGS} -lws2_32"
AC_SUBST(WINDOWS_ARCH)
AC_SUBST(PROGRAMFILES)
;;
*)
SYS="${host_os}"
;;
esac
AM_CONDITIONAL(WIN32, [test "x$SYS" = "xmingw32"])
AS_IF([test "x$SYS" = "xandroid"],
[], [LDFLAGS="${LDFLAGS} -lpthread"])
LT_INIT()
LT_LANG(C++)
AX_CXX_COMPILE_STDCXX(11,[noext],[mandatory])
PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES([Nettle], [nettle >= 2.4])
PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.1])
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
CXXFLAGS="${CXXFLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT"
AC_ARG_ENABLE([tools], AS_HELP_STRING([--disable-tools],[Disable tools (CLI DHT node)]),,build_tools=yes)
AM_CONDITIONAL(ENABLE_TOOLS, test x$build_tools == xyes)
AM_COND_IF([ENABLE_TOOLS], [
AC_CHECK_HEADERS([readline/readline.h readline/history.h], [], [
AC_MSG_ERROR([unable to find readline.h])
])
])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])])
dnl Configure setup.py if we build the python module
AM_COND_IF([USE_CYTHON], [
AC_SUBST(CURRENT_SOURCE_DIR, ".")
AC_SUBST(CURRENT_BINARY_DIR, ".")
AC_SUBST(PROJECT_SOURCE_DIR, "..")
AC_SUBST(PROJECT_BINARY_DIR, "../src/.libs")
AC_CONFIG_FILES([python/Makefile python/setup.py])
])
AC_CONFIG_FILES([Makefile
src/Makefile
src/argon2/Makefile
tools/Makefile
opendht.pc])
AC_OUTPUT
+16
View File
@@ -0,0 +1,16 @@
if (OPENDHT_TOOLS)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dhtnode.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif ()
if (OPENDHT_DOCUMENTATION)
if (NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()
configure_file (Doxyfile.in Doxyfile @ONLY)
add_custom_target(doc ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION ${CMAKE_INSTALL_DOCDIR}/opendht)
endif()
-9
View File
@@ -1,9 +0,0 @@
doxyfile.stamp:
$(DOXYGEN) Doxyfile
echo stamp > doxyfile.stamp
CLEANFILES = doxyfile.stamp
all-local: doxyfile.stamp
clean-local:
rm -rf $(top_srcdir)/doc/man $(top_srcdir)/doc/html
Binary file not shown.
@@ -0,0 +1,142 @@
\documentclass[11pt]{article}
\usepackage[utf8x]{inputenc}
\usepackage[top=2cm,bottom=2cm]{geometry}
\usepackage{forloop}
\newcounter{counter}
% maths
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{mathrsfs}
\usepackage{shadethm}
\usepackage{amsthm}
\newshadetheorem{shadeDef}{Definition}[section]
\newtheorem{remark}{Remark}[section]
\renewcommand{\P}{\mathbb{P}}
\usepackage{float}
\usepackage{booktabs}
\setlength{\parindent}{0ex}
\setlength{\parskip}{0.5em}
\begin{document}
\title{Annex 1: Probabilistic analysis of connectivity changes}
\author{Adrien Béraud, Simon Désaulniers, Guillaume Roguez}
\maketitle
\pagestyle{empty}
\begin{shadeDef}
A node flagged as \emph{``expired''} by a node $n$ is a node which has not responded to any
of $n$'s last three requests.
\end{shadeDef}
\begin{remark}
An expired node will not be contacted before 10 minutes from its expiration time.
\end{remark}
Let $N$ the DHT network, $n_0\in N$, a given node and the following probabilistic events:
\begin{itemize}
\item $A$: $\forall n \in N$ $n$ is unreachable by $n_0$, \emph{i.e.} $n_0$ lost connection
with $N$;
\item $B$: $S\subset N$, the nodes unreachable by $n_0$ with $k={|S|\over|N|}$;
\item $C$: $m \le |N|$ nodes are flagged as ``expired''.
\end{itemize}
We are interested in knowing $\P(A|C)$, \emph{i.e.} the probability of the event where $A$ occurs
prior to $C$. From the above, we immediately get
$$\left\{
\begin{array}{ll}
\P(C|A) & = 1\\
\P(A) + \P(B) & = 1
\end{array}
\right.$$
Also, the event $A|C$ can be abstracted as the urn problem of draw without replacement. Then,
$$\P(C|B) = \prod_{i=0}^m \left[k|N| - i \over |N|\right] = \prod_{i=0}^m \left[k - { i \over |N| }\right]$$
Furthermore, using Bayes' theroem we have
\begin{align*}
\P(A|C) & = { \P(C|A)\P(A) \over \P(C|A)\P(A) + \P(C|B)\P(B)}\\
& = { \P(A) \over \P(A) + \P(C|B)\P(B) }\\
& = { \P(A) \over \P(A) + \P(C|B)\left[1 - \P(A)\right] }\\
\Rightarrow \forloop{counter}{0}{\value{counter} < 5}{\qquad}\quad \P(A) & =
\P(A|C)\left[\P(A) + \P(C|B)\left(1 - \P(A)\right) \right] \\
\Rightarrow \forloop{counter}{0}{\value{counter} < 2}{\qquad}\;\:\, \P(A)\left[{ 1 \over \P(A|C)} - 1\right] & =
\P(C|B)\left(1 - \P(A)\right) \\
\end{align*}
Finally,
\begin{equation}
\label{eq:final}
\left[{\P(A) \over 1 - \P(A)}\right]\left[{ 1 \over \P(A|C)} - 1\right] =
\prod_{i=0}^m \left[k - { i \over |N| }\right]
\end{equation}
From \eqref{eq:final}, we may set a plausible configuration $\{\P(A),\P(A|C),k,|N|\}$ letting us
produce results such as in table \ref{tbl:k_1_2}, \ref{tbl:k_2_3} and \ref{tbl:k_3_4}.
\begin{table}[H]
\centering
\caption{The values for $m$ assuming $\P(A|C) \ge 0.95,\, k = {1 \over 2}$}
\label{tbl:k_1_2}
\begin{tabular}{lcccc}
\toprule
$|N| \diagdown \P(A)$ & ${1 \over 10 }$ & ${1 \over 100 }$ & ${1 \over 1000 }$ & ${1 \over 10000 }$\\
\midrule
$2^0$ & 1 & 1 & 1 & 1\\
$2^1$ & 1 & 1 & 1 & 1\\
$2^2$ & 2 & 2 & 2 & 2\\
$2^3$ & 4 & 4 & 4 & 4\\
$2^4$ & 5 & 6 & 7 & 8\\
$2^5$ & 5 & 7 & 9 & 10\\
$2^6$ & 6 & 9 & 11 & 13\\
$2^7$ & 6 & 9 & 12 & 14\\
$2^8$ & 7 & 10 & 13 & 16\\
$2^9$ & 7 & 10 & 13 & 16\\
$2^{10}$ & 7 & 10 & 13 & 17\\
\bottomrule
\end{tabular}
\end{table}
\begin{table}[H]
\centering
\caption{The values for $m$ assuming $\P(A|C) \ge 0.95,\, k = {2 \over 3}$}
\label{tbl:k_2_3}
\begin{tabular}{lcccc}
\toprule
$|N| \diagdown \P(A)$ & ${1 \over 10 }$ & ${1 \over 100 }$ & ${1 \over 1000 }$ & ${1 \over 10000 }$\\
\midrule
$2^0$ & 1 & 1 & 1 & 1\\
$2^1$ & 2 & 2 & 2 & 2\\
$2^2$ & 3 & 3 & 4 & 4\\
$2^3$ & 5 & 5 & 6 & 8\\
$2^4$ & 6 & 8 & 9 & 10\\
$2^5$ & 8 & 10 & 12 & 14\\
$2^6$ & 9 & 13 & 16 & 18\\
$2^7$ & 11 & 15 & 18 & 22\\
$2^8$ & 11 & 16 & 21 & 25\\
$2^9$ & 12 & 17 & 22 & 27\\
$2^{10}$ & 12 & 18 & 23 & 28\\
\bottomrule
\end{tabular}
\end{table}
\begin{table}[H]
\centering
\caption{The values for $m$ assuming $\P(A|C) \ge 0.95,\, k = {3 \over 4}$}
\label{tbl:k_3_4}
\begin{tabular}{lcccc}
\toprule
$|N| \diagdown \P(A)$ & ${1 \over 10 }$ & ${1 \over 100 }$ & ${1 \over 1000 }$ & ${1 \over 10000 }$\\
\midrule
$2^0$ & 1 & 1 & 1 & 1\\
$2^1$ & 2 & 2 & 2 & 2\\
$2^2$ & 3 & 3 & 3 & 3\\
$2^3$ & 5 & 6 & 6 & 6\\
$2^4$ & 7 & 9 & 10 & 11\\
$2^5$ & 10 & 12 & 14 & 16\\
$2^6$ & 12 & 16 & 19 & 22\\
$2^7$ & 14 & 19 & 23 & 27\\
$2^8$ & 15 & 21 & 27 & 32\\
$2^9$ & 16 & 23 & 30 & 36\\
$2^{10}$ & 17 & 24 & 31 & 38\\
\bottomrule
\end{tabular}
\end{table}
\end{document}
+110
View File
@@ -0,0 +1,110 @@
.TH DHTNODE 1 2019-06-08
.SH NAME
.B dhtnode
- a simple OpenDHT command line node runner.
.SH SYNOPSIS
.B dhtnode
[\fB\-h\fR]
[\fB\-v\fR [\fB\-l\fR \fIlogfile\fR] [\fB\-L\fR]]
[\fB\-i\fR [\fB\-\-save\-identity\fR \fIfile\fR]]
[\fB\-d\fR] [\fB\-s\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]
.SH DESCRIPTION
Runs an OpenDHT node, with a 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.
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
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).
.EE
.SH OPTIONS
.TP
\fB\-h\fP
Prints some help.
.TP
\fB\-v\fP
Enable the verbose mode (log to stdout/stderr by default)
.TP
\fB\-l\fP \fIlog_file\fP
Write log to file instead of stdout/stderr
.TP
\fB\-L\fP
Write log to syslog instead of stdout/stderr
.TP
\fB\-i\fP
Generate cryptographic identity for the node.
.TP
\fB\-\-save\-identity\fP \fIfile\fP
Save generated identity (certificate and private key) to given file prefix.
.TP
\fB\-\-certificate\fP \fIfile\fP
Load identity certificate from given file.
.TP
\fB\-\-privkey\fP \fIfile\fP
Load identity private key from given file.
.TP
\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).
.TP
\fB\-s\fP
Run the program in service mode (non\-forking daemon).
.TP
\fB\-D\fP
Enables multicast automatic local peer discovery.
.TP
\fB\-f\fP \fIfile\fP
Specify a file path to persist/load the node state.
.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).
.TP
\fB\-p\fP \fIlocal_port\fP
Use UDP port \fIlocal_port\fP for the program to bind to.
.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.
.TP
\fB\-\-proxyserver\fP \fIlocal_port\fP
Run a proxy server bound to this DHT node on HTTP port \fIlocal_port\fP
.TP
\fB\-\-proxyclient\fP \fIserver\fP
Run this DHT node in proxy client mode, and connect to \fIserver\fP
.SH AUTHORS
.TP
Program written by
.IP \(bu
.\}
Adrien Béraud <adrien.beraud@savoirfairelinux.com>
.TP
Man page written by
.IP \(bu
.\}
Simon Désaulniers <sim.desaulniers@gmail.com>
+19
View File
@@ -0,0 +1,19 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
COPY . opendht
RUN cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_TESTING=Off \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install \
&& cd ../.. && rm -rf opendht
+38
View File
@@ -0,0 +1,38 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-alpine:latest AS build
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
COPY . opendht
RUN mkdir /install
ENV DESTDIR=/install
RUN cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DBUILD_TESTING=Off \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install
FROM alpine:3.23 AS install
COPY --from=build /install /
RUN apk add --no-cache \
libstdc++ \
gnutls \
nettle \
openssl \
argon2-dev \
jsoncpp \
llhttp \
fmt \
readline \
ncurses
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
EXPOSE 4222/udp
EXPOSE 8080/tcp
+40
View File
@@ -0,0 +1,40 @@
FROM opendht-alpine-edge-deps:latest AS build
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
COPY . opendht
RUN mkdir /install
ENV DESTDIR=/install
RUN cd opendht && mkdir build && cd build \
&& cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=/usr \
-DOPENDHT_DOWNLOAD_DEPS=Off \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& ninja && ninja install
FROM alpine:edge AS install
COPY --from=build /install /
RUN apk add --no-cache \
libstdc++ \
gnutls \
nettle \
openssl \
argon2-dev \
jsoncpp \
llhttp \
fmt \
simdutf \
readline \
ncurses
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
EXPOSE 4222/udp
EXPOSE 8080/tcp
+32
View File
@@ -0,0 +1,32 @@
FROM ubuntu:24.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update && apt-get install -y \
build-essential pkg-config cmake git wget meson \
libtool \
python3-dev python3-setuptools python3-build python3-virtualenv cython3 \
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
libssl-dev libfmt-dev libasio-dev libmsgpack-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
RUN mkdir /usr/include/nonstd \
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/Stiffstream/restinio/releases/download/v0.7.8.1/restinio-0.7.8.1.tar.bz2 \
&& ls -l && tar -xjf restinio-0.7.8.1.tar.bz2 \
&& cd restinio-0.7.8.1/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
&& make -j2 && make install \
&& cd ../../ && rm -rf restinio*
+27
View File
@@ -0,0 +1,27 @@
FROM alpine:3.23
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
RUN apk add --no-cache \
build-base cmake ninja git wget \
cython python3-dev py3-setuptools \
ncurses-dev readline-dev nettle-dev \
cppunit-dev gnutls-dev jsoncpp-dev \
argon2-dev openssl-dev fmt-dev \
llhttp-dev asio-dev msgpack-cxx-dev \
&& rm -rf /var/cache/apk/*
RUN mkdir /usr/include/nonstd \
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/Stiffstream/restinio/releases/download/v0.7.8.1/restinio-0.7.8.1.tar.bz2 \
&& ls -l && tar -xjf restinio-0.7.8.1.tar.bz2 \
&& cd restinio-0.7.8.1/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
&& make -j2 && make install \
&& cd ../../ && rm -rf restinio*
+27
View File
@@ -0,0 +1,27 @@
FROM alpine:edge
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
RUN apk add --no-cache \
build-base cmake ninja git wget \
cython python3-dev py3-setuptools \
ncurses-dev readline-dev nettle-dev \
cppunit-dev gnutls-dev jsoncpp-dev \
argon2-dev openssl-dev fmt-dev simdutf-dev \
llhttp-dev asio-dev msgpack-cxx-dev \
&& rm -rf /var/cache/apk/*
RUN mkdir /usr/include/nonstd \
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/Stiffstream/restinio/releases/download/v0.7.8.1/restinio-0.7.8.1.tar.bz2 \
&& ls -l && tar -xjf restinio-0.7.8.1.tar.bz2 \
&& cd restinio-0.7.8.1/dev \
&& cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
&& ninja && ninja install \
&& cd ../../ && rm -rf restinio*
+34
View File
@@ -0,0 +1,34 @@
FROM ubuntu:20.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update && apt-get install -y \
build-essential pkg-config cmake git wget \
libtool \
python3-dev python3-setuptools python3-pip \
libncurses5-dev libreadline-dev nettle-dev libcppunit-dev \
libgnutls28-dev libuv1-dev libjsoncpp-dev libargon2-dev \
libssl-dev libfmt-dev libasio-dev libmsgpack-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
RUN pip3 install meson Cython
RUN mkdir /usr/include/nonstd \
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/Stiffstream/restinio/releases/download/v.0.7.3/restinio-0.7.3.tar.bz2 \
&& ls -l && tar -xjf restinio-0.7.3.tar.bz2 \
&& cd restinio-0.7.3/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
&& make -j2 && make install \
&& cd ../../ && rm -rf restinio*
+38
View File
@@ -0,0 +1,38 @@
FROM ubuntu:24.04
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
RUN apt-get update && apt-get install -y \
dialog apt-utils \
&& apt-get clean \
&& echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
RUN apt-get update \
&& apt-get install -y llvm llvm-dev lldb clang gdb make cmake meson pkg-config \
libtool git wget libncurses5-dev libreadline-dev \
nettle-dev libgnutls28-dev libuv1-dev libmsgpack-dev libjsoncpp-dev python3-dev \
python3-setuptools libcppunit-dev python3-pip python3-build python3-virtualenv \
libssl-dev libargon2-dev \
libfmt-dev libasio-dev \
&& apt-get remove -y gcc g++ && apt-get autoremove -y \
&& apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
RUN pip3 install Cython --break-system-packages
ENV CC=cc
ENV CXX=c++
RUN mkdir /usr/include/nonstd \
&& wget https://raw.githubusercontent.com/martinmoene/expected-lite/master/include/nonstd/expected.hpp \
-O /usr/include/nonstd/expected.hpp
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/Stiffstream/restinio/releases/download/v0.7.8.1/restinio-0.7.8.1.tar.bz2 \
&& ls -l && tar -xjf restinio-0.7.8.1.tar.bz2 \
&& cd restinio-0.7.8.1/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=Off -DRESTINIO_SAMPLE=Off -DRESTINIO_BENCHMARK=Off \
-DRESTINIO_WITH_SOBJECTIZER=Off -DRESTINIO_DEP_STANDALONE_ASIO=system -DRESTINIO_DEP_LLHTTP=system \
-DRESTINIO_DEP_FMT=system -DRESTINIO_DEP_EXPECTED_LITE=system . \
&& make -j2 && make install \
&& cd ../../ && rm -rf restinio*
+4
View File
@@ -0,0 +1,4 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht:latest
CMD ["dhtnode", "-b", "bootstrap.jami.net", "-p", "4222", "--proxyserver", "8080"]
EXPOSE 4222/udp
EXPOSE 8080/tcp
+18
View File
@@ -0,0 +1,18 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-focal:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
COPY . opendht
RUN cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DBUILD_TESTING=Off \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
&& make -j8 && make install \
&& cd ../.. && rm -rf opendht
+18
View File
@@ -0,0 +1,18 @@
FROM ghcr.io/savoirfairelinux/opendht/opendht-deps-llvm:latest
LABEL maintainer="Adrien Béraud <adrien.beraud@savoirfairelinux.com>"
LABEL org.opencontainers.image.source=https://github.com/savoirfairelinux/opendht
COPY . opendht
RUN cd opendht && mkdir build && cd build \
&& cmake .. -DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=On \
-DOPENDHT_C=On \
-DOPENDHT_PEER_DISCOVERY=On \
-DOPENDHT_PYTHON=On \
-DOPENDHT_TOOLS=On \
-DOPENDHT_PROXY_SERVER=On \
-DOPENDHT_PROXY_CLIENT=On \
-DOPENDHT_SYSTEMD=On \
&& make -j8 && make install \
&& cd ../.. && rm -rf opendht
+2 -20
View File
@@ -1,24 +1,6 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "opendht/dhtrunner.h"
#include "opendht/log.h"
#include "opendht/default_types.h"
+178 -41
View File
@@ -1,22 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h"
@@ -25,52 +8,206 @@
#include <vector>
#include <memory>
#include <functional>
#include <string>
#ifdef OPENDHT_JSONCPP
#include <json/json.h>
#endif
namespace dht {
struct Node;
/**
* Current status of a DHT node.
*/
enum class NodeStatus {
Disconnected, // 0 nodes
Connecting, // 1+ nodes
Connecting, // bootstrap pending or 1+ nodes
Connected // 1+ good nodes
};
struct Config {
InfoHash node_id;
bool is_bootstrap;
inline constexpr std::string_view
statusToStr(NodeStatus status)
{
return status == NodeStatus::Connected ? "connected"sv
: (status == NodeStatus::Connecting ? "connecting"sv : "disconnected"sv);
}
struct OPENDHT_PUBLIC NodeStats
{
unsigned good_nodes {0}, dubious_nodes {0}, cached_nodes {0}, incoming_nodes {0};
unsigned table_depth {0};
unsigned searches {0};
unsigned node_cache_size {0};
unsigned getKnownNodes() const { return good_nodes + dubious_nodes; }
unsigned long getNetworkSizeEstimation() const { return 8 * std::exp2(table_depth); }
std::string toString() const;
#ifdef OPENDHT_JSONCPP
/**
* Build a json object from a NodeStats
*/
Json::Value toJson() const;
NodeStats() {};
explicit NodeStats(const Json::Value& v);
#endif
MSGPACK_DEFINE_MAP(good_nodes, dubious_nodes, cached_nodes, incoming_nodes, table_depth, searches, node_cache_size)
};
struct SecureDhtConfig
struct OPENDHT_PUBLIC NodeInfo
{
Config node_config;
crypto::Identity id;
InfoHash id;
InfoHash node_id;
NodeStats ipv4 {};
NodeStats ipv6 {};
size_t ongoing_ops {0};
size_t storage_values {0};
size_t storage_size {0};
size_t local_storage_values {0};
size_t local_storage_size {0};
in_port_t bound4 {0};
in_port_t bound6 {0};
#ifdef OPENDHT_JSONCPP
/**
* Build a json object from a NodeStats
*/
Json::Value toJson() const;
NodeInfo() {};
explicit NodeInfo(const Json::Value& v);
#endif
MSGPACK_DEFINE_MAP(id,
node_id,
ipv4,
ipv6,
ongoing_ops,
storage_values,
storage_size,
local_storage_values,
local_storage_size,
bound4,
bound6)
};
/**
* Dht configuration.
*/
struct OPENDHT_PUBLIC Config
{
/** DHT node ID */
InfoHash node_id {};
/**
* DHT network ID. A node will only talk with other nodes having
* the same network ID.
* Network ID 0 (default) represents the main public network.
*/
NetId network {0};
/** For testing purposes only, enables bootstrap mode */
bool is_bootstrap {false};
/** Makes the DHT responsible to maintain its stored values. Consumes more ressources. */
bool maintain_storage {false};
/** If set, the dht will load its state from this file on start and save its state in this file on shutdown */
std::string persist_path {};
/** If non-0, overrides the default global rate-limit. -1 means no limit. */
ssize_t max_req_per_sec {0};
/** If non-0, overrides the default per-IP address rate-limit. -1 means no limit. */
ssize_t max_peer_req_per_sec {0};
/* If non-0, overrides the default maximum number of searches. -1 means no limit. */
ssize_t max_searches {0};
/* If non-0, overrides the default maximum store size for remote values. -1 means no limit. */
ssize_t max_store_size {0};
/* If non-0, overrides the default maximum store size for locally stored values. -1 means no limit. */
ssize_t max_local_store_size {0};
/* If non-0, overrides the default maximum store key count. -1 means no limit. */
ssize_t max_store_keys {0};
/**
* Use appropriate bahavior for a public IP, stable node:
* - No connectivity change triggered when a search fails
* - Larger listen refresh time
*/
bool public_stable {false};
/* Client mode, node will not be used by other nodes to store data. */
bool client_mode {false};
};
/**
* SecureDht configuration.
*/
struct OPENDHT_PUBLIC SecureDhtConfig
{
Config node_config {};
crypto::Identity id {};
/**
* Cache all encountered public keys and certificates,
* for use by the certificate store, putEncrypted and putSigned
*/
bool cert_cache_all {false};
};
enum class OPENDHT_PUBLIC PushNotificationResult : uint8_t {
/* success codes */
PutRefresh,
ListenRefresh,
Values,
ValuesExpired,
/* ignored/error codes */
IgnoredWrongSession = 0x80,
IgnoredNoOp,
IgnoredStopped,
IgnoredDisabled,
Error
};
static constexpr size_t STORAGE_LIMIT_DEFAULT {1024 * 1024 * 64};
static constexpr size_t STORAGE_LIMIT_UNLIMITED {(size_t) -1};
using ValuesExport = std::pair<InfoHash, Blob>;
using QueryCallback = std::function<bool(const std::vector<std::shared_ptr<FieldValueIndex>>& fields)>;
using GetCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>& values)>;
using ValueCallback = std::function<bool(const std::vector<std::shared_ptr<Value>>& values, bool expired)>;
using GetCallbackSimple = std::function<bool(std::shared_ptr<Value> value)>;
using ShutdownCallback = std::function<void()>;
using IdentityAnnouncedCb = std::function<void(bool)>;
using PublicAddressChangedCb = std::function<void(std::vector<SockAddr>)>;
using CertificateStoreQuery = std::function<std::vector<std::shared_ptr<crypto::Certificate>>(const InfoHash& pk_id)>;
typedef bool (*GetCallbackRaw)(std::shared_ptr<Value>, void *user_data);
static constexpr size_t DEFAULT_STORAGE_LIMIT {1024 * 1024 * 64};
GetCallbackSimple bindGetCb(GetCallbackRaw raw_cb, void* user_data);
GetCallback bindGetCb(GetCallbackSimple cb);
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)>;
typedef void (*DoneCallbackRaw)(bool, std::vector<std::shared_ptr<Node>>*, void *user_data);
typedef void (*ShutdownCallbackRaw)(void *user_data);
using DoneCallbackSimple = std::function<void(bool success)>;
ShutdownCallback bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data);
DoneCallback bindDoneCb(DoneCallbackSimple donecb);
DoneCallback bindDoneCb(DoneCallbackRaw raw_cb, void* user_data);
typedef bool (*GetCallbackRaw)(std::shared_ptr<Value>, void* user_data);
typedef bool (*ValueCallbackRaw)(std::shared_ptr<Value>, bool expired, void* user_data);
typedef void (*DoneCallbackRaw)(bool, std::vector<std::shared_ptr<Node>>*, void* user_data);
typedef void (*ShutdownCallbackRaw)(void* user_data);
typedef void (*DoneCallbackSimpleRaw)(bool, void* user_data);
typedef bool (*FilterRaw)(const Value&, void* user_data);
OPENDHT_PUBLIC GetCallbackSimple bindGetCb(GetCallbackRaw raw_cb, void* user_data);
OPENDHT_PUBLIC GetCallback bindGetCb(GetCallbackSimple cb);
OPENDHT_PUBLIC ValueCallback bindValueCb(ValueCallbackRaw raw_cb, void* user_data);
OPENDHT_PUBLIC ShutdownCallback bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data);
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackSimple donecb);
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackRaw raw_cb, void* user_data);
OPENDHT_PUBLIC DoneCallbackSimple bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data);
OPENDHT_PUBLIC Value::Filter bindFilterRaw(FilterRaw raw_filter, void* user_data);
}
} // namespace dht
+585 -79
View File
@@ -1,106 +1,147 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h"
#include "utils.h"
#include "rng.h"
extern "C" {
#include <gnutls/gnutls.h>
#include <gnutls/abstract.h>
#include <gnutls/x509.h>
#include <gnutls/ocsp.h>
}
#include <vector>
#include <memory>
#include <atomic>
#include <mutex>
#include <string_view>
#ifdef _WIN32
#include <iso646.h>
#endif
namespace dht {
/**
* Contains all crypto primitives
*/
namespace crypto {
class CryptoException : public std::runtime_error {
public:
CryptoException(const std::string& str) : std::runtime_error(str) {};
class OPENDHT_PUBLIC CryptoException : public std::runtime_error
{
public:
explicit CryptoException(const std::string& str)
: std::runtime_error(str) {};
explicit CryptoException(const char* str)
: std::runtime_error(str) {};
CryptoException(const CryptoException& e) noexcept = default;
CryptoException& operator=(const CryptoException&) noexcept = default;
};
/**
* Exception thrown when a decryption error happened.
*/
class DecryptError : public CryptoException {
public:
DecryptError(const std::string& str = "") : CryptoException(str) {};
class OPENDHT_PUBLIC DecryptError : public CryptoException
{
public:
explicit DecryptError(const std::string& str)
: CryptoException(str) {};
explicit DecryptError(const char* str)
: CryptoException(str) {};
DecryptError(const DecryptError& e) noexcept = default;
DecryptError& operator=(const DecryptError&) noexcept = default;
};
struct PrivateKey;
struct Certificate;
class RevocationList;
using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
/**
* A public key.
*/
struct PublicKey
struct OPENDHT_PUBLIC PublicKey
{
PublicKey() {}
PublicKey();
/**
* Takes ownership of an existing gnutls_pubkey.
*/
PublicKey(gnutls_pubkey_t k) : pk(k) {}
PublicKey(const Blob& pk);
PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; };
PublicKey(gnutls_pubkey_t k)
: pk(k)
{}
/** Import public key from serialized data */
PublicKey(const uint8_t* dat, size_t dat_size);
PublicKey(const Blob& pk)
: PublicKey(pk.data(), pk.size())
{}
PublicKey(std::string_view pk)
: PublicKey((const uint8_t*) pk.data(), pk.size())
{}
PublicKey(PublicKey&& o) noexcept
: pk(o.pk)
{
o.pk = nullptr;
}
~PublicKey();
explicit operator bool() const { return pk; }
bool operator ==(const PublicKey& o) const {
return pk == o.pk || getId() == o.getId();
}
bool operator !=(const PublicKey& o) const {
return !(*this == o);
}
bool operator==(const PublicKey& o) const { return pk == o.pk || getLongId() == o.getLongId(); }
bool operator!=(const PublicKey& o) const { return !(*this == o); }
PublicKey& operator=(PublicKey&& o) noexcept;
InfoHash getId() const;
bool checkSignature(const Blob& data, const Blob& signature) const;
Blob encrypt(const Blob&) const;
/**
* Get public key fingerprint
*/
const InfoHash& getId() const;
/**
* Get public key long fingerprint
*/
const PkId& getLongId() const;
bool checkSignature(const uint8_t* data, size_t data_len, const uint8_t* signature, size_t signature_len) const;
inline bool checkSignature(const Blob& data, const Blob& signature) const
{
return checkSignature(data.data(), data.size(), signature.data(), signature.size());
}
Blob encrypt(const uint8_t* data, size_t data_len) const;
inline Blob encrypt(const Blob& data) const { return encrypt(data.data(), data.size()); }
inline Blob encrypt(std::string_view data) const { return encrypt((const uint8_t*) data.data(), data.size()); }
void pack(Blob& b) const;
int pack(uint8_t* out, size_t* out_len) const;
void unpack(const uint8_t* dat, size_t dat_size);
template <typename Packer>
std::string toString() const;
template<typename Packer>
void msgpack_pack(Packer& p) const
{
Blob b;
pack(b);
p.pack_bin(b.size());
p.pack_bin_body((const char*)b.data(), b.size());
p.pack_bin_body((const char*) b.data(), b.size());
}
void msgpack_unpack(msgpack::object o);
void msgpack_unpack(const msgpack::object& o);
gnutls_digest_algorithm_t getPreferredDigest() const;
gnutls_pubkey_t pk {nullptr};
gnutls_pubkey_t pk {};
private:
mutable InfoHash cachedId_ {};
mutable PkId cachedLongId_ {};
mutable std::atomic_bool idCached_ {false};
mutable std::atomic_bool longIdCached_ {false};
PublicKey(const PublicKey&) = delete;
PublicKey& operator=(const PublicKey&) = delete;
void encryptBloc(const uint8_t* src, size_t src_size, uint8_t* dst, size_t dst_size) const;
@@ -109,10 +150,10 @@ private:
/**
* A private key, including the corresponding public key.
*/
struct PrivateKey
struct OPENDHT_PUBLIC PrivateKey
{
PrivateKey();
//PrivateKey(gnutls_privkey_t k) : key(k) {}
// PrivateKey(gnutls_privkey_t k) : key(k) {}
/**
* Takes ownership of an existing gnutls_x509_privkey.
@@ -122,68 +163,291 @@ struct PrivateKey
PrivateKey(PrivateKey&& o) noexcept;
PrivateKey& operator=(PrivateKey&& o) noexcept;
PrivateKey(const Blob& import, const std::string& password = {});
PrivateKey(const uint8_t* src, size_t src_size, const char* password = nullptr);
PrivateKey(const Blob& src, const std::string& password = {})
: PrivateKey(src.data(), src.size(), password.c_str())
{}
PrivateKey(std::string_view src, const std::string& password = {})
: PrivateKey((const uint8_t*) src.data(), src.size(), password.c_str())
{}
~PrivateKey();
explicit operator bool() const { return key; }
PublicKey getPublicKey() const;
const PublicKey& getPublicKey() const;
const std::shared_ptr<PublicKey>& getSharedPublicKey() const;
int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const;
Blob serialize(const std::string& password = {}) const;
/**
* Sign the provided binary object.
* @returns the signature data.
*/
Blob sign(const Blob&) const;
Blob sign(const uint8_t* data, size_t data_len) const;
inline Blob sign(std::string_view dat) const { return sign((const uint8_t*) dat.data(), dat.size()); }
inline Blob sign(const Blob& dat) const { return sign(dat.data(), dat.size()); }
/**
* Try to decrypt the provided cypher text.
* In case of failure a CryptoException is thrown.
* @returns the decrypted data.
*/
Blob decrypt(const Blob& cypher) const;
Blob decrypt(const uint8_t* cypher, size_t cypher_len) const;
Blob decrypt(const Blob& cypher) const { return decrypt(cypher.data(), cypher.size()); }
/**
* Generate a new RSA key pair
* @param key_length : size of the modulus in bits
* Minimim value: 2048
* Recommended values: 4096, 8192
* @param algo : the public key algorithm to use, GNUTLS_PK_RSA or GNUTLS_PK_RSA_OAEP
*/
static PrivateKey generate(unsigned key_length = 4096);
static PrivateKey generate(unsigned key_length = 4096, gnutls_pk_algorithm_t algo = GNUTLS_PK_RSA);
static PrivateKey generateEC();
gnutls_privkey_t key {};
gnutls_x509_privkey_t x509_key {};
private:
PrivateKey(const PrivateKey&) = delete;
PrivateKey& operator=(const PrivateKey&) = delete;
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
mutable std::mutex publicKeyMutex_;
mutable std::shared_ptr<PublicKey> publicKey_ {};
};
struct Certificate {
Certificate() {}
class OPENDHT_PUBLIC RevocationList
{
using clock = std::chrono::system_clock;
using time_point = clock::time_point;
using duration = clock::duration;
public:
RevocationList();
RevocationList(const Blob& b);
RevocationList(RevocationList&& o) noexcept
: crl(o.crl)
{
o.crl = nullptr;
}
~RevocationList();
RevocationList& operator=(RevocationList&& o)
{
crl = o.crl;
o.crl = nullptr;
return *this;
}
void pack(Blob& b) const;
void unpack(const uint8_t* dat, size_t dat_size);
Blob getPacked() const
{
Blob b;
pack(b);
return b;
}
template<typename Packer>
void msgpack_pack(Packer& p) const
{
Blob b = getPacked();
p.pack_bin(b.size());
p.pack_bin_body((const char*) b.data(), b.size());
}
void msgpack_unpack(const msgpack::object& o);
void revoke(const Certificate& crt, time_point t = time_point::min());
bool isRevoked(const Certificate& crt) const;
/**
* Sign this revocation list using provided key and certificate.
* Validity_period sets the duration until next update (default to no next update).
*/
void sign(const PrivateKey&, const Certificate&, duration validity_period = {});
void sign(const Identity& id) { sign(*id.first, *id.second); }
bool isSignedBy(const Certificate& issuer) const;
std::string toString() const;
/**
* Read the CRL number extension field.
*/
Blob getNumber() const;
/** Read CRL issuer Common Name (CN) */
std::string getIssuerName() const;
/** Read CRL issuer User ID (UID) */
std::string getIssuerUID() const;
time_point getUpdateTime() const;
time_point getNextUpdateTime() const;
gnutls_x509_crl_t get() { return crl; }
gnutls_x509_crl_t getCopy() const
{
if (not crl)
return nullptr;
auto copy = RevocationList(getPacked());
gnutls_x509_crl_t ret = copy.crl;
copy.crl = nullptr;
return ret;
}
private:
gnutls_x509_crl_t crl {};
RevocationList(const RevocationList&) = delete;
RevocationList& operator=(const RevocationList&) = delete;
};
enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
class OPENDHT_PUBLIC CertificateRequest
{
public:
CertificateRequest();
CertificateRequest(const uint8_t* data, size_t size);
CertificateRequest(std::string_view src)
: CertificateRequest((const uint8_t*) src.data(), src.size())
{}
CertificateRequest(const Blob& data)
: CertificateRequest(data.data(), data.size())
{}
CertificateRequest(CertificateRequest&& o) noexcept
: request(std::move(o.request))
{
o.request = nullptr;
}
CertificateRequest& operator=(CertificateRequest&& o) noexcept;
~CertificateRequest();
void setName(const std::string& name);
void setUID(const std::string& name);
void setAltName(NameType type, const std::string& name);
std::string getName() const;
std::string getUID() const;
void sign(const PrivateKey& key, const std::string& password = {});
bool verify() const;
Blob pack() const;
std::string toString() const;
gnutls_x509_crq_t get() const { return request; }
private:
CertificateRequest(const CertificateRequest& o) = delete;
CertificateRequest& operator=(const CertificateRequest& o) = delete;
gnutls_x509_crq_t request {nullptr};
};
class OPENDHT_PUBLIC OcspRequest
{
public:
OcspRequest(gnutls_ocsp_req_t r)
: request(r)
{}
OcspRequest(const uint8_t* dat_ptr, size_t dat_size);
OcspRequest(std::string_view dat)
: OcspRequest((const uint8_t*) dat.data(), dat.size())
{}
~OcspRequest();
/*
* Get OCSP Request in readable format.
*/
std::string toString(const bool compact = true) const;
Blob pack() const;
Blob getNonce() const;
private:
gnutls_ocsp_req_t request;
};
class OPENDHT_PUBLIC OcspResponse
{
public:
OcspResponse(const uint8_t* dat_ptr, size_t dat_size);
OcspResponse(std::string_view response)
: OcspResponse((const uint8_t*) response.data(), response.size())
{}
~OcspResponse();
Blob pack() const;
/*
* Get OCSP Response in readable format.
*/
std::string toString(const bool compact = true) const;
/*
* Get OCSP response certificate status.
* Return certificate status.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-cert-status-t
*/
gnutls_ocsp_cert_status_t getCertificateStatus() const;
/*
* Verify OCSP response and return OCSP status.
* Throws CryptoException in case of error in the response.
* http://www.gnu.org/software/gnutls/reference/gnutls-ocsp.html#gnutls-ocsp-verify-reason-t
*/
gnutls_ocsp_cert_status_t verifyDirect(const Certificate& crt, const Blob& nonce);
private:
gnutls_ocsp_resp_t response;
};
struct OPENDHT_PUBLIC Certificate
{
Certificate() noexcept {}
/**
* Take ownership of existing gnutls structure
*/
Certificate(gnutls_x509_crt_t crt) : cert(crt) {}
Certificate(gnutls_x509_crt_t crt) noexcept
: cert(crt)
{}
Certificate(Certificate&& o) noexcept : cert(o.cert), issuer(std::move(o.issuer)) { o.cert = nullptr; };
Certificate(Certificate&& o) noexcept
: cert(o.cert)
, issuer(std::move(o.issuer))
, publicKey_(std::move(o.publicKey_))
{
o.cert = nullptr;
};
/**
* Import certificate (PEM or DER) or certificate chain (PEM),
* ordered from subject to issuer
*/
Certificate(const Blob& crt);
Certificate(const uint8_t* dat, size_t dat_size) {
Certificate(const uint8_t* dat, size_t dat_size)
: cert(nullptr)
{
unpack(dat, dat_size);
}
Certificate(std::string_view pem)
: Certificate((const uint8_t*) pem.data(), pem.size())
{}
/**
* Import certificate chain (PEM or DER),
* ordered from subject to issuer
*/
template<typename Iterator>
Certificate(const Iterator& begin, const Iterator& end) {
Certificate(const Iterator& begin, const Iterator& end)
{
unpack(begin, end);
}
@@ -192,7 +456,8 @@ struct Certificate {
* ordered from subject to issuer
*/
template<typename Iterator>
Certificate(const std::vector<std::pair<Iterator, Iterator>>& certs) {
Certificate(const std::vector<std::pair<Iterator, Iterator>>& certs)
{
unpack(certs);
}
@@ -201,7 +466,8 @@ struct Certificate {
void pack(Blob& b) const;
void unpack(const uint8_t* dat, size_t dat_size);
Blob getPacked() const {
Blob getPacked() const
{
Blob b;
pack(b);
return b;
@@ -250,7 +516,7 @@ struct Certificate {
for (auto li = certs.rbegin(); li != certs.rend(); ++li) {
Certificate tmp_crt;
gnutls_x509_crt_init(&tmp_crt.cert);
const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)};
const gnutls_datum_t crt_dt {(uint8_t*) &(*li->first), (unsigned) (li->second - li->first)};
int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
if (err != GNUTLS_E_SUCCESS)
err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
@@ -262,22 +528,30 @@ struct Certificate {
*this = tmp_issuer ? std::move(*tmp_issuer) : Certificate();
}
template <typename Packer>
template<typename Packer>
void msgpack_pack(Packer& p) const
{
Blob b;
pack(b);
p.pack_bin(b.size());
p.pack_bin_body((const char*)b.data(), b.size());
p.pack_bin_body((const char*) b.data(), b.size());
}
void msgpack_unpack(msgpack::object o);
void msgpack_unpack(const msgpack::object& o);
explicit operator bool() const { return cert; }
PublicKey getPublicKey() const;
const PublicKey& getPublicKey() const;
const std::shared_ptr<PublicKey>& getSharedPublicKey() const;
/** Same as getPublicKey().getId() */
InfoHash getId() const;
const InfoHash& getId() const;
/** Same as getPublicKey().getLongId() */
const PkId& getLongId() const;
Blob getSerialNumber() const;
/** Read certificate full DN as described in RFC4514 */
std::string getDN() const;
/** Read certificate Common Name (CN) */
std::string getName() const;
@@ -285,19 +559,24 @@ struct Certificate {
/** Read certificate User ID (UID) */
std::string getUID() const;
/** Read certificate issuer DN as described in RFC4514 */
std::string getIssuerDN() const;
/** Read certificate issuer Common Name (CN) */
std::string getIssuerName() const;
/** Read certificate issuer User ID (UID) */
std::string getIssuerUID() const;
enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
/** Read certificate alternative names */
std::vector<std::pair<NameType, std::string>> getAltNames() const;
std::chrono::system_clock::time_point getActivation() const;
std::chrono::system_clock::time_point getExpiration() const;
/**
* Returns true if the certificate is marked as a Certificate Authority.
* Returns true if the certificate is marked as a Certificate Authority
* and has necessary key usage flags to sign certificates.
*/
bool isCA() const;
@@ -307,15 +586,140 @@ struct Certificate {
*/
std::string toString(bool chain = true) const;
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", Identity ca = {}, bool is_ca = false);
std::string print() const;
gnutls_x509_crt_t cert {};
/**
* As a CA, revoke a certificate, adding it to
* the attached Certificate Revocation List (CRL)
*/
void revoke(const PrivateKey&, const Certificate&);
/**
* Get the list of certificates revoked as as CA.
*/
std::vector<std::shared_ptr<RevocationList>> getRevocationLists() const;
/**
* Attach existing revocation list.
*/
void addRevocationList(RevocationList&&);
void addRevocationList(std::shared_ptr<RevocationList>);
static Certificate generate(const PrivateKey& key,
const std::string& name = "dhtnode",
const Identity& ca = {},
bool is_ca = false,
int64_t validity = 0);
static Certificate generate(const CertificateRequest& request, const Identity& ca, int64_t validity = 0);
gnutls_x509_crt_t getCopy() const
{
if (not cert)
return nullptr;
auto copy = Certificate(getPacked());
gnutls_x509_crt_t ret = copy.cert;
copy.cert = nullptr;
return ret;
}
std::vector<gnutls_x509_crt_t> getChain(bool copy = false) const
{
if (not cert)
return {};
std::vector<gnutls_x509_crt_t> crts;
for (auto c = this; c; c = c->issuer.get())
crts.emplace_back(copy ? c->getCopy() : c->cert);
return crts;
}
std::pair<std::vector<gnutls_x509_crt_t>, std::vector<gnutls_x509_crl_t>> getChainWithRevocations(
bool copy = false) const
{
if (not cert)
return {};
std::vector<gnutls_x509_crt_t> crts;
std::vector<gnutls_x509_crl_t> crls;
for (auto c = this; c; c = c->issuer.get()) {
crts.emplace_back(copy ? c->getCopy() : c->cert);
crls.reserve(crls.size() + c->revocation_lists.size());
for (const auto& crl : c->revocation_lists)
crls.emplace_back(copy ? crl->getCopy() : crl->get());
}
return {crts, crls};
}
gnutls_digest_algorithm_t getPreferredDigest() const;
/*
* Generate OCSP request.
* Return GnuTLS error code.
* https://www.gnutls.org/manual/html_node/Error-codes.html
*/
std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
/**
* Change certificate's expiration
*/
void setValidity(const Identity& ca, int64_t validity);
void setValidity(const PrivateKey& key, int64_t validity);
gnutls_x509_crt_t cert {nullptr};
std::shared_ptr<Certificate> issuer {};
std::shared_ptr<OcspResponse> ocspResponse;
private:
Certificate(const Certificate&) = delete;
Certificate& operator=(const Certificate&) = delete;
mutable InfoHash cachedId_ {};
mutable PkId cachedLongId_ {};
mutable std::atomic_bool idCached_ {false};
mutable std::atomic_bool longIdCached_ {false};
struct crlNumberCmp
{
bool operator()(const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const
{
return lhs->getNumber() < rhs->getNumber();
}
};
std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
mutable std::mutex publicKeyMutex_;
mutable std::shared_ptr<PublicKey> publicKey_ {};
};
struct OPENDHT_PUBLIC TrustList
{
struct VerifyResult
{
int ret;
unsigned result;
bool hasError() const { return ret < 0; }
bool isValid() const { return !hasError() and !(result & GNUTLS_CERT_INVALID); }
explicit operator bool() const { return isValid(); }
OPENDHT_PUBLIC std::string toString() const;
OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const VerifyResult& h);
};
TrustList();
TrustList(TrustList&& o) noexcept
: trust(std::move(o.trust))
{
o.trust = nullptr;
}
TrustList& operator=(TrustList&& o) noexcept;
~TrustList();
void add(const Certificate& crt);
void add(const RevocationList& crl);
void remove(const Certificate& crt, bool parents = true);
VerifyResult verify(const Certificate& crt) const;
private:
TrustList(const TrustList& o) = delete;
TrustList& operator=(const TrustList& o) = delete;
gnutls_x509_trust_list_t trust {nullptr};
};
/**
* Generate an RSA key pair (4096 bits) and a certificate.
@@ -324,14 +728,28 @@ private:
* If not set, the generated certificate will be a self-signed CA.
* @param key_length stength of the generated private key (bits).
*/
Identity generateIdentity(const std::string& name, Identity ca, unsigned key_length, bool is_ca);
Identity generateIdentity(const std::string& name = "dhtnode", Identity ca = {}, unsigned key_length = 4096);
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name, const Identity& ca, unsigned key_length, bool is_ca);
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode",
const Identity& ca = {},
unsigned key_length = 4096);
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name, const Identity& ca, bool is_ca);
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name = "dhtnode", const Identity& ca = {});
OPENDHT_PUBLIC void saveIdentity(const Identity& id, const std::string& path, const std::string& privkey_password = {});
OPENDHT_PUBLIC Identity loadIdentity(const std::string& path, const std::string& privkey_password = {});
/**
* SHA512
* Performs SHA512, SHA256 or SHA1, depending on hash_length.
* Attempts to choose an hash function with
* output size of at least hash_length bytes, Current implementation
* will use SHA1 for hash_length up to 20 bytes,
* will use SHA256 for hash_length up to 32 bytes,
* will use SHA512 for hash_length of 33 bytes and more.
*/
Blob hash(const Blob& data);
OPENDHT_PUBLIC Blob hash(const Blob& data, size_t hash_length = 512 / 8);
OPENDHT_PUBLIC void hash(const uint8_t* data, size_t data_length, uint8_t* hash, size_t hash_length);
/**
* Generates an encryption key from a text password,
@@ -340,19 +758,107 @@ Blob hash(const Blob& data);
* that can be transmitted in clear, and will be generated if
* not provided (32 bytes).
*/
Blob stretchKey(const std::string& password, Blob& salt);
OPENDHT_PUBLIC Blob stretchKey(std::string_view password, Blob& salt, size_t key_length = 512 / 8);
/**
* AES-GCM encryption. Key must be 128, 192 or 256 bits long (16, 24 or 32 bytes).
*/
Blob aesEncrypt(const Blob& data, const Blob& key);
Blob aesEncrypt(const Blob& data, const std::string& password);
OPENDHT_PUBLIC Blob aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key);
OPENDHT_PUBLIC inline Blob
aesEncrypt(const Blob& data, const Blob& key)
{
return aesEncrypt(data.data(), data.size(), key);
}
/**
* AES-GCM encryption with argon2 key derivation.
* This function uses `stretchKey` to generate an AES key from the password and a random salt.
* The result is a bundle including the salt that can be decrypted with `aesDecrypt(data, password)`.
* If needed, the salt or encrypted data can be individually extracted from the bundle with `aesGetSalt` and
* `aesGetEncrypted`.
* @param data: data to encrypt
* @param password: password to encrypt the data with
* @param salt: optional salt to use for key derivation. If not provided, a random salt will be generated.
*/
OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, std::string_view password, const Blob& salt = {});
/**
* AES-GCM decryption.
*/
Blob aesDecrypt(const Blob& data, const Blob& key);
Blob aesDecrypt(const Blob& data, const std::string& password);
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t* data, size_t data_length, const Blob& key);
OPENDHT_PUBLIC inline Blob
aesDecrypt(const Blob& data, const Blob& key)
{
return aesDecrypt(data.data(), data.size(), key);
}
OPENDHT_PUBLIC inline Blob
aesDecrypt(std::string_view data, const Blob& key)
{
return aesDecrypt((uint8_t*) data.data(), data.size(), key);
}
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t* data, size_t data_length, std::string_view password);
OPENDHT_PUBLIC inline Blob
aesDecrypt(const Blob& data, std::string_view password)
{
return aesDecrypt(data.data(), data.size(), password);
}
OPENDHT_PUBLIC inline Blob
aesDecrypt(std::string_view data, std::string_view password)
{
return aesDecrypt((uint8_t*) data.data(), data.size(), password);
}
/**
* Get raw AES key from password and salt stored with the encrypted data.
*/
OPENDHT_PUBLIC Blob aesGetKey(const uint8_t* data, size_t data_length, std::string_view password);
OPENDHT_PUBLIC Blob inline aesGetKey(const Blob& data, std::string_view password)
{
return aesGetKey(data.data(), data.size(), password);
}
/** Get the salt part of data password-encrypted with `aesEncrypt(data, password)` */
OPENDHT_PUBLIC Blob aesGetSalt(const uint8_t* data, size_t data_length);
OPENDHT_PUBLIC Blob inline aesGetSalt(const Blob& data)
{
return aesGetSalt(data.data(), data.size());
}
/** Get the encrypted data (ciphertext) part of data password-encrypted with `aesEncrypt(data, password)` */
OPENDHT_PUBLIC std::string_view aesGetEncrypted(const uint8_t* data, size_t data_length);
OPENDHT_PUBLIC std::string_view inline aesGetEncrypted(const Blob& data)
{
return aesGetEncrypted(data.data(), data.size());
}
/** Build an encrypted bundle that can be decrypted with aesDecrypt(data, password).
* @param encryptedData: result of `aesEncrypt(data, key)` or `aesGetEncrypted`
* @param salt: should match the encryption key and password so that `stretchKey(password, salk) == key`.
* Can be obtained from an existing bundle with `aesGetSalt`.
**/
OPENDHT_PUBLIC Blob aesBuildEncrypted(const uint8_t* encryptedData, size_t data_length, const Blob& salt);
OPENDHT_PUBLIC Blob inline aesBuildEncrypted(const Blob& encryptedData, const Blob& salt)
{
return aesBuildEncrypted(encryptedData.data(), encryptedData.size(), salt);
}
OPENDHT_PUBLIC Blob inline aesBuildEncrypted(std::string_view encryptedData, const Blob& salt)
{
return aesBuildEncrypted((const uint8_t*) encryptedData.data(), encryptedData.size(), salt);
}
/**
* Encrypts a payload for WebPush (RFC 8291).
* @param p256dh: The user's P-256 public key (uncompressed, 65 bytes).
* @param auth: The user's authentication secret (16 bytes).
* @param payload: The data to encrypt.
* @param privKey: (Optional) The sender's private key (for testing).
* @param salt: (Optional) The salt to use (for testing).
* @return The encrypted body (including salt, record size, keyid).
*/
OPENDHT_PUBLIC Blob webPushEncrypt(const Blob& p256dh,
const Blob& auth,
const uint8_t* payload,
size_t payload_length,
const PrivateKey& privKey = {},
const Blob& salt = {});
} // namespace crypto
} // namespace dht
+121
View File
@@ -0,0 +1,121 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include <vector>
#include <random>
namespace dht {
namespace crypto {
template<class T>
class secure_vector
{
public:
secure_vector() {}
secure_vector(secure_vector<T> const&) = default;
secure_vector(secure_vector<T>&&) = default;
explicit secure_vector(unsigned size)
: data_(size)
{}
explicit secure_vector(unsigned size, T _item)
: data_(size, _item)
{}
explicit secure_vector(const std::vector<T>& c)
: data_(c)
{}
secure_vector(std::vector<T>&& c)
: data_(std::move(c))
{}
~secure_vector() { clean(); }
static secure_vector<T> getRandom(size_t size)
{
secure_vector<T> ret(size);
std::random_device rdev;
#ifdef _WIN32
std::uniform_int_distribution<int> rand_byte {0, std::numeric_limits<uint8_t>::max()};
#else
std::uniform_int_distribution<uint8_t> rand_byte;
#endif
std::generate_n((uint8_t*) ret.data_.data(), ret.size() * sizeof(T), std::bind(rand_byte, std::ref(rdev)));
return ret;
}
secure_vector<T>& operator=(const secure_vector<T>& c)
{
if (&c == this)
return *this;
clean();
data_ = c.data_;
return *this;
}
secure_vector<T>& operator=(secure_vector<T>&& c)
{
if (&c == this)
return *this;
clean();
data_ = std::move(c.data_);
return *this;
}
secure_vector<T>& operator=(std::vector<T>&& c)
{
clean();
data_ = std::move(c);
return *this;
}
std::vector<T>& writable()
{
clean();
return data_;
}
const std::vector<T>& makeInsecure() const { return data_; }
const uint8_t* data() const { return data_.data(); }
void clean() { clean(data_.begin(), data_.end()); }
void clear()
{
clean();
data_.clear();
}
size_t size() const { return data_.size(); }
bool empty() const { return data_.empty(); }
void swap(secure_vector<T>& other) { data_.swap(other.data_); }
void resize(size_t s)
{
if (s == data_.size())
return;
if (s < data_.size()) {
// shrink
clean(data_.begin() + s, data_.end());
data_.resize(s);
} else {
// grow
auto data = std::move(data_); // move protected data
clear();
data_.resize(s);
std::copy(data.begin(), data.end(), data_.begin());
clean(data.begin(), data.end());
}
}
private:
/**
* Securely wipe memory
*/
static void clean(const typename std::vector<T>::iterator& i, const typename std::vector<T>::iterator& j)
{
volatile uint8_t* b = reinterpret_cast<uint8_t*>(&*i);
volatile uint8_t* e = reinterpret_cast<uint8_t*>(&*j);
std::fill(b, e, 0);
}
std::vector<T> data_;
};
using SecureBlob = secure_vector<uint8_t>;
} // namespace crypto
} // namespace dht
+44
View File
@@ -0,0 +1,44 @@
#pragma once
// Generic helper definitions for shared library support
#if defined _WIN32 || defined __CYGWIN__
#define OPENDHT_IMPORT __declspec(dllimport)
#define OPENDHT_EXPORT __declspec(dllexport)
#define OPENDHT_HIDDEN
#else
#define OPENDHT_IMPORT __attribute__ ((visibility ("default")))
#define OPENDHT_EXPORT __attribute__ ((visibility ("default")))
#define OPENDHT_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
// Now we use the generic helper definitions above to define OPENDHT_PUBLIC and OPENDHT_LOCAL.
// OPENDHT_PUBLIC is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build)
// OPENDHT_LOCAL is used for non-api symbols.
#ifdef opendht_EXPORTS // defined if OpenDHT is compiled as a shared library
#ifdef OPENDHT_BUILD // defined if we are building the OpenDHT shared library (instead of using it)
#define OPENDHT_PUBLIC OPENDHT_EXPORT
#else
#define OPENDHT_PUBLIC OPENDHT_IMPORT
#endif // OPENDHT_BUILD
#define OPENDHT_LOCAL OPENDHT_HIDDEN
#else // opendht_EXPORTS is not defined: this means OpenDHT is a static lib.
#define OPENDHT_PUBLIC
#define OPENDHT_LOCAL
#endif // opendht_EXPORTS
#ifdef opendht_c_EXPORTS // defined if OpenDHT is compiled as a shared library
#ifdef OPENDHT_C_BUILD // defined if we are building the OpenDHT shared library (instead of using it)
#define OPENDHT_C_PUBLIC OPENDHT_EXPORT
#else
#define OPENDHT_C_PUBLIC OPENDHT_IMPORT
#endif // OPENDHT_BUILD
#define OPENDHT_C_LOCAL OPENDHT_HIDDEN
#else // opendht_EXPORTS is not defined: this means OpenDHT is a static lib.
#define OPENDHT_C_PUBLIC
#define OPENDHT_C_LOCAL
#endif // opendht_EXPORTS
// bytes
#define HASH_LEN 20u
+119 -123
View File
@@ -1,109 +1,98 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "value.h"
#include "sockaddr.h"
namespace dht {
enum class ImStatus : uint8_t {
NONE = 0,
TYPING,
RECEIVED,
READ
};
enum class ImStatus : uint8_t { NONE = 0, TYPING, RECEIVED, READ };
}
MSGPACK_ADD_ENUM(dht::ImStatus);
MSGPACK_ADD_ENUM(dht::ImStatus)
namespace dht {
class DhtMessage : public Value::Serializable<DhtMessage>
class OPENDHT_PUBLIC DhtMessage : public Value::Serializable<DhtMessage>
{
public:
static const ValueType TYPE;
DhtMessage(std::string s = {}, Blob msg = {}) : service(s), data(msg) {}
DhtMessage(const std::string& s = {}, const Blob& msg = {})
: service(s)
, data(msg)
{}
std::string getService() const {
return service;
}
std::string getService() const { return service; }
static Value::Filter getFilter() { return {}; }
static bool storePolicy(InfoHash key, std::shared_ptr<Value>& value, InfoHash from, const sockaddr* from_addr, socklen_t from_len);
static bool storePolicy(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr&);
static Value::Filter ServiceFilter(std::string s);
static Value::Filter ServiceFilter(const std::string& s);
/** print value for debugging */
friend std::ostream& operator<< (std::ostream&, const DhtMessage&);
friend std::ostream& operator<<(std::ostream&, const DhtMessage&);
std::string service;
Blob data;
MSGPACK_DEFINE(service, data);
MSGPACK_DEFINE(service, data)
};
template <typename T>
template<typename T>
class SignedValue : public Value::Serializable<T>
{
private:
using BaseClass = Value::Serializable<T>;
public:
virtual void unpackValue(const Value& v) override {
if (v.owner)
virtual void unpackValue(const Value& v) override
{
if (v.owner) {
owner = v.owner;
from = v.owner->getId();
} else {
throw std::runtime_error("Value has no owner");
}
BaseClass::unpackValue(v);
}
static Value::Filter getFilter() {
return [](const Value& v){ return v.isSigned(); };
static Value::Filter getFilter()
{
return [](const Value& v) {
return v.isSigned();
};
}
Sp<crypto::PublicKey> owner;
dht::InfoHash from;
};
template <typename T>
template<typename T>
class EncryptedValue : public SignedValue<T>
{
public:
using BaseClass = SignedValue<T>;
public:
virtual void unpackValue(const Value& v) override {
virtual void unpackValue(const Value& v) override
{
if (!v.recipient) {
throw std::runtime_error("Value has no recipient");
}
to = v.recipient;
BaseClass::unpackValue(v);
}
static Value::Filter getFilter() {
return Value::Filter::chain(
BaseClass::getFilter(),
[](const Value& v){ return v.recipient != InfoHash(); }
);
static Value::Filter getFilter()
{
return Value::Filter::chain(BaseClass::getFilter(),
[](const Value& v) { return static_cast<bool>(v.recipient); });
}
dht::InfoHash to;
};
class ImMessage : public SignedValue<ImMessage>
class OPENDHT_PUBLIC ImMessage : public SignedValue<ImMessage>
{
private:
using BaseClass = SignedValue<ImMessage>;
@@ -113,23 +102,44 @@ public:
ImMessage() {}
ImMessage(dht::Value::Id id, std::string&& m, long d = 0)
: id(id), msg(std::move(m)), date(d) {}
: id(id)
, msg(std::move(m))
, date(d)
{}
ImMessage(dht::Value::Id id, std::string&& dt, std::string&& m, long d = 0)
: id(id)
, msg(std::move(m))
, datatype(std::move(dt))
, date(d)
{}
ImMessage(dht::Value::Id id, std::string&& dt, std::string&& m, std::map<std::string, std::string>&& md, long d = 0)
: id(id)
, msg(std::move(m))
, datatype(std::move(dt))
, metadatas(std::move(md))
, date(d)
{}
virtual void unpackValue(const Value& v) override {
virtual void unpackValue(const Value& v) override
{
to = v.recipient;
SignedValue::unpackValue(v);
}
static Value::Filter getFilter() { return SignedValue::getFilter(); }
dht::InfoHash to;
dht::Value::Id id;
dht::Value::Id id {0};
std::string msg;
std::string datatype;
std::map<std::string, std::string> metadatas;
long date {0};
ImStatus status {ImStatus::NONE};
MSGPACK_DEFINE_MAP(id, msg, date, status);
MSGPACK_DEFINE_MAP(id, msg, date, status, datatype, metadatas)
};
class TrustRequest : public EncryptedValue<TrustRequest>
class OPENDHT_PUBLIC TrustRequest : public EncryptedValue<TrustRequest>
{
private:
using BaseClass = EncryptedValue<TrustRequest>;
@@ -138,19 +148,26 @@ public:
static const ValueType TYPE;
TrustRequest() {}
TrustRequest(std::string s) : service(s) {}
TrustRequest(std::string s, const Blob& d) : service(s), payload(d) {}
TrustRequest(std::string s, std::string ci = {})
: service(s)
, conversationId(ci)
{}
TrustRequest(std::string s, std::string ci, const Blob& d)
: service(s)
, conversationId(ci)
, payload(d)
{}
static Value::Filter getFilter() {
return EncryptedValue::getFilter();
}
static Value::Filter getFilter() { return EncryptedValue::getFilter(); }
std::string service;
std::string conversationId;
Blob payload;
MSGPACK_DEFINE(service, payload);
bool confirm {false};
MSGPACK_DEFINE_MAP(service, conversationId, payload, confirm)
};
class IceCandidates : public EncryptedValue<IceCandidates>
class OPENDHT_PUBLIC IceCandidates : public EncryptedValue<IceCandidates>
{
private:
using BaseClass = EncryptedValue<IceCandidates>;
@@ -159,44 +176,47 @@ public:
static const ValueType TYPE;
IceCandidates() {}
IceCandidates(Value::Id msg_id, Blob ice) : id(msg_id), ice_data(ice) {}
IceCandidates(Value::Id msg_id, Blob ice)
: id(msg_id)
, ice_data(ice)
{}
static Value::Filter getFilter() {
return EncryptedValue::getFilter();
}
static Value::Filter getFilter() { return EncryptedValue::getFilter(); }
template <typename Packer>
template<typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_array(2);
pk.pack(id);
#if 1
pk.pack_bin(ice_data.size());
pk.pack_bin_body((const char*)ice_data.data(), ice_data.size());
pk.pack_bin_body((const char*) ice_data.data(), ice_data.size());
#else
// hack for backward compatibility with old opendht compiled with msgpack 1.0
// remove when enough people have moved to new versions
// remove when enough people have moved to new versions
pk.pack_array(ice_data.size());
for (uint8_t b : ice_data)
pk.pack(b);
#endif
}
virtual void msgpack_unpack(msgpack::object o)
virtual void msgpack_unpack(const msgpack::object& o)
{
if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
if (o.via.array.size < 2) throw msgpack::type_error();
if (o.type != msgpack::type::ARRAY)
throw msgpack::type_error();
if (o.via.array.size < 2)
throw msgpack::type_error();
id = o.via.array.ptr[0].as<Value::Id>();
ice_data = unpackBlob(o.via.array.ptr[1]);
}
Value::Id id;
Value::Id id {0};
Blob ice_data;
};
/* "Peer" announcement
*/
class IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
class OPENDHT_PUBLIC IpServiceAnnouncement : public Value::Serializable<IpServiceAnnouncement>
{
private:
using BaseClass = Value::Serializable<IpServiceAnnouncement>;
@@ -204,75 +224,51 @@ private:
public:
static const ValueType TYPE;
IpServiceAnnouncement(in_port_t p = 0) {
ss.ss_family = 0;
setPort(p);
IpServiceAnnouncement(sa_family_t family = AF_UNSPEC, in_port_t p = 0)
{
addr.setFamily(family);
addr.setPort(p);
}
IpServiceAnnouncement(const sockaddr* sa, socklen_t sa_len) {
if (sa)
std::copy_n((const uint8_t*)sa, sa_len, (uint8_t*)&ss);
}
IpServiceAnnouncement(const SockAddr& sa)
: addr(sa)
{}
IpServiceAnnouncement(const Blob& b) {
msgpack_unpack(unpackMsg(b).get());
}
IpServiceAnnouncement(const Blob& b) { msgpack_unpack(unpackMsg(b).get()); }
template <typename Packer>
template<typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_array(2);
pk.pack(getPort());
if (ss.ss_family == AF_INET) {
pk.pack_bin(sizeof(in_addr));
pk.pack_bin_body((const char*)&reinterpret_cast<const sockaddr_in*>(&ss)->sin_addr, sizeof(in_addr));
} else if (ss.ss_family == AF_INET6) {
pk.pack_bin(sizeof(in6_addr));
pk.pack_bin_body((const char*)&reinterpret_cast<const sockaddr_in6*>(&ss)->sin6_addr, sizeof(in6_addr));
}
pk.pack_bin(addr.getLength());
pk.pack_bin_body((const char*) addr.get(), addr.getLength());
}
virtual void msgpack_unpack(msgpack::object o)
virtual void msgpack_unpack(const msgpack::object& o)
{
if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
if (o.via.array.size < 2) throw msgpack::type_error();
setPort(o.via.array.ptr[0].as<in_port_t>());
auto ip_dat = o.via.array.ptr[1].as<Blob>();
if (ip_dat.size() == sizeof(in_addr))
std::copy(ip_dat.begin(), ip_dat.end(), (char*)&reinterpret_cast<sockaddr_in*>(&ss)->sin_addr);
else if (ip_dat.size() == sizeof(in6_addr))
std::copy(ip_dat.begin(), ip_dat.end(), (char*)&reinterpret_cast<sockaddr_in6*>(&ss)->sin6_addr);
if (o.type == msgpack::type::BIN)
addr = {(sockaddr*) o.via.bin.ptr, (socklen_t) o.via.bin.size};
else
throw msgpack::type_error();
}
in_port_t getPort() const {
return ntohs(reinterpret_cast<const sockaddr_in*>(&ss)->sin_port);
}
void setPort(in_port_t p) {
reinterpret_cast<sockaddr_in*>(&ss)->sin_port = htons(p);
}
in_port_t getPort() const { return addr.getPort(); }
void setPort(in_port_t p) { addr.setPort(p); }
sockaddr_storage getPeerAddr() const {
return ss;
}
const SockAddr& getPeerAddr() const { return addr; }
virtual const ValueType& getType() const {
return TYPE;
}
virtual const ValueType& getType() const { return TYPE; }
static bool storePolicy(InfoHash, std::shared_ptr<Value>&, InfoHash, const sockaddr*, socklen_t);
static bool storePolicy(InfoHash, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&);
/** print value for debugging */
friend std::ostream& operator<< (std::ostream&, const IpServiceAnnouncement&);
friend std::ostream& operator<<(std::ostream&, const IpServiceAnnouncement&);
private:
sockaddr_storage ss;
SockAddr addr;
};
OPENDHT_PUBLIC extern const std::array<std::reference_wrapper<const ValueType>, 5> DEFAULT_TYPES;
extern const std::array<std::reference_wrapper<const ValueType>, 5> DEFAULT_TYPES;
OPENDHT_PUBLIC extern const std::array<std::reference_wrapper<const ValueType>, 1> DEFAULT_INSECURE_TYPES;
extern const std::array<std::reference_wrapper<const ValueType>, 1> DEFAULT_INSECURE_TYPES;
}
} // namespace dht
+384 -264
View File
@@ -1,24 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h"
@@ -28,15 +9,13 @@
#include "scheduler.h"
#include "routing_table.h"
#include "callbacks.h"
#include "dht_interface.h"
#include <string>
#include <array>
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <functional>
#include <algorithm>
#include <memory>
#ifdef _WIN32
@@ -45,7 +24,15 @@
namespace dht {
namespace net {
struct Request;
} /* namespace net */
struct Storage;
struct ValueStorage;
class StorageBucket;
struct Listener;
struct LocalListener;
/**
* Main Dht class.
@@ -54,42 +41,41 @@ struct Request;
* Must be given open UDP sockets and ::periodic must be
* called regularly.
*/
class Dht {
class OPENDHT_PUBLIC Dht final : public DhtInterface
{
public:
// [[deprecated]]
using NodeExport = dht::NodeExport;
// [[deprecated]]
using Status = NodeStatus;
Dht();
/**
* Initialise the Dht with two open sockets (for IPv4 and IP6)
* and an ID for the node.
*/
Dht(int s, int s6, Config config);
Dht(std::unique_ptr<net::DatagramSocket>&& sock,
const Config& config,
const Sp<Logger>& l = {},
std::unique_ptr<std::mt19937_64>&& rd = {});
virtual ~Dht();
/**
* Get the ID of the node.
*/
inline const InfoHash& getNodeId() const { return myid; }
inline const InfoHash& getNodeId() const override { return myid; }
void setOnPublicAddressChanged(PublicAddressChangedCb cb) override { publicAddressChangedCb_ = std::move(cb); }
NodeStatus updateStatus(sa_family_t af) override;
/**
* Get the current status of the node for the given family.
*/
NodeStatus getStatus(sa_family_t af) const;
NodeStatus getStatus(sa_family_t af) const override { return dht(af).status; }
NodeStatus getStatus() const {
return std::max(getStatus(AF_INET), getStatus(AF_INET6));
}
NodeStatus getStatus() const override { return std::max(getStatus(AF_INET), getStatus(AF_INET6)); }
net::DatagramSocket* getSocket() const override { return network_engine.getSocket(); };
/**
* Performs final operations before quitting.
*/
void shutdown(ShutdownCallback cb);
void shutdown(ShutdownCallback cb, bool stop = false) override;
/**
* Returns true if the node is running (have access to an open socket).
@@ -97,35 +83,36 @@ public:
* af: address family. If non-zero, will return true if the node
* is running for the provided family.
*/
bool isRunning(sa_family_t af = 0) const;
bool isRunning(sa_family_t af = 0) const override;
/**
* Enable or disable logging of DHT internal messages
*/
void setLoggers(LogMethod error = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG);
virtual void registerType(const ValueType& type) override { types.registerType(type); }
const ValueType& getType(ValueType::Id type_id) const override { return types.getType(type_id); }
virtual void registerType(const ValueType& type) {
types[type.id] = type;
}
const ValueType& getType(ValueType::Id type_id) const {
const auto& t_it = types.find(type_id);
return (t_it == types.end()) ? ValueType::USER_DATA : t_it->second;
void addBootstrap(const std::string& host, const std::string& service) override
{
bootstrap_nodes.emplace_back(host, service);
startBootstrap();
}
void clearBootstrap() override { bootstrap_nodes.clear(); }
/**
* Insert a node in the main routing table.
* The node is not pinged, so this should be
* used to bootstrap efficiently from previously known nodes.
*/
bool insertNode(const InfoHash& id, const sockaddr*, socklen_t);
bool insertNode(const NodeExport& n) {
return insertNode(n.id, reinterpret_cast<const sockaddr*>(&n.ss), n.sslen);
void insertNode(const InfoHash& id, const SockAddr&) override;
void insertNode(const NodeExport& n) override { insertNode(n.id, n.addr); }
void pingNode(SockAddr, DoneCallbackSimple&& cb = {}) override;
time_point periodic(const uint8_t* buf, size_t buflen, SockAddr, const time_point& now) override;
time_point periodic(
const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override
{
return periodic(buf, buflen, SockAddr(from, fromlen), now);
}
int pingNode(const sockaddr*, socklen_t);
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr *from, socklen_t fromlen);
/**
* Get a value by searching on all available protocols (IPv4, IPv6),
* and call the provided get callback when values are found at key.
@@ -133,67 +120,94 @@ public:
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param donecb a function called when the operation is complete.
cb and donecb won't be called again afterward.
cb and donecb won't be called again afterward.
* @param f a filter function used to prefilter values.
*/
virtual void get(const InfoHash& key, GetCallback cb, DoneCallback donecb={}, Value::Filter&& f={});
virtual void get(const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f={}) {
get(key, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f));
virtual void get(
const InfoHash& key, GetCallback cb, DoneCallback donecb = {}, Value::Filter&& f = {}, Where&& w = {}) override;
virtual void get(const InfoHash& key,
GetCallback cb,
DoneCallbackSimple donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}) {
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f));
virtual void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallback donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}) {
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f));
virtual void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallbackSimple donecb,
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
/**
* Similar to Dht::get, but sends a Query to filter data remotely.
* @param key the key for which to query data for.
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param done_cb a function called when the operation is complete.
cb and done_cb won't be called again afterward.
* @param q a query used to filter values on the remotes before they send a
* response.
*/
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override;
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override
{
query(key, cb, bindDoneCb(done_cb), std::forward<Query>(q));
}
/**
* Get locally stored data for the given hash.
*/
std::vector<std::shared_ptr<Value>> getLocal(const InfoHash& key, Value::Filter f = Value::AllFilter()) const;
std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override;
/**
* Get locally stored data for the given key and value id.
*/
std::shared_ptr<Value> getLocalById(const InfoHash& key, Value::Id vid) const;
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override;
/**
* Announce a value on all available protocols (IPv4, IPv6), and
* automatically re-announce when it's about to expire.
* Announce a value on all available protocols (IPv4, IPv6).
*
* The operation will start as soon as the node is connected to the network.
* The done callback will be called once, when the first announce succeeds, or fails.
*
* A "put" operation will never end by itself because the value will need to be
* reannounced on a regular basis.
* User can call #cancelPut(InfoHash, Value::Id) to cancel a put operation.
*/
void put(const InfoHash& key,
std::shared_ptr<Value>,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false);
Sp<Value>,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override;
void put(const InfoHash& key,
const std::shared_ptr<Value>& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, v, bindDoneCb(cb), created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false)
Value&& v,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, std::make_shared<Value>(std::move(v)), cb, created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
Value&& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, std::forward<Value>(v), bindDoneCb(cb), created, permanent);
}
@@ -201,18 +215,18 @@ public:
/**
* Get data currently being put at the given hash.
*/
std::vector<std::shared_ptr<Value>> getPut(const InfoHash&);
std::vector<Sp<Value>> getPut(const InfoHash&) const override;
/**
* Get data currently being put at the given hash with the given id.
*/
std::shared_ptr<Value> getPut(const InfoHash&, const Value::Id&);
Sp<Value> getPut(const InfoHash&, const Value::Id&) const override;
/**
* Stop any put/announce operation at the given location,
* for the value with the given id.
*/
bool cancelPut(const InfoHash&, const Value::Id&);
bool cancelPut(const InfoHash&, const Value::Id&) override;
/**
* Listen on the network for any changes involving a specified hash.
@@ -221,81 +235,124 @@ public:
*
* @return a token to cancel the listener later.
*/
virtual size_t listen(const InfoHash&, GetCallback, Value::Filter&&={});
virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}) {
return listen(key, bindGetCb(cb), std::forward<Value::Filter>(f));
size_t listen(const InfoHash&, ValueCallback, Value::Filter = {}, Where = {}) override;
size_t listen(const InfoHash& key, GetCallback cb, Value::Filter f = {}, Where w = {}) override
{
return listen(
key,
[cb](const std::vector<Sp<Value>>& vals, bool expired) {
if (not expired)
return cb(vals);
return true;
},
std::forward<Value::Filter>(f),
std::forward<Where>(w));
}
size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {}) override
{
return listen(key, bindGetCb(cb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual bool cancelListen(const InfoHash&, size_t token);
bool cancelListen(const InfoHash&, size_t token) override;
/**
* Inform the DHT of lower-layer connectivity changes.
* This will cause the DHT to assume a public IP address change.
* The DHT will recontact neighbor nodes, re-register for listen ops etc.
*/
void connectivityChanged();
void connectivityChanged(sa_family_t) override;
void connectivityChanged() override
{
connectivityChanged(AF_INET);
connectivityChanged(AF_INET6);
}
/**
* Get the list of good nodes for local storage saving purposes
* The list is ordered to minimize the back-to-work delay.
*/
std::vector<NodeExport> exportNodes();
std::vector<NodeExport> exportNodes() const override;
std::vector<ValuesExport> exportValues() const;
void importValues(const std::vector<ValuesExport>&);
std::vector<ValuesExport> exportValues() const override;
void importValues(const std::vector<ValuesExport>&) override;
int getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return,
unsigned *incoming_return) const;
std::string getStorageLog() const;
std::string getRoutingTablesLog(sa_family_t) const;
std::string getSearchesLog(sa_family_t) const;
void saveState(const std::string& path) const;
void loadState(const std::string& path);
void dumpTables() const;
std::vector<unsigned> getNodeMessageStats(bool in = false) {
NodeStats getNodesStats(sa_family_t af) const override;
std::string getStorageLog() const override;
std::string getStorageLog(const InfoHash&) const override;
std::string getRoutingTablesLog(sa_family_t) const override;
std::string getSearchesLog(sa_family_t) const override;
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const override;
void dumpTables() const override;
std::vector<unsigned> getNodeMessageStats(bool in = false) override
{
return network_engine.getNodeMessageStats(in);
}
/**
* Set the in-memory storage limit in bytes
* Set the in-memory storage limit in bytes for remote values
*/
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) {
max_store_size = limit;
void setStorageLimit(size_t limit = 0) override { max_store_size = limit == 0 ? STORAGE_LIMIT_DEFAULT : limit; }
size_t getStorageLimit() const override { return max_store_size; }
/**
* Set the in-memory storage limit in bytes for locally stored values
*/
void setLocalStorageLimit(size_t limit = 0) override
{
max_local_store_size = limit == 0 ? STORAGE_LIMIT_UNLIMITED : limit;
}
size_t getLocalStorageLimit() const override { return max_local_store_size; }
/**
* Returns the total memory usage of stored values and the number
* of stored values.
*/
std::pair<size_t, size_t> getStoreSize() const {
return {total_store_size, total_values};
std::pair<size_t, size_t> getStoreSize() const override { return {total_store_size, total_values}; }
std::pair<size_t, size_t> getLocalStoreSize() const override;
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override;
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>&) override
{
return PushNotificationResult::IgnoredDisabled;
}
std::vector<Address> getPublicAddress(sa_family_t family = 0);
protected:
Logger DHT_LOG;
void resubscribe(unsigned) {}
private:
/* When performing a search, we search for up to SEARCH_NODES closest nodes
to the destination, and use the additional ones to backtrack if any of
the target 8 turn out to be dead. */
static constexpr unsigned SEARCH_NODES {14};
/* Concurrent requests during a search */
static constexpr unsigned SEARCH_REQUESTS {4};
/* The number of bad nodes is limited in order to help determine
* presence of connectivity changes. See
* https://github.com/savoirfairelinux/opendht/issues/137 for details.
*
* According to the tables, 25 is a good average value for big networks. If
* the network is small, normal search expiration process will handle the
* situation.
* */
static constexpr unsigned SEARCH_MAX_BAD_NODES {25};
/* Concurrent search nodes requested count */
static constexpr unsigned MAX_REQUESTED_SEARCH_NODES {4};
/* Number of listening nodes */
static constexpr unsigned LISTEN_NODES {4};
/* The maximum number of values we store for a given hash. */
static constexpr unsigned MAX_VALUES {1024};
/* The maximum number of hashes we're willing to track. */
static constexpr unsigned MAX_HASHES {16384};
static constexpr unsigned MAX_HASHES {1024 * 1024 * 1024};
/* The maximum number of searches we keep data about. */
static constexpr unsigned MAX_SEARCHES {2048};
static constexpr unsigned MAX_SEARCHES {1024 * 1024};
static constexpr std::chrono::minutes MAX_STORAGE_MAINTENANCE_EXPIRE_TIME {10};
@@ -303,103 +360,70 @@ private:
static constexpr std::chrono::minutes SEARCH_EXPIRE_TIME {62};
/* Timeout for listen */
static constexpr std::chrono::seconds LISTEN_EXPIRE_TIME {30};
static constexpr duration LISTEN_EXPIRE_TIME {std::chrono::seconds(30)};
static constexpr duration LISTEN_EXPIRE_TIME_PUBLIC {std::chrono::minutes(5)};
static constexpr std::chrono::seconds REANNOUNCE_MARGIN {5};
static constexpr duration REANNOUNCE_MARGIN {std::chrono::seconds(10)};
static constexpr size_t TOKEN_SIZE {64};
static constexpr std::chrono::seconds BOOTSTRAP_PERIOD {10};
static constexpr size_t TOKEN_SIZE {32};
// internal structures
struct SearchNode;
/**
* A single "get" operation data
*/
struct Get {
time_point start;
Value::Filter filter;
GetCallback get_cb;
DoneCallback done_cb;
};
/**
* A single "put" operation data
*/
struct Announce {
bool permanent;
std::shared_ptr<Value> value;
time_point created;
DoneCallback callback;
};
/**
* A single "listen" operation data
*/
struct LocalListener {
Value::Filter filter;
GetCallback get_cb;
};
/**
* A search is a list of the nodes we think are responsible
* for storing values for a given hash.
*/
struct Get;
struct Announce;
struct Search;
struct ValueStorage {
std::shared_ptr<Value> data {};
time_point time {};
ValueStorage() {}
ValueStorage(const std::shared_ptr<Value>& v, time_point t) : data(v), time(t) {}
};
/**
* Foreign nodes asking for updates about an InfoHash.
*/
struct Listener {
size_t rid {};
time_point time {};
/*constexpr*/ Listener(size_t rid, time_point t) : rid(rid), time(t) {}
void refresh(size_t tid, time_point t) {
rid = tid;
time = t;
}
};
struct Storage;
// prevent copy
Dht(const Dht&) = delete;
Dht& operator=(const Dht&) = delete;
std::mt19937_64 rd;
InfoHash myid {};
std::array<uint8_t, 8> secret {{}};
std::array<uint8_t, 8> oldsecret {{}};
uint64_t secret {};
uint64_t oldsecret {};
// registred types
std::map<ValueType::Id, ValueType> types;
TypeStore types;
// are we a bootstrap node ?
// note: Any running node can be used as a bootstrap node.
// Only nodes running only as bootstrap nodes should
// be put in bootstrap mode.
const bool is_bootstrap {false};
using SearchMap = std::map<InfoHash, Sp<Search>>;
using ReportedAddr = std::pair<unsigned, SockAddr>;
// the stuff
RoutingTable buckets {};
RoutingTable buckets6 {};
struct Kad
{
RoutingTable buckets {};
SearchMap searches {};
unsigned pending_pings {0};
NodeStatus status;
std::vector<ReportedAddr> reported_addr;
std::vector<Storage> store;
NodeStatus getStatus(time_point now) const;
NodeStats getNodesStats(time_point now, const InfoHash& myid) const;
};
Kad dht4 {};
Kad dht6 {};
PublicAddressChangedCb publicAddressChangedCb_ {};
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;
std::unique_ptr<StorageBucket> local_store_quota;
size_t total_values {0};
size_t total_store_size {0};
size_t max_store_size {DEFAULT_STORAGE_LIMIT};
size_t max_store_keys {MAX_HASHES};
size_t max_store_size {STORAGE_LIMIT_DEFAULT};
size_t max_local_store_size {STORAGE_LIMIT_UNLIMITED};
std::map<InfoHash, std::shared_ptr<Search>> searches4 {};
std::map<InfoHash, std::shared_ptr<Search>> searches6 {};
uint16_t search_id {0};
size_t max_searches {MAX_SEARCHES};
size_t search_id {0};
// map a global listen token to IPv4, IPv6 specific listen tokens.
// 0 is the invalid token.
@@ -407,116 +431,212 @@ private:
size_t listener_token {1};
// timing
Scheduler scheduler {};
std::shared_ptr<Scheduler::Job> nextNodesConfirmation {};
time_point mybucket_grow_time {time_point::min()}, mybucket6_grow_time {time_point::min()};
Scheduler scheduler;
Sp<Scheduler::Job> nextNodesConfirmation {};
Sp<Scheduler::Job> nextStorageMaintenance {};
NetworkEngine network_engine;
net::NetworkEngine network_engine;
using ReportedAddr = std::pair<unsigned, Address>;
std::vector<ReportedAddr> reported_addr;
std::string persistPath;
// are we a bootstrap node ?
// note: Any running node can be used as a bootstrap node.
// Only nodes running only as bootstrap nodes should
// be put in bootstrap mode.
const bool is_bootstrap {false};
const bool maintain_storage {false};
const bool public_stable {false};
inline const duration& getListenExpiration() const
{
return public_stable ? LISTEN_EXPIRE_TIME_PUBLIC : LISTEN_EXPIRE_TIME;
}
void rotateSecrets();
Blob makeToken(const sockaddr *sa, bool old) const;
bool tokenMatch(const Blob& token, const sockaddr *sa) const;
Blob makeToken(const SockAddr&, bool old) const;
bool tokenMatch(const Blob& token, const SockAddr&) const;
void reportedAddr(const sockaddr *sa, socklen_t sa_len);
void reportedAddr(const SockAddr&);
// Storage
decltype(Dht::store)::iterator findStorage(const InfoHash& id);
decltype(Dht::store)::const_iterator findStorage(const InfoHash& id) const;
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {}, int version = 0);
bool storageStore(const InfoHash& id,
const Sp<Value>& value,
time_point created,
const SockAddr& sa = {},
bool permanent = false,
time_point expiration = time_point::min());
bool storageRefresh(const InfoHash& id, Value::Id vid);
void expireStore();
void expireStorage(InfoHash h);
void expireStore(decltype(store)::iterator);
void storageAddListener(const InfoHash& id, const std::shared_ptr<Node>& node, size_t tid);
bool storageStore(const InfoHash& id, const std::shared_ptr<Value>& value, time_point created);
void expireStorage();
void storageChanged(Storage& st, ValueStorage&);
void storageRemoved(const InfoHash& id, Storage& st, const std::vector<Sp<Value>>& values, size_t totalSize);
void storageChanged(const InfoHash& id, Storage& st, const Sp<Value>&, bool newValue);
std::string printStorageLog(const decltype(store)::value_type&) const;
/**
* For a given storage, if values don't belong there anymore because this
* node is too far from the target, values are sent to the appropriate
* nodes.
*/
void dataPersistence();
size_t maintainStorage(InfoHash id, bool force=false, DoneCallback donecb=nullptr);
void dataPersistence(InfoHash id);
size_t maintainStorage(decltype(store)::value_type&, bool force = false, const DoneCallback& donecb = {});
// Buckets
Bucket* findBucket(const InfoHash& id, sa_family_t af) {
RoutingTable::iterator b;
switch (af) {
case AF_INET:
b = buckets.findBucket(id);
return b == buckets.end() ? nullptr : &(*b);
case AF_INET6:
b = buckets6.findBucket(id);
return b == buckets6.end() ? nullptr : &(*b);
default:
return nullptr;
}
Kad& dht(sa_family_t af) { return af == AF_INET ? dht4 : dht6; }
const Kad& dht(sa_family_t af) const { return af == AF_INET ? dht4 : dht6; }
RoutingTable& buckets(sa_family_t af) { return dht(af).buckets; }
const RoutingTable& buckets(sa_family_t af) const { return dht(af).buckets; }
Bucket* findBucket(const InfoHash& id, sa_family_t af)
{
auto& b = buckets(af);
auto it = b.findBucket(id);
return it == b.end() ? nullptr : &(*it);
}
const Bucket* findBucket(const InfoHash& id, sa_family_t af) const {
const Bucket* findBucket(const InfoHash& id, sa_family_t af) const
{
return const_cast<Dht*>(this)->findBucket(id, af);
}
void expireBuckets(RoutingTable&);
int sendCachedPing(Bucket& b);
void sendCachedPing(Bucket& b);
bool bucketMaintenance(RoutingTable&);
void dumpBucket(const Bucket& b, std::ostream& out) const;
void bootstrap();
void startBootstrap();
void stopBootstrap();
// Nodes
void onNewNode(const std::shared_ptr<Node>& node, int confirm);
std::shared_ptr<Node> findNode(const InfoHash& id, sa_family_t af);
const std::shared_ptr<Node> findNode(const InfoHash& id, sa_family_t af) const;
bool trySearchInsert(const std::shared_ptr<Node>& node);
void onNewNode(const Sp<Node>& node, int confirm);
const Sp<Node> findNode(const InfoHash& id, sa_family_t af) const;
bool trySearchInsert(const Sp<Node>& node);
// Searches
inline SearchMap& searches(sa_family_t af) { return dht(af).searches; }
inline const SearchMap& searches(sa_family_t af) const { return dht(af).searches; }
/**
* Low-level method that will perform a search on the DHT for the
* specified infohash (id), using the specified IP version (IPv4 or IPv6).
* The values can be filtered by an arbitrary provided filter.
* Low-level method that will perform a search on the DHT for the specified
* infohash (id), using the specified IP version (IPv4 or IPv6).
*/
std::shared_ptr<Search> search(const InfoHash& id, sa_family_t af, GetCallback = nullptr, DoneCallback = nullptr, Value::Filter = Value::AllFilter());
void announce(const InfoHash& id, sa_family_t af, std::shared_ptr<Value> value, DoneCallback callback, time_point created=time_point::max(), bool permanent = false);
size_t listenTo(const InfoHash& id, sa_family_t af, GetCallback cb, Value::Filter f = Value::AllFilter());
Sp<Search> search(const InfoHash& id,
sa_family_t af,
GetCallback = {},
QueryCallback = {},
DoneCallback = {},
Value::Filter = {},
const Sp<Query>& q = {});
void bootstrapSearch(Search& sr);
Search *findSearch(unsigned short tid, sa_family_t af);
void announce(const InfoHash& id,
sa_family_t af,
Sp<Value> value,
DoneCallback callback,
time_point created = time_point::max(),
bool permanent = false);
size_t listenTo(const InfoHash& id, sa_family_t af, ValueCallback cb, Value::Filter f = {}, const Sp<Query>& q = {});
/**
* Refill the search with good nodes if possible.
*
* @param sr The search to refill.
*
* @return the number inserted nodes.
*/
unsigned refill(Search& sr);
void expireSearches();
void confirmNodes();
void expire();
void onConnected();
void onDisconnected();
/**
* Generic function to execute when a 'get' request has completed.
*
* @param status The request passed by the network engine.
* @param answer The answer from the network engine.
* @param ws A weak pointer to the search concerned by the request.
* @param query The query sent to the node.
*/
void searchNodeGetDone(const net::Request& status,
net::RequestAnswer&& answer,
std::weak_ptr<Search> ws,
Sp<Query> query);
/**
* Generic function to execute when a 'get' request expires.
*
* @param status The request passed by the network engine.
* @param over Whether we're done to try sending the request to the node
* or not. This lets us mark a node as candidate.
* @param ws A weak pointer to the search concerned by the request.
* @param query The query sent to the node.
*/
void searchNodeGetExpired(const net::Request& status, bool over, std::weak_ptr<Search> ws, Sp<Query> query);
/**
* This method recovers sends individual request for values per id.
*
* @param ws A weak pointer to the Search.
* @param query The initial query passed through the API.
* @param n The node to which send the requests.
*/
void paginate(std::weak_ptr<Search> ws, Sp<Query> query, SearchNode* n);
/**
* If update is true, this method will also send message to synced but non-updated search nodes.
*/
SearchNode* searchSendGetValues(std::shared_ptr<Search> sr, SearchNode *n = nullptr, bool update = true);
SearchNode* searchSendGetValues(Sp<Search> sr, SearchNode* n = nullptr, bool update = true);
/**
* Forwards an 'announce' request for a list of nodes to the network engine.
*
* @param sr The search for which we want to announce a value.
* @param announce The 'announce' structure.
*/
void searchSendAnnounceValue(const Sp<Search>& sr, unsigned syncLevel = TARGET_NODES);
/**
* Main process of a Search's operations. This function will demand the
* network engine to send requests packets for all pending operations
* ('get', 'put' and 'listen').
*
* @param sr The search to execute its operations.
*/
void searchStep(std::weak_ptr<Search> ws);
void searchSynchedNodeListen(const Sp<Search>&, SearchNode&);
void searchStep(std::shared_ptr<Search> sr);
void dumpSearch(const Search& sr, std::ostream& out) const;
bool neighbourhoodMaintenance(RoutingTable&);
void processMessage(const uint8_t *buf, size_t buflen, const sockaddr *from, socklen_t fromlen);
void onError(std::shared_ptr<Request> node, DhtProtocolException e);
void onError(Sp<net::Request> node, net::DhtProtocolException e);
/* when our address is reported by a distant peer. */
void onReportedAddr(const InfoHash& id, sockaddr* sa , socklen_t salen);
void onReportedAddr(const InfoHash& id, const SockAddr&);
/* when we receive a ping request */
NetworkEngine::RequestAnswer onPing(std::shared_ptr<Node> node);
net::RequestAnswer onPing(Sp<Node> node);
/* when we receive a "find node" request */
NetworkEngine::RequestAnswer onFindNode(std::shared_ptr<Node> node, InfoHash& hash, want_t want);
void onFindNodeDone(const Request& status, NetworkEngine::RequestAnswer& a, std::shared_ptr<Search> sr);
net::RequestAnswer onFindNode(Sp<Node> node, const InfoHash& hash, want_t want);
void onFindNodeDone(const Sp<Node>& status, net::RequestAnswer& a, Sp<Search> sr);
/* when we receive a "get values" request */
NetworkEngine::RequestAnswer onGetValues(std::shared_ptr<Node> node, InfoHash& hash, want_t want);
void onGetValuesDone(const Request& status, NetworkEngine::RequestAnswer& a, std::shared_ptr<Search> sr);
net::RequestAnswer onGetValues(Sp<Node> node, const InfoHash& hash, want_t want, const Query& q);
void onGetValuesDone(const Sp<Node>& status, net::RequestAnswer& a, Sp<Search>& sr, const Sp<Query>& orig_query);
/* when we receive a listen request */
NetworkEngine::RequestAnswer onListen(std::shared_ptr<Node> node, InfoHash& hash, Blob& token, size_t rid);
void onListenDone(const Request& status, NetworkEngine::RequestAnswer& a, std::shared_ptr<Search>& sr);
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>& node, net::RequestAnswer& a, Sp<Search>& sr);
/* when we receive an announce request */
NetworkEngine::RequestAnswer onAnnounce(std::shared_ptr<Node> node,
InfoHash& hash, Blob& token, std::vector<std::shared_ptr<Value>> v, time_point created);
void onAnnounceDone(const Request& status, NetworkEngine::RequestAnswer& a, std::shared_ptr<Search>& sr);
net::RequestAnswer onAnnounce(Sp<Node> node,
const InfoHash& hash,
const Blob& token,
const std::vector<Sp<Value>>& v,
const time_point& created);
net::RequestAnswer onRefresh(Sp<Node> node, const InfoHash& hash, const Blob& token, const Value::Id& vid);
void onAnnounceDone(const Sp<Node>& status, net::RequestAnswer& a, Sp<Search>& sr);
};
}
} // namespace dht
+269
View File
@@ -0,0 +1,269 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h"
#include "logger.h"
#include "node_export.h"
#include <queue>
namespace dht {
namespace net {
class DatagramSocket;
}
class OPENDHT_PUBLIC DhtInterface
{
public:
DhtInterface() = default;
DhtInterface(const std::shared_ptr<Logger>& l)
: logger_(l)
{}
virtual ~DhtInterface() = default;
// [[deprecated]]
using Status = NodeStatus;
// [[deprecated]]
using NodeExport = dht::NodeExport;
/**
* Get the current status of the node for the given family.
*/
virtual NodeStatus updateStatus(sa_family_t af) { return getStatus(af); }
virtual NodeStatus getStatus(sa_family_t af) const = 0;
virtual NodeStatus getStatus() const = 0;
void addOnConnectedCallback(std::function<void()> cb) { onConnectCallbacks_.emplace(std::move(cb)); }
virtual void setOnPublicAddressChanged(PublicAddressChangedCb) {}
virtual net::DatagramSocket* getSocket() const { return {}; }
/**
* Get the ID of the DHT node.
*/
virtual const InfoHash& getNodeId() const = 0;
/**
* Performs final operations before quitting.
* stop: if true, cancel ongoing operations and call their 'done'
* callbacks synchronously.
*/
virtual void shutdown(ShutdownCallback cb, bool stop = false) = 0;
/**
* Returns true if the node is running (have access to an open socket).
*
* af: address family. If non-zero, will return true if the node
* is running for the provided family.
*/
virtual bool isRunning(sa_family_t af = 0) const = 0;
virtual void registerType(const ValueType& type) = 0;
virtual const ValueType& getType(ValueType::Id type_id) const = 0;
virtual void addBootstrap(const std::string& /*host*/, const std::string& /*service*/) {};
virtual void clearBootstrap() {};
/**
* Insert a node in the main routing table.
* The node is not pinged, so this should be
* used to bootstrap efficiently from previously known nodes.
*/
virtual void insertNode(const InfoHash& id, const SockAddr&) = 0;
virtual void insertNode(const NodeExport& n) = 0;
virtual void pingNode(SockAddr, DoneCallbackSimple&& cb = {}) = 0;
virtual time_point periodic(const uint8_t* buf, size_t buflen, SockAddr, const time_point& now) = 0;
virtual time_point periodic(
const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now)
= 0;
/**
* Get a value by searching on all available protocols (IPv4, IPv6),
* and call the provided get callback when values are found at key.
* The operation will start as soon as the node is connected to the network.
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param donecb a function called when the operation is complete.
cb and donecb won't be called again afterward.
* @param f a filter function used to prefilter values.
*/
virtual void get(
const InfoHash& key, GetCallback cb, DoneCallback donecb = {}, Value::Filter&& f = {}, Where&& w = {})
= 0;
virtual void get(
const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb = {}, Value::Filter&& f = {}, Where&& w = {})
= 0;
virtual void get(
const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb = {}, Value::Filter&& f = {}, Where&& w = {})
= 0;
virtual void get(
const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f = {}, Where&& w = {})
= 0;
/**
* Similar to Dht::get, but sends a Query to filter data remotely.
* @param key the key for which to query data for.
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param done_cb a function called when the operation is complete.
cb and done_cb won't be called again afterward.
* @param q a query used to filter values on the remotes before they send a
* response.
*/
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) = 0;
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) = 0;
/**
* Get locally stored data for the given hash.
*/
virtual std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const = 0;
/**
* Get locally stored data for the given key and value id.
*/
virtual Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const = 0;
/**
* Announce a value on all available protocols (IPv4, IPv6).
*
* The operation will start as soon as the node is connected to the network.
* The done callback will be called once, when the first announce succeeds, or fails.
*/
virtual void put(const InfoHash& key,
Sp<Value>,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false)
= 0;
virtual void put(const InfoHash& key,
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false)
= 0;
virtual void put(const InfoHash& key,
Value&& v,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false)
= 0;
virtual void put(const InfoHash& key,
Value&& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false)
= 0;
/**
* Get data currently being put at the given hash.
*/
virtual std::vector<Sp<Value>> getPut(const InfoHash&) const = 0;
/**
* Get data currently being put at the given hash with the given id.
*/
virtual Sp<Value> getPut(const InfoHash&, const Value::Id&) const = 0;
/**
* Stop any put/announce operation at the given location,
* for the value with the given id.
*/
virtual bool cancelPut(const InfoHash&, const Value::Id&) = 0;
/**
* Listen on the network for any changes involving a specified hash.
* The node will register to receive updates from relevent nodes when
* new values are added or removed.
*
* @return a token to cancel the listener later.
*/
virtual size_t listen(const InfoHash&, GetCallback, Value::Filter = {}, Where w = {}) = 0;
virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {}) = 0;
virtual size_t listen(const InfoHash&, ValueCallback, Value::Filter = {}, Where w = {}) = 0;
virtual bool cancelListen(const InfoHash&, size_t token) = 0;
/**
* Inform the DHT of lower-layer connectivity changes.
* This will cause the DHT to assume a public IP address change.
* The DHT will recontact neighbor nodes, re-register for listen ops etc.
*/
virtual void connectivityChanged(sa_family_t) = 0;
virtual void connectivityChanged() = 0;
/**
* Get the list of good nodes for local storage saving purposes
* The list is ordered to minimize the back-to-work delay.
*/
virtual std::vector<NodeExport> exportNodes() const = 0;
virtual std::vector<ValuesExport> exportValues() const = 0;
virtual void importValues(const std::vector<ValuesExport>&) = 0;
virtual NodeStats getNodesStats(sa_family_t af) const = 0;
virtual std::string getStorageLog() const = 0;
virtual std::string getStorageLog(const InfoHash&) const = 0;
virtual std::string getRoutingTablesLog(sa_family_t) const = 0;
virtual std::string getSearchesLog(sa_family_t) const = 0;
virtual std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const = 0;
virtual void dumpTables() const = 0;
virtual std::vector<unsigned> getNodeMessageStats(bool in = false) = 0;
/**
* Set the in-memory storage limit in bytes for remote values
*/
virtual void setStorageLimit(size_t limit = 0) = 0;
virtual size_t getStorageLimit() const = 0;
/**
* Set the in-memory storage limit in bytes for locally stored values
*/
virtual void setLocalStorageLimit(size_t limit = 0) = 0;
virtual size_t getLocalStorageLimit() const = 0;
/**
* Returns the total memory usage of stored values and the number
* of stored values.
*/
virtual std::pair<size_t, size_t> getStoreSize() const = 0;
virtual std::pair<size_t, size_t> getLocalStoreSize() const = 0;
virtual std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) = 0;
virtual void setLogger(const std::shared_ptr<Logger>& l) { logger_ = l; }
/**
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
*/
virtual void setLogFilter(const InfoHash& f)
{
if (logger_)
logger_->setFilter(f);
}
virtual void setPushNotificationToken(const std::string&) {};
virtual void setPushNotificationTopic(const std::string&) {};
virtual void setPushNotificationPlatform(const std::string&) {};
/**
* Call linked callback with a push notification
* @param notification to process
*/
virtual PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& data) = 0;
protected:
std::shared_ptr<Logger> logger_ {};
std::queue<std::function<void()>> onConnectCallbacks_ {};
};
} // namespace dht
+481
View File
@@ -0,0 +1,481 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include <functional>
#include <mutex>
#include "callbacks.h"
#include "def.h"
#include "dht_interface.h"
#include "proxy.h"
#include "http.h"
#include <restinio/all.hpp>
#include <json/json.h>
#include <chrono>
#include <vector>
#include <functional>
namespace Json {
class Value;
}
namespace http {
class Resolver;
class Request;
} // namespace http
namespace dht {
class OPENDHT_PUBLIC DhtProxyClient final : public DhtInterface
{
public:
DhtProxyClient();
explicit DhtProxyClient(std::shared_ptr<crypto::Certificate> serverCA,
crypto::Identity clientIdentity,
std::function<void()> loopSignal,
const std::string& serverHost,
const std::string& userAgent = "",
const std::string& pushClientId = "",
const std::string& pushToken = "",
const std::string& pushTopic = "",
const std::string& pushPlatform = "",
std::shared_ptr<Logger> logger = {});
void setHeaderFields(http::Request& request);
virtual void setPushNotificationToken(const std::string& token) override;
virtual void setPushNotificationTopic(const std::string& topic) override
{
#ifdef OPENDHT_PUSH_NOTIFICATIONS
notificationTopic_ = topic;
#else
(void) topic;
#endif
}
virtual void setPushNotificationPlatform(const std::string& platform) override
{
#ifdef OPENDHT_PUSH_NOTIFICATIONS
platform_ = platform;
#else
(void) platform;
#endif
}
virtual ~DhtProxyClient();
/**
* Get the ID of the node.
*/
inline const InfoHash& getNodeId() const override { return myid; }
void setOnPublicAddressChanged(PublicAddressChangedCb cb) override { publicAddressChangedCb_ = std::move(cb); }
/**
* Get the current status of the node for the given family.
*/
NodeStatus getStatus(sa_family_t af) const override;
NodeStatus getStatus() const override { return std::max(getStatus(AF_INET), getStatus(AF_INET6)); }
/**
* Performs final operations before quitting.
*/
void shutdown(ShutdownCallback cb, bool) override;
/**
* Returns true if the node is running (have access to an open socket).
*
* af: address family. If non-zero, will return true if the node
* is running for the provided family.
*/
bool isRunning(sa_family_t af = 0) const override;
/**
* Get a value by asking the proxy and call the provided get callback when
* values are found at key.
* The operation will start as soon as the node is connected to the network.
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param donecb a function called when the operation is complete.
cb and donecb won't be called again afterward.
* @param f a filter function used to prefilter values.
*/
virtual void get(
const InfoHash& key, GetCallback cb, DoneCallback donecb = {}, Value::Filter&& f = {}, Where&& w = {}) override;
virtual void get(const InfoHash& key,
GetCallback cb,
DoneCallbackSimple donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, cb, bindDoneCb(std::move(donecb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallback donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), std::move(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallbackSimple donecb,
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), bindDoneCb(std::move(donecb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
/**
* Announce a value on all available protocols (IPv4, IPv6).
*
* The operation will start as soon as the node is connected to the network.
* The done callback will be called once, when the first announce succeeds, or fails.
* NOTE: For now, created parameter is ignored.
*/
void put(const InfoHash& key,
Sp<Value>,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override;
void put(const InfoHash& key,
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, v, bindDoneCb(std::move(cb)), created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, std::make_shared<Value>(std::move(v)), std::move(cb), created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
put(key, std::forward<Value>(v), bindDoneCb(std::move(cb)), created, permanent);
}
/**
* @param af the socket family
* @return node stats from the proxy
*/
NodeStats getNodesStats(sa_family_t af) const override;
/**
* @param family the socket family
* @return public address
*/
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override;
/**
* Listen on the network for any changes involving a specified hash.
* The node will register to receive updates from relevent nodes when
* new values are added or removed.
*
* @return a token to cancel the listener later.
*/
virtual size_t listen(const InfoHash&, ValueCallback, Value::Filter = {}, Where = {}) override;
virtual size_t listen(const InfoHash& key, GetCallback cb, Value::Filter f = {}, Where w = {}) override
{
return listen(
key,
[cb = std::move(cb)](const std::vector<Sp<Value>>& vals, bool expired) {
if (not expired)
return cb(vals);
return true;
},
std::forward<Value::Filter>(f),
std::forward<Where>(w));
}
virtual size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {}) override
{
return listen(key, bindGetCb(std::move(cb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
/*
* This function relies on the cache implementation.
* It means that there are no true cancel here, it keeps the caching in higher priority.
*/
virtual bool cancelListen(const InfoHash& key, size_t token) override;
/**
* Call linked callback with a push notification
* @param notification to process
*/
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& notification) override;
time_point periodic(const uint8_t*, size_t, SockAddr, const time_point& now) override;
time_point periodic(
const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override
{
return periodic(buf, buflen, SockAddr(from, fromlen), now);
}
/**
* Similar to Dht::get, but sends a Query to filter data remotely.
* @param key the key for which to query data for.
* @param cb a function called when new values are found on the network.
* It should return false to stop the operation.
* @param done_cb a function called when the operation is complete.
cb and done_cb won't be called again afterward.
* @param q a query used to filter values on the remotes before they send a
* response.
*/
virtual void query(const InfoHash& /*key*/,
QueryCallback /*cb*/,
DoneCallback /*done_cb*/ = {},
Query&& /*q*/ = {}) override
{}
virtual void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override
{
query(key, cb, bindDoneCb(std::move(done_cb)), std::forward<Query>(q));
}
/**
* Get data currently being put at the given hash.
*/
std::vector<Sp<Value>> getPut(const InfoHash&) const override;
/**
* Get data currently being put at the given hash with the given id.
*/
Sp<Value> getPut(const InfoHash&, const Value::Id&) const override;
/**
* Stop any put/announce operation at the given location,
* for the value with the given id.
*/
bool cancelPut(const InfoHash&, const Value::Id&) override;
void pingNode(SockAddr, DoneCallbackSimple&& /*cb*/ = {}) override {}
virtual void registerType(const ValueType& type) override { types.registerType(type); }
const ValueType& getType(ValueType::Id type_id) const override { return types.getType(type_id); }
std::vector<Sp<Value>> getLocal(const InfoHash& k, const Value::Filter& filter) const override;
Sp<Value> getLocalById(const InfoHash& k, Value::Id id) const override;
/**
* NOTE: The following methods will not be implemented because the
* DhtProxyClient doesn't have any storage nor synchronization process
*/
void insertNode(const InfoHash&, const SockAddr&) override {}
void insertNode(const NodeExport&) override {}
std::pair<size_t, size_t> getStoreSize() const override { return {}; }
std::pair<size_t, size_t> getLocalStoreSize() const override { return {}; }
std::vector<NodeExport> exportNodes() const override { return {}; }
std::vector<ValuesExport> exportValues() const override { return {}; }
void importValues(const std::vector<ValuesExport>&) override {}
std::string getStorageLog() const override { return {}; }
std::string getStorageLog(const InfoHash&) const override { return {}; }
std::string getRoutingTablesLog(sa_family_t) const override { return {}; }
std::string getSearchesLog(sa_family_t) const override { return {}; }
std::string getSearchLog(const InfoHash&, sa_family_t) const override { return {}; }
void dumpTables() const override {}
std::vector<unsigned> getNodeMessageStats(bool) override { return {}; }
void setStorageLimit(size_t) override {}
virtual size_t getStorageLimit() const override { return 0; }
void setLocalStorageLimit(size_t) override {}
virtual size_t getLocalStorageLimit() const override { return STORAGE_LIMIT_UNLIMITED; }
void connectivityChanged(sa_family_t) override { getProxyInfos(); }
void connectivityChanged() override
{
getProxyInfos();
loopSignal_();
}
void listenKeepIdle(uint32_t seconds) { listenKeepIdle_ = seconds; }
inline uint32_t listenKeepIdle() { return listenKeepIdle_; }
private:
/**
* Start the connection with a server.
*/
void startProxy();
void stop();
/**
* Get informations from the proxy node
* @return the JSON returned by the proxy
*/
struct InfoState;
void getProxyInfos();
void queryProxyInfo(const std::shared_ptr<InfoState>& infoState,
const std::shared_ptr<http::Resolver>& resolver,
sa_family_t family);
void onProxyInfos(const Json::Value& val, const sa_family_t family);
SockAddr parsePublicAddress(const Json::Value& val);
void opFailed();
void handleExpireListener(const asio::error_code& ec, const InfoHash& key);
struct Listener;
struct OperationState;
enum class ListenMethod {
LISTEN,
SUBSCRIBE,
RESUBSCRIBE,
};
using CacheValueCallback
= std::function<bool(const std::vector<std::shared_ptr<Value>>& values, bool expired, system_clock::time_point)>;
/**
* Send Listen with httpClient_
*/
void sendListen(const restinio::http_request_header_t& header,
const CacheValueCallback& cb,
const Sp<OperationState>& opstate,
Listener& listener,
ListenMethod method = ListenMethod::LISTEN);
void handleResubscribe(const asio::error_code& ec,
const InfoHash& key,
const size_t token,
std::shared_ptr<OperationState> opstate);
void doPut(const InfoHash&, Sp<Value>, DoneCallbackSimple, time_point created, bool permanent);
void handleRefreshPut(const asio::error_code& ec, InfoHash key, Value::Id id);
/**
* Initialize statusIpvX_
*/
void getConnectivityStatus();
/**
* cancel all Listeners
*/
void cancelAllListeners();
std::atomic_bool isDestroying_ {false};
std::string proxyUrl_;
dht::crypto::Identity clientIdentity_;
std::shared_ptr<dht::crypto::Certificate> serverCertificate_;
std::string userAgent_ {"OpenDHT"};
std::string pushClientId_;
std::string pushSessionId_;
mutable std::mutex lockCurrentProxyInfos_;
NodeStatus statusIpv4_ {NodeStatus::Disconnected};
NodeStatus statusIpv6_ {NodeStatus::Disconnected};
NodeStats stats4_ {};
NodeStats stats6_ {};
SockAddr localAddrv4_;
SockAddr localAddrv6_;
SockAddr publicAddressV4_;
SockAddr publicAddressV6_;
std::atomic_bool launchConnectedCbs_ {false};
PublicAddressChangedCb publicAddressChangedCb_ {};
InfoHash myid {};
// registred types
TypeStore types;
/*
* ASIO I/O Context for sockets in httpClient_
* Note: Each context is used in one thread only
*/
asio::io_context httpContext_;
mutable std::mutex resolverLock_;
std::shared_ptr<http::Resolver> resolver_;
mutable std::mutex requestLock_;
std::map<unsigned, std::shared_ptr<http::Request>> requests_;
/*
* Thread for executing the http io_context.run() blocking call
*/
std::thread httpClientThread_;
/**
* Store listen requests.
*/
struct ProxySearch;
mutable std::mutex searchLock_;
size_t listenerToken_ {0};
std::map<InfoHash, ProxySearch> searches_;
/**
* Keepalive idle time for listen
*/
uint32_t listenKeepIdle_ {120};
/**
* Callbacks should be executed in the main thread.
*/
std::mutex lockCallbacks_;
std::vector<std::function<void()>> callbacks_;
Sp<InfoState> infoState_;
/**
* Retrieve if we can connect to the proxy (update statusIpvX_)
*/
void handleProxyConfirm(const asio::error_code& ec);
std::unique_ptr<asio::steady_timer> nextProxyConfirmationTimer_;
std::unique_ptr<asio::steady_timer> listenerRestartTimer_;
/**
* Relaunch LISTEN requests if the client disconnect/reconnect.
*/
void restartListeners(const asio::error_code& ec);
/**
* Refresh a listen via a token
* @param token
*/
void resubscribe(const InfoHash& key, const size_t token, Listener& listener);
/**
* If we want to use push notifications by default.
* NOTE: empty by default to avoid to use services like FCM or APN.
*/
std::string deviceKey_ {};
/**
* Notification topic for ios notifications.
*/
std::string notificationTopic_ {};
/**
* Platform for push notifications (supported android, ios, unifiedpush)
*/
std::string platform_
#ifdef __ANDROID__
{"android"};
#else
#ifdef __APPLE__
{"ios"};
#else
{};
#endif
#endif
const std::function<void()> loopSignal_;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
std::string fillBody(bool resubscribe);
void getPushRequest(Json::Value&) const;
#endif // OPENDHT_PUSH_NOTIFICATIONS
Json::StreamWriterBuilder jsonBuilder_;
std::unique_ptr<Json::CharReader> jsonReader_;
std::shared_ptr<http::Request> buildRequest(const std::string& target = {});
};
} // namespace dht
+504
View File
@@ -0,0 +1,504 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "callbacks.h"
#include "def.h"
#include "infohash.h"
#include "proxy.h"
#include "scheduler.h"
#include "sockaddr.h"
#include "value.h"
#include "http.h"
#include <restinio/all.hpp>
#include <restinio/tls.hpp>
#include <json/json.h>
#include <memory>
#include <mutex>
namespace dht {
enum class PushType { None = 0, Android, iOS, UnifiedPush };
}
MSGPACK_ADD_ENUM(dht::PushType)
namespace Json {
class Value;
}
namespace dht {
namespace http {
class Request;
struct ListenerSession;
} // namespace http
class DhtRunner;
using RestRouter = restinio::router::express_router_t<>;
using RequestStatus = restinio::request_handling_status_t;
struct OPENDHT_PUBLIC ProxyServerConfig
{
std::string address {};
in_port_t port {8000};
std::string pushServer {};
std::string persistStatePath {};
dht::crypto::Identity identity {};
std::string bundleId {};
};
/**
* Describes the REST API
*/
class OPENDHT_PUBLIC DhtProxyServer
{
public:
/**
* Start the Http server for OpenDHT
* @param dht the DhtRunner linked to this proxy server
* @param port to listen
* @param pushServer where to push notifications
* @note if the server fails to start (if port is already used or reserved),
* it will fails silently
*/
DhtProxyServer(const std::shared_ptr<DhtRunner>& dht,
const ProxyServerConfig& config = {},
const std::shared_ptr<log::Logger>& logger = {});
virtual ~DhtProxyServer();
DhtProxyServer(const DhtProxyServer& other) = delete;
DhtProxyServer(DhtProxyServer&& other) = delete;
DhtProxyServer& operator=(const DhtProxyServer& other) = delete;
DhtProxyServer& operator=(DhtProxyServer&& other) = delete;
asio::io_context& io_context() const;
using clock = std::chrono::steady_clock;
using time_point = clock::time_point;
struct PushStats
{
uint64_t highPriorityCount {0};
uint64_t normalPriorityCount {0};
void increment(bool highPriority)
{
if (highPriority)
highPriorityCount++;
else
normalPriorityCount++;
}
Json::Value toJson() const
{
Json::Value val;
val["highPriorityCount"] = static_cast<Json::UInt64>(highPriorityCount);
val["normalPriorityCount"] = static_cast<Json::UInt64>(normalPriorityCount);
return val;
}
std::string toString() const
{
return fmt::format("{} high priority, {} normal priority", highPriorityCount, normalPriorityCount);
}
};
struct OPENDHT_PUBLIC ServerStats
{
/** Current number of listen operations */
size_t listenCount {0};
/** Current number of permanent put operations (hash used) */
size_t putCount {0};
/** Current number of permanent put values */
size_t totalPermanentPuts {0};
/** Current number of push tokens with at least one listen operation */
size_t pushListenersCount {0};
/** Time at which the server was started */
time_point serverStartTime;
/** Last time at which the stats were updated */
time_point lastUpdated;
/** Total number of push notification requests that the server attempted to
* send since being started, broken down by type and priority level */
PushStats androidPush;
PushStats iosPush;
PushStats unifiedPush;
/** Average requests per second */
double requestRate {0};
/** Node Info **/
std::shared_ptr<NodeInfo> nodeInfo {};
std::string toString() const;
/**
* Build a json object from a NodeStats
*/
Json::Value toJson() const;
};
std::shared_ptr<ServerStats> stats() const { return stats_; }
std::shared_ptr<ServerStats> updateStats(std::shared_ptr<NodeInfo> info) const;
std::shared_ptr<DhtRunner> getNode() const { return dht_; }
private:
class ConnectionListener;
struct RestRouterTraitsTls;
struct RestRouterTraits;
template<typename HttpResponse>
static HttpResponse initHttpResponse(HttpResponse response);
static restinio::request_handling_status_t serverError(restinio::request_t& request);
template<typename ServerSettings>
void addServerSettings(ServerSettings& serverSettings, const unsigned int max_pipelined_requests = 16);
std::unique_ptr<RestRouter> createRestRouter();
void onConnectionClosed(restinio::connection_id_t);
/**
* Return the PublicKey id, the node id and node stats
* Method: GET "/"
* Result: HTTP 200, body: Node infos in JSON format
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
RequestStatus getNodeInfo(restinio::request_handle_t request, restinio::router::route_params_t params) const;
/**
* Return ServerStats in JSON format
* Method: STATS "/"
* Result: HTTP 200, body: Node infos in JSON format
* @param session
*/
RequestStatus getStats(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Return Values of an infoHash
* Method: GET "/{InfoHash: .*}"
* Return: Multiple JSON object in parts. Example:
* Value in JSON format\n
* Value in JSON format
*
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
RequestStatus get(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Listen incoming Values of an infoHash.
* Method: LISTEN "/{InfoHash: .*}"
* Return: Multiple JSON object in parts. Example:
* Value in JSON format\n
* Value in JSON format
*
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
RequestStatus listen(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Put a value on the DHT
* Method: POST "/{InfoHash: .*}"
* body = Value to put in JSON
* Return: HTTP 200 if success and the value put in JSON
* On error: HTTP 503, body: {"err":"xxxx"} if no dht
* HTTP 400, body: {"err":"xxxx"} if bad json or HTTP 502 if put fails
* @param session
*/
RequestStatus put(restinio::request_handle_t request, restinio::router::route_params_t params);
void handleCancelPermamentPut(const asio::error_code& ec, const InfoHash& key, Value::Id vid);
#ifdef OPENDHT_PROXY_SERVER_IDENTITY
/**
* Put a value to sign by the proxy on the DHT
* Method: SIGN "/{InfoHash: .*}"
* body = Value to put in JSON
* Return: HTTP 200 if success and the value put in JSON
* On error: HTTP 503, body: {"err":"xxxx"} if no dht
* HTTP 400, body: {"err":"xxxx"} if bad json
* @param session
*/
RequestStatus putSigned(restinio::request_handle_t request, restinio::router::route_params_t params) const;
/**
* Put a value to encrypt by the proxy on the DHT
* Method: ENCRYPT "/{hash: .*}"
* body = Value to put in JSON + "to":"infoHash"
* Return: HTTP 200 if success and the value put in JSON
* On error: HTTP 503, body: {"err":"xxxx"} if no dht
* HTTP 400, body: {"err":"xxxx"} if bad json
* @param session
*/
RequestStatus putEncrypted(restinio::request_handle_t request, restinio::router::route_params_t params);
#endif // OPENDHT_PROXY_SERVER_IDENTITY
/**
* Return Values of an infoHash filtered by a value id
* Method: GET "/{InfoHash: .*}/{ValueId: .*}"
* Return: Multiple JSON object in parts. Example:
* Value in JSON format\n
* Value in JSON format
*
* On error: HTTP 503, body: {"err":"xxxx"}
* @param session
*/
RequestStatus getFiltered(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Respond allowed Methods
* Method: OPTIONS "/{hash: .*}"
* Return: HTTP 200 + Allow: allowed methods
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
* @param session
*/
RequestStatus options(restinio::request_handle_t request, restinio::router::route_params_t params);
struct PushSessionContext
{
std::mutex lock;
std::string sessionId;
PushSessionContext(const std::string& id)
: sessionId(id)
{}
};
#ifdef OPENDHT_PUSH_NOTIFICATIONS
PushType getTypeFromString(const std::string& type);
std::string getDefaultTopic(PushType type);
RequestStatus pingPush(restinio::request_handle_t request, restinio::router::route_params_t /*params*/);
/**
* Subscribe to push notifications for an iOS or Android device.
* Method: SUBSCRIBE "/{InfoHash: .*}"
* Body: {"key": "device_key", (optional)"isAndroid":false (default true)}"
* Return: {"token": x}" where x if a token to save
* @note: the listen will timeout after six hours (and send a push notification).
* so you need to refresh the operation each six hours.
* @param session
*/
RequestStatus subscribe(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Unsubscribe to push notifications for an iOS or Android device.
* Method: UNSUBSCRIBE "/{InfoHash: .*}"
* Body: {"key": "device_key", "token": x} where x if the token to cancel
* Return: nothing
* @param session
*/
RequestStatus unsubscribe(restinio::request_handle_t request, restinio::router::route_params_t params);
/**
* Send a push notification via a gorush push gateway
* @param key of the device
* @param json, the content to send
*/
void sendPushNotification(
const std::string& key, Json::Value&& json, PushType type, bool highPriority, const std::string& topic);
/**
* Send push notification with an expire timeout.
* @param ec
* @param pushToken
* @param json
* @param type
* @param topic
*/
void handleNotifyPushListenExpire(const asio::error_code& ec,
const std::string pushToken,
std::function<Json::Value()> json,
PushType type,
const std::string& topic);
/**
* Remove a push listener between a client and a hash
* @param ec
* @param pushToken
* @param key
* @param clientId
*/
void handleCancelPushListen(const asio::error_code& ec,
const std::string pushToken,
const InfoHash key,
const std::string clientId);
/**
* Handles a push listen request.
*
* @param infoHash The information hash associated with the push listen request.
* @param pushToken The push token associated with the push listen request.
* @param type The type of the push listen request.
* @param clientId The client ID associated with the push listen request.
* @param sessionCtx The shared pointer to the push session context associated with the push listen request.
* @param topic The topic associated with the push listen request.
* @param values The vector of shared pointers to values associated with the push listen request.
* @param expired A boolean indicating whether the push listen request has expired.
* @return true.
*/
bool handlePushListen(const InfoHash& infoHash,
const std::string& pushToken,
PushType type,
const std::string& clientId,
const std::shared_ptr<DhtProxyServer::PushSessionContext>& sessionCtx,
const std::string& topic,
const std::vector<std::shared_ptr<Value>>& values,
bool expired);
#endif // OPENDHT_PUSH_NOTIFICATIONS
void handlePrintStats(const asio::error_code& ec);
void updateStats();
template<typename Os>
void saveState(Os& stream);
template<typename Is>
void loadState(Is& is, size_t size);
std::shared_ptr<asio::io_context> ioContext_;
std::shared_ptr<DhtRunner> dht_;
Json::StreamWriterBuilder jsonBuilder_;
Json::CharReaderBuilder jsonReaderBuilder_;
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
std::string persistPath_;
// http server
std::thread serverThread_;
std::unique_ptr<restinio::http_server_t<RestRouterTraitsTls>> httpsServer_;
std::unique_ptr<restinio::http_server_t<RestRouterTraits>> httpServer_;
// http client
std::pair<std::string, std::string> pushHostPort_;
mutable std::mutex requestLock_;
std::map<unsigned int /*id*/, std::shared_ptr<http::Request>> requests_;
std::shared_ptr<log::Logger> logger_;
std::shared_ptr<ServerStats> stats_;
std::shared_ptr<NodeInfo> nodeInfo_ {};
std::unique_ptr<asio::steady_timer> printStatsTimer_;
const time_point serverStartTime_;
mutable std::mutex pushStatsMutex_;
PushStats androidPush_;
PushStats iosPush_;
PushStats unifiedPush_;
// Thread-safe access to listeners map.
std::mutex lockListener_;
// Shared with connection listener.
std::map<restinio::connection_id_t, http::ListenerSession> listeners_;
// Connection Listener observing conn state changes.
std::shared_ptr<ConnectionListener> connListener_;
struct PermanentPut
{
time_point expiration;
std::string pushToken;
std::string clientId;
std::shared_ptr<PushSessionContext> sessionCtx;
std::unique_ptr<asio::steady_timer> expireTimer;
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
Sp<Value> value;
PushType type;
std::string topic;
template<typename Packer>
void msgpack_pack(Packer& p) const
{
p.pack_map(2 + (sessionCtx ? 1 : 0) + (clientId.empty() ? 0 : 1) + (type == PushType::None ? 0 : 2)
+ (topic.empty() ? 0 : 1));
p.pack("value");
p.pack(value);
p.pack("exp");
p.pack(to_time_t(expiration));
if (not clientId.empty()) {
p.pack("cid");
p.pack(clientId);
}
if (sessionCtx) {
std::lock_guard<std::mutex> l(sessionCtx->lock);
p.pack("sid");
p.pack(sessionCtx->sessionId);
}
if (type != PushType::None) {
p.pack("t");
p.pack(type);
p.pack("token");
p.pack(pushToken);
}
if (not topic.empty()) {
p.pack("top");
p.pack(topic);
}
}
void msgpack_unpack(const msgpack::object& o);
};
struct SearchPuts
{
std::map<dht::Value::Id, PermanentPut> puts;
MSGPACK_DEFINE_ARRAY(puts)
};
std::mutex lockSearchPuts_;
std::map<InfoHash, SearchPuts> puts_;
mutable std::atomic<size_t> requestNum_ {0};
mutable std::atomic<time_point> lastStatsReset_ {time_point::min()};
std::string pushServer_;
std::string bundleId_;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
struct Listener
{
time_point expiration;
std::string clientId;
std::shared_ptr<PushSessionContext> sessionCtx;
std::future<size_t> internalToken;
std::unique_ptr<asio::steady_timer> expireTimer;
std::unique_ptr<asio::steady_timer> expireNotifyTimer;
PushType type;
std::string topic;
template<typename Packer>
void msgpack_pack(Packer& p) const
{
p.pack_map(3 + (sessionCtx ? 1 : 0) + (topic.empty() ? 0 : 1));
p.pack("cid");
p.pack(clientId);
p.pack("exp");
p.pack(to_time_t(expiration));
if (sessionCtx) {
std::lock_guard<std::mutex> l(sessionCtx->lock);
p.pack("sid");
p.pack(sessionCtx->sessionId);
}
p.pack("t");
p.pack(type);
if (!topic.empty()) {
p.pack("top");
p.pack(topic);
}
}
void msgpack_unpack(const msgpack::object& o);
};
struct PushListener
{
std::map<InfoHash, std::vector<Listener>> listeners;
MSGPACK_DEFINE_ARRAY(listeners)
};
std::map<std::string, PushListener> pushListeners_;
#endif // OPENDHT_PUSH_NOTIFICATIONS
};
} // namespace dht
+447 -196
View File
@@ -1,29 +1,15 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
//#include "securedht.h"
#include "def.h"
#include "infohash.h"
#include "value.h"
#include "callbacks.h"
#include "sockaddr.h"
#include "logger.h"
#include "network_utils.h"
#include "node_export.h"
#include <thread>
#include <mutex>
@@ -38,6 +24,7 @@ namespace dht {
struct Node;
class SecureDht;
class PeerDiscovery;
struct SecureDhtConfig;
/**
@@ -46,154 +33,344 @@ struct SecureDhtConfig;
* either wait for (expectedly frequent) calls to ::loop() or start an internal
* thread that will update the DHT when appropriate.
*/
class DhtRunner {
class OPENDHT_PUBLIC DhtRunner
{
public:
typedef std::function<void(NodeStatus, NodeStatus)> StatusCallback;
using StatusCallback = std::function<void(NodeStatus, NodeStatus)>;
struct Config
{
SecureDhtConfig dht_config {};
bool threaded {true};
std::string proxy_server {};
std::string push_node_id {};
std::string push_token {};
std::string push_topic {};
std::string push_platform {};
std::string proxy_user_agent {};
bool peer_discovery {false};
bool peer_publish {false};
std::shared_ptr<dht::crypto::Certificate> server_ca;
dht::crypto::Identity client_identity;
SockAddr bind4 {}, bind6 {};
};
struct Context
{
std::shared_ptr<Logger> logger {};
std::unique_ptr<net::DatagramSocket> sock;
std::shared_ptr<PeerDiscovery> peerDiscovery {};
StatusCallback statusChangedCallback {};
CertificateStoreQueryLegacy certificateStore {};
CertificateStoreQuery certificateStorePkId {};
IdentityAnnouncedCb identityAnnouncedCb {};
PublicAddressChangedCb publicAddressChangedCb {};
std::unique_ptr<std::mt19937_64> rng {};
Context() {}
};
DhtRunner();
virtual ~DhtRunner();
void get(InfoHash id, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter f = Value::AllFilter()) {
get(id, bindGetCb(cb), donecb, f);
}
void get(InfoHash id, GetCallbackSimple cb, DoneCallbackSimple donecb={}, Value::Filter f = Value::AllFilter()) {
get(id, bindGetCb(cb), donecb, f);
}
void get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f={});
void get(InfoHash id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter f = Value::AllFilter()) {
get(id, cb, bindDoneCb(donecb), f);
}
void get(const std::string& key, GetCallback vcb, DoneCallbackSimple dcb={}, Value::Filter f = Value::AllFilter());
template <class T>
void get(InfoHash hash, std::function<bool(std::vector<T>&&)> cb, DoneCallbackSimple dcb={})
void get(InfoHash id, GetCallbackSimple cb, DoneCallback donecb = {}, Value::Filter f = {}, Where w = {})
{
get(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
return cb(unpackVector<T>(vals));
},
dcb,
getFilterSet<T>());
get(id, bindGetCb(cb), donecb, f, w);
}
template <class T>
void get(InfoHash hash, std::function<bool(T&&)> cb, DoneCallbackSimple dcb={})
void get(InfoHash id, GetCallbackSimple cb, DoneCallbackSimple donecb = {}, Value::Filter f = {}, Where w = {})
{
get(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v)))
return false;
} catch (const std::exception&) {
continue;
get(id, bindGetCb(cb), donecb, f, w);
}
void get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f = {}, Where w = {});
void get(InfoHash id, GetCallback cb, DoneCallbackSimple donecb = {}, Value::Filter f = {}, Where w = {})
{
get(id, cb, bindDoneCb(donecb), f, w);
}
void get(const std::string& key, GetCallback vcb, DoneCallbackSimple dcb = {}, Value::Filter f = {}, Where w = {});
template<class T>
void get(InfoHash hash, std::function<bool(std::vector<T>&&)> cb, DoneCallbackSimple dcb = {})
{
get(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) { return cb(unpackVector<T>(vals)); },
dcb,
getFilterSet<T>());
}
template<class T>
void get(InfoHash hash, std::function<bool(T&&)> cb, DoneCallbackSimple dcb = {})
{
get(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v)))
return false;
} catch (const std::exception&) {
continue;
}
}
}
return true;
},
dcb,
getFilterSet<T>());
return true;
},
dcb,
getFilterSet<T>());
}
std::future<std::vector<std::shared_ptr<dht::Value>>> get(InfoHash key, Value::Filter f = Value::AllFilter()) {
auto p = std::make_shared<std::promise<std::vector<std::shared_ptr< dht::Value >>>>();
auto values = std::make_shared<std::vector<std::shared_ptr< dht::Value >>>();
get(key, [=](const std::vector<std::shared_ptr<dht::Value>>& vlist) {
values->insert(values->end(), vlist.begin(), vlist.end());
return true;
}, [=](bool) {
p->set_value(std::move(*values));
},
f);
std::future<std::vector<std::shared_ptr<dht::Value>>> get(InfoHash key, Value::Filter f = {}, Where w = {})
{
auto p = std::make_shared<std::promise<std::vector<std::shared_ptr<dht::Value>>>>();
auto values = std::make_shared<std::vector<std::shared_ptr<dht::Value>>>();
get(
key,
[=](const std::vector<std::shared_ptr<dht::Value>>& vlist) {
values->insert(values->end(), vlist.begin(), vlist.end());
return true;
},
[=](bool) { p->set_value(std::move(*values)); },
f,
w);
return p->get_future();
}
template <class T>
std::future<std::vector<T>> get(InfoHash key) {
template<class T>
std::future<std::vector<T>> get(InfoHash key)
{
auto p = std::make_shared<std::promise<std::vector<T>>>();
auto values = std::make_shared<std::vector<T>>();
get<T>(key, [=](T&& v) {
values->emplace_back(std::move(v));
return true;
}, [=](bool) {
p->set_value(std::move(*values));
});
get<T>(
key,
[=](T&& v) {
values->emplace_back(std::move(v));
return true;
},
[=](bool) { p->set_value(std::move(*values)); });
return p->get_future();
}
std::future<size_t> listen(InfoHash key, GetCallback vcb, Value::Filter f = Value::AllFilter());
std::future<size_t> listen(const std::string& key, GetCallback vcb, Value::Filter f = Value::AllFilter());
std::future<size_t> listen(InfoHash key, GetCallbackSimple cb, Value::Filter f = Value::AllFilter()) {
return listen(key, bindGetCb(cb), f);
void query(const InfoHash& hash, QueryCallback cb, DoneCallback done_cb = {}, Query q = {});
void query(const InfoHash& hash, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query q = {})
{
query(hash, cb, bindDoneCb(done_cb), q);
}
template <class T>
std::future<size_t> listen(InfoHash key, ValueCallback vcb, Value::Filter f = {}, Where w = {});
std::future<size_t> listen(InfoHash key, GetCallback cb, Value::Filter f = {}, Where w = {})
{
return listen(
key,
[cb = std::move(cb)](const std::vector<Sp<Value>>& vals, bool expired) {
if (not expired)
return cb(vals);
return true;
},
std::forward<Value::Filter>(f),
std::forward<Where>(w));
}
std::future<size_t> listen(const std::string& key, GetCallback vcb, Value::Filter f = {}, Where w = {});
std::future<size_t> listen(InfoHash key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {})
{
return listen(key, bindGetCb(cb), f, w);
}
template<class T>
std::future<size_t> listen(InfoHash hash, std::function<bool(std::vector<T>&&)> cb)
{
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
return cb(unpackVector<T>(vals));
},
getFilterSet<T>());
return listen(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) { return cb(unpackVector<T>(vals)); },
getFilterSet<T>());
}
template <typename T>
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&)> cb, Value::Filter f = Value::AllFilter())
template<class T>
std::future<size_t> listen(InfoHash hash, std::function<bool(std::vector<T>&&, bool)> cb)
{
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v)))
return false;
} catch (const std::exception&) {
continue;
return listen(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
return cb(unpackVector<T>(vals), expired);
},
getFilterSet<T>());
}
template<typename T>
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&)> cb, Value::Filter f = {}, Where w = {})
{
return listen(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v)))
return false;
} catch (const std::exception&) {
continue;
}
}
}
return true;
},
getFilterSet<T>(f));
return true;
},
getFilterSet<T>(f),
w);
}
template<typename T>
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&, bool)> cb, Value::Filter f = {}, Where w = {})
{
return listen(
hash,
[cb = std::move(cb)](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v), expired))
return false;
} catch (const std::exception&) {
continue;
}
}
return true;
},
getFilterSet<T>(f),
w);
}
void cancelListen(InfoHash h, size_t token);
void cancelListen(InfoHash h, std::shared_future<size_t> token);
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
void put(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
put(hash, value, bindDoneCb(cb), permanent);
void put(InfoHash hash,
std::shared_ptr<Value> value,
DoneCallback cb = {},
time_point created = time_point::max(),
bool permanent = false);
void put(InfoHash hash,
std::shared_ptr<Value> value,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false)
{
put(hash, value, bindDoneCb(cb), created, permanent);
}
void put(InfoHash hash, Value&& value, DoneCallback cb={}, bool permanent = false);
void put(InfoHash hash, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
put(hash, std::forward<Value>(value), bindDoneCb(cb), permanent);
void put(InfoHash hash,
Value&& value,
DoneCallback cb = {},
time_point created = time_point::max(),
bool permanent = false);
void put(InfoHash hash,
Value&& value,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false)
{
put(hash, std::forward<Value>(value), bindDoneCb(cb), created, permanent);
}
void put(const std::string& key, Value&& value, DoneCallbackSimple cb={}, bool permanent = false);
void put(const std::string& key,
Value&& value,
DoneCallbackSimple cb = {},
time_point created = time_point::max(),
bool permanent = false);
void cancelPut(const InfoHash& h, const Value::Id& id);
void cancelPut(const InfoHash& h, Value::Id id);
void cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value);
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={});
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb) {
putSigned(hash, value, bindDoneCb(cb));
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb = {}, bool permanent = false);
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false)
{
putSigned(hash, value, bindDoneCb(cb), permanent);
}
void putSigned(InfoHash hash, Value&& value, DoneCallback cb={});
void putSigned(InfoHash hash, Value&& value, DoneCallbackSimple cb) {
putSigned(hash, std::forward<Value>(value), bindDoneCb(cb));
void putSigned(InfoHash hash, Value&& value, DoneCallback cb = {}, bool permanent = false);
void putSigned(InfoHash hash, Value&& value, DoneCallbackSimple cb, bool permanent = false)
{
putSigned(hash, std::forward<Value>(value), bindDoneCb(cb), permanent);
}
void putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb={});
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={});
void putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallbackSimple cb) {
putEncrypted(hash, to, value, bindDoneCb(cb));
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={});
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallbackSimple cb) {
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb));
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={});
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb = {}, bool permanent = false);
void bootstrap(const char* host, const char* service);
void bootstrap(const std::vector<std::pair<sockaddr_storage, socklen_t>>& nodes);
void bootstrap(const std::vector<NodeExport>& nodes);
void putEncrypted(InfoHash hash,
const std::shared_ptr<crypto::PublicKey>& to,
std::shared_ptr<Value> value,
DoneCallback cb = {},
bool permanent = false);
void putEncrypted(InfoHash hash,
const std::shared_ptr<crypto::PublicKey>& to,
std::shared_ptr<Value> value,
DoneCallbackSimple cb,
bool permanent = false)
{
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
}
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(InfoHash hash,
const std::shared_ptr<crypto::PublicKey>& to,
Value&& value,
DoneCallback cb = {},
bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(InfoHash hash,
const std::shared_ptr<crypto::PublicKey>& to,
Value&& value,
DoneCallbackSimple cb,
bool permanent = false)
{
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
}
void putEncrypted(
InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallback cb = {}, bool permanent = false);
void putEncrypted(
InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false)
{
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
}
/**
* Insert known nodes to the routing table, without necessarly ping them.
* Usefull to restart a node and get things running fast without putting load on the network.
*/
void bootstrap(std::vector<SockAddr> nodes, DoneCallbackSimple cb = {});
void bootstrap(SockAddr addr, DoneCallbackSimple cb = {});
/**
* Insert known nodes to the routing table, without necessarly ping them.
* Usefull to restart a node and get things running fast without putting load on the network.
*/
void bootstrap(std::vector<NodeExport> nodes);
/**
* Add host:service to bootstrap nodes, and ping this node.
* DNS resolution is performed asynchronously.
* When disconnected, all bootstrap nodes added with this method will be tried regularly until connection
* to the DHT network is established.
*/
void bootstrap(const std::string& host, const std::string& service);
void bootstrap(const std::string& hostService);
/**
* Insert known nodes to the routing table, without necessarly ping them.
* Usefull to restart a node and get things running fast without putting load on the network.
*/
void bootstrap(const InfoHash& id, const SockAddr& address);
/**
* Clear the list of bootstrap added using bootstrap(const std::string&, const std::string&).
*/
void clearBootstrap();
/**
* Inform the DHT of lower-layer connectivity changes.
@@ -204,63 +381,83 @@ public:
void dumpTables() const;
InfoHash getId() const;
/**
* Get the public key fingerprint if an identity is used with this node, 0 otherwise.
*/
[[deprecated("Use getPublicKey()->getLongId() instead")]] InfoHash getId() const;
std::shared_ptr<crypto::PublicKey> getPublicKey() const;
/**
* Get the ID of the DHT node.
*/
InfoHash getNodeId() const;
/**
* Returns the currently bound address.
* @param f: address family of the bound address to retreive.
*/
const Address& getBound(sa_family_t f = AF_INET) const {
return (f == AF_INET) ? bound4 : bound6;
}
SockAddr getBound(sa_family_t f = AF_INET) const;
/**
* Returns the currently bound port, in host byte order.
* @param f: address family of the bound port to retreive.
*/
in_port_t getBoundPort(sa_family_t f = AF_INET) const {
return ntohs(((sockaddr_in*)&getBound(f).first)->sin_port);
}
in_port_t getBoundPort(sa_family_t f = AF_INET) const;
std::pair<size_t, size_t> getStoreSize() const;
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT);
size_t getStorageLimit() const;
void setStorageLimit(size_t limit = 0);
size_t getLocalStorageLimit() const;
void setLocalStorageLimit(size_t limit = 0);
std::vector<NodeExport> exportNodes() const;
std::vector<ValuesExport> exportValues() const;
void setLoggers(LogMethod err = NOLOG, LogMethod warn = NOLOG, LogMethod debug = NOLOG);
void setLogger(const Sp<Logger>& logger = {});
/**
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
*/
void setLogFilter(const InfoHash& f = {});
void registerType(const ValueType& type);
void registerInsecureType(const ValueType& type);
void importValues(const std::vector<ValuesExport>& values);
bool isRunning() const {
return running;
}
bool isRunning() const { return running != State::Idle; }
int getNodesStats(sa_family_t af, unsigned *good_return, unsigned *dubious_return, unsigned *cached_return, unsigned *incoming_return) const;
NodeStats getNodesStats(sa_family_t af) const;
unsigned getNodesStats(sa_family_t af,
unsigned* good_return,
unsigned* dubious_return,
unsigned* cached_return,
unsigned* incoming_return) const;
NodeInfo getNodeInfo() const;
void getNodeInfo(std::function<void(std::shared_ptr<NodeInfo>)>);
std::vector<unsigned> getNodeMessageStats(bool in = false) const;
std::string getStorageLog() const;
std::string getStorageLog(const InfoHash&) const;
std::string getRoutingTablesLog(sa_family_t af) const;
std::string getSearchesLog(sa_family_t af = 0) const;
std::vector<Address> getPublicAddress(sa_family_t af = 0);
std::vector<std::string> getPublicAddressStr(sa_family_t af = 0);
std::string getSearchesLog(sa_family_t af = AF_UNSPEC) const;
std::string getSearchLog(const InfoHash&, sa_family_t af = AF_UNSPEC) const;
std::vector<SockAddr> getPublicAddress(sa_family_t af = AF_UNSPEC) const;
std::vector<std::string> getPublicAddressStr(sa_family_t af = AF_UNSPEC) const;
void getPublicAddress(std::function<void(std::vector<SockAddr>&&)>, sa_family_t af = AF_UNSPEC);
// securedht methods
void findCertificate(InfoHash hash, std::function<void(const std::shared_ptr<crypto::Certificate>)>);
void registerCertificate(std::shared_ptr<crypto::Certificate> cert);
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
[[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>&)>);
struct Config {
SecureDhtConfig dht_config;
bool threaded;
};
void registerCertificate(const std::shared_ptr<crypto::Certificate>& cert);
void setLocalCertificateStore(CertificateStoreQueryLegacy&& query_method);
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
/**
* @param port: Local port to bind. Both IPv4 and IPv6 will be tried (ANY).
@@ -268,37 +465,31 @@ public:
* @param threaded: If false, ::loop() must be called periodically. Otherwise a thread is launched.
* @param cb: Optional callback to receive general state information.
*/
void run(in_port_t port, const crypto::Identity identity, bool threaded = false, bool is_bootstrap = false) {
run(port, {
/*.dht_config = */{
/*.node_config = */{
/*.node_id = */{},
/*.is_bootstrap = */is_bootstrap
},
/*.id = */identity
},
/*.threaded = */threaded
});
void run(in_port_t port = dht::net::DHT_DEFAULT_PORT,
const crypto::Identity& identity = {},
bool threaded = true,
NetId network = 0)
{
Config config;
config.dht_config.node_config.network = network;
config.dht_config.id = identity;
config.threaded = threaded;
run(port, config);
}
void run(in_port_t port, Config config);
void run(in_port_t port, Config& config, Context&& context = {});
/**
* @param local4: Local IPv4 address and port to bind. Can be null.
* @param local6: Local IPv6 address and port to bind. Can be null.
* You should allways bind to a global IPv6 address.
* @param identity: RSA key pair to use for cryptographic operations.
* @param threaded: If false, loop() must be called periodically. Otherwise a thread is launched.
* @param cb: Optional callback to receive general state information.
* Same as @run(sockaddr_in, sockaddr_in6, Identity, bool, StatusCallback), but with string IP addresses and service
* (port).
*/
void run(const sockaddr_in* local4, const sockaddr_in6* local6, Config config);
void run(const char* ip4, const char* ip6, const char* service, Config& config, Context&& context = {});
/**
* Same as @run(sockaddr_in, sockaddr_in6, Identity, bool, StatusCallback), but with string IP addresses and service (port).
*/
void run(const char* ip4, const char* ip6, const char* service, Config config);
void run(const Config& config, Context&& context);
void setOnStatusChanged(StatusCallback&& cb) {
statusCb = std::move(cb);
void setOnStatusChanged(StatusCallback&& cb)
{
if (cb)
statusCbs.emplace_back(std::move(cb));
}
/**
@@ -306,7 +497,8 @@ public:
* regularly and everytime a new packet is received.
* @return the next op
*/
time_point loop() {
time_point loop()
{
std::lock_guard<std::mutex> lck(dht_mtx);
return loop_();
}
@@ -314,47 +506,106 @@ public:
/**
* Gracefuly disconnect from network.
*/
void shutdown(ShutdownCallback cb);
void shutdown(ShutdownCallback cb = {}, bool stop = false);
/**
* Quit and wait for all threads to terminate.
* No callbacks will be called after this method returns.
* All internal state will be lost. The DHT can then be run again with @run().
* Stop the node and wait for all threads to terminate.
* The node is reset to its default state. The DHT can then be run again with @run().
* No DHT callbacks will run after this method returns.
* Calling this method is optional. It allows to ensure the destructor won't block.
* This method is unable to be called from a DHT callback.
*/
void join();
std::shared_ptr<PeerDiscovery> getPeerDiscovery() const { return peerDiscovery_; };
void setProxyServer(const std::string& proxy, const std::string& pushNodeId = "");
/**
* Start or stop the proxy
* @param proxify if we want to use the proxy
*/
void enableProxy(bool proxify);
/* Push notification methods */
/**
* Updates the push notification device token
*/
void setPushNotificationToken(const std::string& token);
/**
* Sets the push notification topic
*/
void setPushNotificationTopic(const std::string& topic);
/**
* Sets the push notification platform
*/
void setPushNotificationPlatform(const std::string& platform);
/**
* Insert a push notification to process for OpenDHT
*/
std::future<PushNotificationResult> pushNotificationReceived(const std::map<std::string, std::string>& data);
/* Proxy server mothods */
void forwardAllMessages(bool forward);
private:
enum class State { Idle, Running, Stopping };
void doRun(const sockaddr_in* sin4, const sockaddr_in6* sin6, SecureDhtConfig config);
time_point loop_();
static std::vector<std::pair<sockaddr_storage, socklen_t>> getAddrInfo(const char* host, const char* service);
NodeStatus getStatus() const { return std::max(status4, status6); }
NodeStatus getStatus() const {
return std::max(status4, status6);
}
bool checkShutdown();
void opEnded();
DoneCallback bindOpDoneCallback(DoneCallback&& cb);
DoneCallbackSimple bindOpDoneCallback(DoneCallbackSimple&& cb);
/** DHT instance */
std::unique_ptr<SecureDht> dht_;
mutable std::mutex dht_mtx {};
/** true if we are currently using a proxy */
std::atomic_bool use_proxy {false};
/** Current configuration */
Config config_;
IdentityAnnouncedCb identityAnnouncedCb_;
/**
* reset dht clients
*/
void resetDht();
mutable std::mutex dht_mtx;
std::thread dht_thread {};
std::condition_variable cv {};
std::thread rcv_thread {};
std::mutex sock_mtx {};
std::vector<std::pair<Blob, std::pair<sockaddr_storage, socklen_t>>> rcv {};
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<bool> running {false};
std::atomic<State> running {State::Idle};
std::atomic_size_t ongoing_ops {0};
std::vector<ShutdownCallback> shutdownCallbacks_;
NodeStatus status4 {NodeStatus::Disconnected},
status6 {NodeStatus::Disconnected};
StatusCallback statusCb {nullptr};
NodeStatus status4 {NodeStatus::Disconnected}, status6 {NodeStatus::Disconnected};
Address bound4 {};
Address bound6 {};
std::vector<StatusCallback> statusCbs {};
/** PeerDiscovery Parameters */
std::shared_ptr<PeerDiscovery> peerDiscovery_;
/**
* The Logger instance is used in enableProxy and other methods that
* would create instances of classes using a common logger.
*/
std::shared_ptr<dht::Logger> logger_;
};
}
} // namespace dht
+374
View File
@@ -0,0 +1,374 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include "infohash.h"
#include "crypto.h"
// some libraries may try to redefine snprintf
// but restinio will use it in std namespace
#ifdef _MSC_VER
#undef snprintf
#define snprintf snprintf
#endif
#include <asio/ip/tcp.hpp>
#include <asio/streambuf.hpp>
#include <asio/ssl/context.hpp>
#include <restinio/message_builders.hpp>
#include <memory>
#include <queue>
#include <mutex>
#include <future>
namespace Json {
class Value;
}
namespace restinio {
namespace impl {
class tls_socket_t;
}
} // namespace restinio
namespace dht {
namespace log {
struct Logger;
}
namespace crypto {
struct Certificate;
}
namespace http {
using HandlerCb = std::function<void(const asio::error_code& ec)>;
using BytesHandlerCb = std::function<void(const asio::error_code& ec, size_t bytes)>;
using ConnectHandlerCb = std::function<void(const asio::error_code& ec, const asio::ip::tcp::endpoint& endpoint)>;
using ssl_socket_t = restinio::impl::tls_socket_t;
using socket_t = asio::ip::tcp::socket;
class OPENDHT_PUBLIC Url
{
public:
Url() = default;
Url(std::string_view url);
std::string url;
std::string protocol {"http"};
std::string_view user;
std::string_view password;
std::string_view host;
std::string_view service;
std::string target;
std::string_view query;
std::string_view fragment;
std::string toString() const;
};
class OPENDHT_PUBLIC Connection : public std::enable_shared_from_this<Connection>
{
public:
Connection(asio::io_context& ctx, const bool ssl = true, std::shared_ptr<log::Logger> l = {});
Connection(asio::io_context& ctx,
std::shared_ptr<dht::crypto::Certificate> server_ca,
const dht::crypto::Identity& identity,
std::shared_ptr<log::Logger> l = {});
~Connection();
inline unsigned int id() const { return id_; };
bool is_open() const;
bool is_ssl() const;
void checkOcsp(bool check = true) { checkOcsp_ = check; }
void set_ssl_verification(const std::string& hostname, const asio::ssl::verify_mode verify_mode);
asio::streambuf& input();
std::istream& data() { return istream_; }
std::string read_bytes(size_t bytes = 0);
std::string read_until(const char delim);
void async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb);
void async_handshake(HandlerCb cb);
void async_write(BytesHandlerCb cb);
void async_read_until(const char* delim, BytesHandlerCb cb);
void async_read_until(char delim, BytesHandlerCb cb);
void async_read(size_t bytes, BytesHandlerCb cb);
void async_read_some(size_t bytes, BytesHandlerCb cb);
void set_keepalive(uint32_t seconds);
const asio::ip::address& local_address() const;
void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {});
void close();
private:
template<typename T>
T wrapCallback(T cb) const
{
return [t = shared_from_this(), cb = std::move(cb)](auto... params) {
cb(params...);
};
}
mutable std::mutex mutex_;
unsigned int id_;
static std::atomic_uint ids_;
asio::io_context& ctx_;
std::unique_ptr<socket_t> socket_;
std::shared_ptr<asio::ssl::context> ssl_ctx_;
std::unique_ptr<ssl_socket_t> ssl_socket_;
asio::ip::tcp::endpoint endpoint_;
asio::streambuf write_buf_;
asio::streambuf read_buf_;
std::istream istream_;
asio::ip::address local_address_;
std::unique_ptr<asio::steady_timer> timeout_timer_;
std::shared_ptr<log::Logger> logger_;
bool checkOcsp_ {false};
};
/* @class Resolver
* @brief The purpose is to only resolve once to avoid mutliple dns requests per operation.
*/
class OPENDHT_PUBLIC Resolver
{
public:
using ResolverCb
= std::function<void(const asio::error_code& ec, const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<log::Logger> logger = {});
Resolver(asio::io_context& ctx,
std::string_view host,
std::string_view service,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
// use already resolved endpoints with classes using this resolver
Resolver(asio::io_context& ctx,
std::vector<asio::ip::tcp::endpoint> endpoints,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
Resolver(asio::io_context& ctx,
const std::string& url,
std::vector<asio::ip::tcp::endpoint> endpoints,
std::shared_ptr<log::Logger> logger = {});
~Resolver();
inline const Url& get_url() const { return url_; }
void add_callback(ResolverCb cb, sa_family_t family = AF_UNSPEC);
std::shared_ptr<log::Logger> getLogger() const { return logger_; }
void cancel();
private:
void resolve(std::string_view host, std::string_view service);
mutable std::mutex mutex_;
Url url_;
asio::error_code ec_;
asio::ip::tcp::resolver resolver_;
std::shared_ptr<bool> destroyed_;
std::vector<asio::ip::tcp::endpoint> endpoints_;
bool completed_ {false};
std::queue<ResolverCb> cbs_;
std::shared_ptr<log::Logger> logger_;
};
class Request;
struct Response
{
unsigned status_code {0};
std::map<std::string, std::string> headers;
std::string body;
bool aborted {false};
std::weak_ptr<Request> request;
};
class OPENDHT_PUBLIC Request : public std::enable_shared_from_this<Request>
{
public:
enum class State { CREATED, SENDING, HEADER_RECEIVED, RECEIVING, DONE };
using OnStatusCb = std::function<void(unsigned status_code)>;
using OnDataCb = std::function<void(const char* at, size_t length)>;
using OnStateChangeCb = std::function<void(State state, const Response& response)>;
using OnJsonCb = std::function<void(Json::Value value, const Response& response)>;
using OnDoneCb = std::function<void(const Response& response)>;
// resolves implicitly
Request(asio::io_context& ctx,
const std::string& url,
const Json::Value& json,
OnJsonCb jsoncb,
std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx,
std::string_view host,
std::string_view service,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, OnDoneCb onDone, std::shared_ptr<log::Logger> logger = {});
// user defined resolver
Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
Request(asio::io_context& ctx,
std::shared_ptr<Resolver> resolver,
const std::string& target,
sa_family_t family = AF_UNSPEC);
// user defined resolved endpoints
Request(asio::io_context& ctx,
std::vector<asio::ip::tcp::endpoint>&& endpoints,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
~Request();
inline unsigned int id() const { return id_; };
void set_connection(std::shared_ptr<Connection> connection);
std::shared_ptr<Connection> get_connection() const;
inline const Url& get_url() const { return resolver_->get_url(); };
void timeout(const std::chrono::seconds& timeout, HandlerCb cb = {})
{
timeout_ = timeout;
timeoutCb_ = cb;
}
/** The previous request in case of redirect following */
std::shared_ptr<Request> getPrevious() const { return prev_.lock(); }
inline std::string& to_string() { return request_; }
void set_certificate_authority(std::shared_ptr<dht::crypto::Certificate> certificate);
void set_identity(const dht::crypto::Identity& identity);
void set_logger(std::shared_ptr<log::Logger> logger);
/**
* Define the HTTP header/body as per https://tools.ietf.org/html/rfc7230.
*/
void set_header(restinio::http_request_header_t header);
void set_method(restinio::http_method_id_t method);
void set_target(std::string target);
void set_header_field(restinio::http_field_t field, std::string value);
void set_connection_type(restinio::http_connection_header_t connection);
void set_body(std::string body);
void set_body(const uint8_t* data, size_t length);
void set_auth(const std::string& username, const std::string& password);
void add_on_status_callback(OnStatusCb cb);
void add_on_body_callback(OnDataCb cb);
void add_on_state_change_callback(OnStateChangeCb cb);
void add_on_done_callback(OnDoneCb cb);
void send();
/** Send and block for response */
const Response& await();
/**
* User action to cancel the Request and call the completion callbacks.
*/
void cancel();
void terminate(const asio::error_code& ec);
private:
using OnCompleteCb = std::function<void()>;
struct Callbacks
{
OnStatusCb on_status;
OnDataCb on_header_field;
OnDataCb on_header_value;
OnDataCb on_body;
OnStateChangeCb on_state_change;
};
static std::string getRelativePath(const Url& origin, const std::string& path);
void notify_state_change(State state);
void build();
static std::string url_encode(std::string_view value);
void init_default_headers();
/**
* Initialized and wraps the llhttp callbacks with our user defined callbacks.
*/
void init_parser();
void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
void post();
void handle_request(const asio::error_code& ec);
void handle_response(const asio::error_code& ec, size_t bytes);
void onHeadersComplete();
void onBody(const char* at, size_t length);
void onComplete();
mutable std::mutex mutex_;
std::shared_ptr<log::Logger> logger_;
restinio::http_request_header_t header_;
std::map<restinio::http_field_t, std::string> headers_;
restinio::http_connection_header_t connection_type_ {restinio::http_connection_header_t::close};
std::string body_;
Callbacks cbs_;
State state_;
dht::crypto::Identity client_identity_;
std::shared_ptr<dht::crypto::Certificate> server_ca_;
std::string service_;
std::string host_;
unsigned int id_;
static std::atomic_uint ids_;
asio::io_context& ctx_;
sa_family_t family_ = AF_UNSPEC;
std::shared_ptr<Connection> conn_;
std::shared_ptr<Resolver> resolver_;
Response response_ {};
std::string request_;
std::atomic<bool> finishing_ {false};
std::unique_ptr<llhttp_t> parser_;
std::unique_ptr<llhttp_settings_t> parser_s_;
// Next request in case of redirect following
std::shared_ptr<Request> next_;
std::weak_ptr<Request> prev_;
unsigned num_redirect {0};
bool follow_redirect {true};
HandlerCb timeoutCb_ {};
std::chrono::seconds timeout_ {0};
};
} // namespace http
} // namespace dht
+546
View File
@@ -0,0 +1,546 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <map>
#include <functional>
#include <stdexcept>
#include <bitset>
#include <iostream>
#include <sstream>
#include "../value.h"
#include "../dhtrunner.h"
#include "../infohash.h"
namespace dht {
namespace indexation {
/*!
* @class Prefix
* @brief A blob structure which prefixes a Key in the PHT.
* @details
* Since the PHT structure is a "trie", every node in this structure have a
* label which is defined by the path from the root of the trie to the node. If
* the node in question is a leaf, *the label is a prefix of all the keys
* contained in the leaf*.
*/
struct OPENDHT_PUBLIC Prefix
{
Prefix() {}
Prefix(InfoHash h)
: size_(h.size() * 8)
, content_(h.begin(), h.end())
{}
Prefix(const Blob& d, const Blob& f = {})
: size_(d.size() * 8)
, flags_(f)
, content_(d)
{}
Prefix(const Prefix& p, size_t first)
: size_(std::min(first, p.content_.size() * 8))
, content_(Blob(p.content_.begin(), p.content_.begin() + size_ / 8))
{
auto rem = size_ % 8;
if (not p.flags_.empty()) {
flags_ = Blob(p.flags_.begin(), p.flags_.begin() + size_ / 8);
if (rem)
flags_.push_back(p.flags_[size_ / 8] & (0xFF << (8 - rem)));
}
if (rem)
content_.push_back(p.content_[size_ / 8] & (0xFF << (8 - rem)));
}
/**
* Get a sub prefix of the Prefix
*
* @param len lenght of the prefix to get, could be negative
* if len is negativ then you will get the prefix
* of size of the previous prefix minus len
*
* @return Sub-prefix of size len or if len is negative sub-prefix of size
* of prefix minus len
*
* @throw out_of_range if len is larger than size of the content
*/
Prefix getPrefix(ssize_t len) const
{
if ((size_t) std::abs(len) >= content_.size() * 8)
throw std::out_of_range("len larger than prefix size.");
if (len < 0)
len += size_;
return Prefix(*this, len);
}
/**
* Flags are considered as active if flag is empty or if the flag
* at pos 'pos' is active
ee *
* @see isActiveBit in private function
*/
bool isFlagActive(size_t pos) const { return flags_.empty() or isActiveBit(flags_, pos); }
/**
* @see isActiveBit in private function
*/
bool isContentBitActive(size_t pos) const { return isActiveBit(content_, pos); }
Prefix getFullSize() { return Prefix(*this, content_.size() * 8); }
/**
* This methods gets the prefix of its sibling in the PHT structure.
*
* @return The prefix of this sibling.
*/
Prefix getSibling() const
{
Prefix copy = *this;
if (size_)
copy.swapContentBit(size_ - 1);
return copy;
}
InfoHash hash() const
{
Blob copy(content_);
copy.push_back(size_);
return InfoHash::get(copy);
}
/**
* This method count total of bit in common between 2 prefix
*
* @param p1 first prefix to compared
* @param p2 second prefix to compared
* @return Lenght of the larger common prefix between both
*/
static inline unsigned commonBits(const Prefix& p1, const Prefix& p2)
{
unsigned i, j;
uint8_t x;
auto longest_prefix_size = std::min(p1.size_, p2.size_);
for (i = 0; i < longest_prefix_size; i++) {
if (p1.content_.data()[i] != p2.content_.data()[i] or not p1.isFlagActive(i) or not p2.isFlagActive(i)) {
break;
}
}
if (i == longest_prefix_size)
return 8 * longest_prefix_size;
x = p1.content_.data()[i] ^ p2.content_.data()[i];
j = 0;
while ((x & 0x80) == 0) {
x <<= 1;
j++;
}
return 8 * i + j;
}
/**
* @see doc of swap private function
*/
void swapContentBit(size_t bit) { swapBit(content_, bit); }
/**
* @see doc of swap private function
*/
void swapFlagBit(size_t bit) { swapBit(flags_, bit); }
/**
* @see doc of addPadding private function
*/
void addPaddingContent(size_t size) { content_ = addPadding(content_, size); }
void updateFlags()
{
/* Fill first known bit */
auto csize = size_ - flags_.size() * 8;
while (csize >= 8) {
flags_.push_back(0xFF);
csize -= 8;
}
/* if needed fill remaining bit */
if (csize)
flags_.push_back(0xFF << (8 - csize));
/* Complet vector space missing */
for (auto i = flags_.size(); i < content_.size(); i++)
flags_.push_back(0xFF);
}
std::string toString() const;
size_t size_ {0};
/* Will contain flags according to content_.
If flags_[i] == 0, then content_[i] is unknown
else if flags_[i] == 1, then content_[i] is known */
Blob flags_ {};
Blob content_ {};
private:
/**
* Add a padding to the input blob
*
* @param toP : Prefix where to add a padding
* @param size : Final size of the prefix with padding
*
* @return Copy of the input Blob but with a padding
*/
Blob addPadding(Blob toP, size_t size)
{
Blob copy = toP;
for (auto i = copy.size(); i < size; i++)
copy.push_back(0);
swapBit(copy, size_ + 1);
return copy;
}
/**
* Check if the bit a pos 'pos' is active, i.e. equal to 1
*
* @param b : Blob to check
* @param pos : Position to check
*
* @return true if the bit is equal to 1, false otherwise
*
* @throw out_of_range if bit is superior to blob size * 8
*/
bool isActiveBit(const Blob& b, size_t pos) const
{
if (pos >= content_.size() * 8)
throw std::out_of_range("Can't detect active bit at pos, pos larger than prefix size or empty prefix");
return ((b[pos / 8] >> (7 - (pos % 8))) & 1) == 1;
}
/**
* Swap bit at position bit [from 0 to 1 and vice-versa]
*
* @param b : Blob to swap
* @param bit : Bit to swap on b
*
* @return the input prefix with the bit at pos 'bit' swapped
*
* @throw out_of_range if bit is superior to blob size * 8
*/
void swapBit(Blob& b, size_t bit)
{
if (bit >= b.size() * 8)
throw std::out_of_range("bit larger than prefix size.");
size_t offset_bit = (8 - bit) % 8;
b[bit / 8] ^= (1 << offset_bit);
}
};
using Value = std::pair<InfoHash, dht::Value::Id>;
struct OPENDHT_PUBLIC IndexEntry : public dht::Value::Serializable<IndexEntry>
{
static const ValueType& TYPE;
virtual void unpackValue(const dht::Value& v)
{
Serializable<IndexEntry>::unpackValue(v);
name = v.user_type;
}
virtual dht::Value packValue() const
{
auto pack = Serializable<IndexEntry>::packValue();
pack.user_type = name;
return pack;
}
Blob prefix;
Value value;
std::string name;
MSGPACK_DEFINE_MAP(prefix, value)
};
class OPENDHT_PUBLIC Pht
{
static constexpr const char* INVALID_KEY = "Key does not match the PHT key spec.";
/* Prefixes the user_type for all dht values put on the DHT */
static constexpr const char* INDEX_PREFIX = "index.pht.";
public:
/* This is the maximum number of entries per node. This parameter is
* critical and influences the traffic a lot during a lookup operation.
*/
static constexpr const size_t MAX_NODE_ENTRY_COUNT {16};
/* A key for a an index entry */
using Key = std::map<std::string, Blob>;
/* Specifications of the keys. It defines the number, the length and the
* serialization order of fields. */
using KeySpec = std::map<std::string, size_t>;
using LookupCallback = std::function<void(std::vector<std::shared_ptr<Value>>& values, const Prefix& p)>;
typedef void (*LookupCallbackRaw)(std::vector<std::shared_ptr<Value>>* values, Prefix* p, void* user_data);
static LookupCallback bindLookupCb(LookupCallbackRaw raw_cb, void* user_data)
{
if (not raw_cb)
return {};
return [=](std::vector<std::shared_ptr<Value>>& values, const Prefix& p) {
raw_cb((std::vector<std::shared_ptr<Value>>*) &values, (Prefix*) &p, user_data);
};
}
using LookupCallbackSimple = std::function<void(std::vector<std::shared_ptr<Value>>& values)>;
typedef void (*LookupCallbackSimpleRaw)(std::vector<std::shared_ptr<Value>>* values, void* user_data);
static LookupCallbackSimple bindLookupCbSimple(LookupCallbackSimpleRaw raw_cb, void* user_data)
{
if (not raw_cb)
return {};
return [=](std::vector<std::shared_ptr<Value>>& values) {
raw_cb((std::vector<std::shared_ptr<Value>>*) &values, user_data);
};
}
Pht(std::string name, KeySpec k_spec, std::shared_ptr<DhtRunner> dht)
: name_(INDEX_PREFIX + name)
, canary_(name_ + ".canary")
, keySpec_(k_spec)
, dht_(dht)
{}
virtual ~Pht() {}
/**
* Lookup a key for a value.
*/
void lookup(Key k, LookupCallback cb = {}, DoneCallbackSimple done_cb = {}, bool exact_match = true);
void lookup(Key k, LookupCallbackSimple cb = {}, DoneCallbackSimple done_cb = {}, bool exact_match = true)
{
lookup(
k,
[cb = std::move(cb)](std::vector<std::shared_ptr<Value>>& values, Prefix) { cb(values); },
done_cb,
exact_match);
}
/**
* Wrapper function which call the private one.
*
* @param k : Key to insert [i.e map of string, blob]
* @param v : Value to insert
* @param done_cb : Callbakc which going to be call when all the insert is done
*/
void insert(Key k, Value v, DoneCallbackSimple done_cb = {})
{
Prefix p = linearize(k);
auto lo = std::make_shared<int>(0);
auto hi = std::make_shared<int>(p.size_);
IndexEntry entry;
entry.value = v;
entry.prefix = p.content_;
entry.name = name_;
Pht::insert(p, entry, lo, hi, clock::now(), true, done_cb);
}
private:
/**
* Insert function which really insert onto the pht
*
* @param kp : Prefix to insert (linearize the the key)
* @param entry : Entry created from the value
* @param lo : Lowest point to start in the prefix
* @param hi : Highest point to end in the prefix
* @param time_p : Timepoint to use for the insertion into the dht (must be < now)
* @param check_split : If this flag is true then the algoritm will not use the merge algorithm
* @param done_cb : Callback to call when the insert is done
*/
void insert(const Prefix& kp,
IndexEntry entry,
std::shared_ptr<int> lo,
std::shared_ptr<int> hi,
time_point time_p,
bool check_split,
DoneCallbackSimple done_cb = {});
class Cache
{
public:
/**
* Insert all needed node into the tree according to a prefix
* @param p : Prefix that we need to insert
*/
void insert(const Prefix& p);
/**
* Lookup into the tree to return the maximum prefix length in the cache tree
*
* @param p : Prefix that we are looking for
*
* @return : The size of the longest prefix known in the cache between 0 and p.size_
*/
int lookup(const Prefix& p);
private:
static constexpr const size_t MAX_ELEMENT {1024};
static constexpr const std::chrono::minutes NODE_EXPIRE_TIME {5};
struct Node
{
time_point last_reply; /* Made the assocation between leaves and leaves multimap */
std::shared_ptr<Node> parent; /* Share_ptr to the parent, it allow the self destruction of tree */
std::weak_ptr<Node> left_child; /* Left child, for bit equal to 1 */
std::weak_ptr<Node> right_child; /* Right child, for bit equal to 0 */
};
std::weak_ptr<Node> root_; /* Root of the tree */
/**
* This mutlimap contains all prefix insert in the tree in time order
* We could then delete the last one if there are too many nodes
* The tree will self destroy is branch ( thanks to share_ptr )
*/
std::multimap<time_point, std::shared_ptr<Node>> leaves_;
};
/* Callback used for insert value by using the pht */
using RealInsertCallback = std::function<void(const Prefix& p, IndexEntry entry)>;
using LookupCallbackWrapper = std::function<void(std::vector<std::shared_ptr<IndexEntry>>& values, const Prefix& p)>;
/**
* Performs a step in the lookup operation. Each steps are performed
* asynchronously.
*
* @param k : Prefix on which the lookup is performed
* @param lo : lowest bound on the prefix (where to start)
* @param hi : highest bound on the prefix (where to stop)
* @param vals : Shared ptr to a vector of IndexEntry (going to contains all values found)
* @param cb : Callback to use at the end of the lookupStep (call on the value of vals)
* @param done_cb : Callback at the end of the lookupStep
* @param max_common_prefix_len: used in the inexacte lookup match case, indicate the longest common prefix found
* @param start : If start is set then lo and hi will be ignore for the first step, if the step fail lo and hi
* will be used
* @param all_values : If all value is true then all value met during the lookupstep will be in the vector vals
*/
void lookupStep(Prefix k,
std::shared_ptr<int> lo,
std::shared_ptr<int> hi,
std::shared_ptr<std::vector<std::shared_ptr<IndexEntry>>> vals,
LookupCallbackWrapper cb,
DoneCallbackSimple done_cb,
std::shared_ptr<unsigned> max_common_prefix_len,
int start = -1,
bool all_values = false);
/**
* Apply the zcurve algorithm on the list of input prefix
*
* @param all_prefix : Vector of prefix to interleave
*
* @return The output prefix where all flags and content are interleaves
*/
Prefix zcurve(const std::vector<Prefix>& all_prefix) const;
/**
* Linearizes the key into a unidimensional key. A pht only takes
* unidimensional key.
*
* @param Key The initial key.
*
* @return the prefix of the linearized key.
*/
virtual Prefix linearize(Key k) const;
/**
* Looking where to put the data cause if there is free space on the node
* above then this node will became the real leave.
*
* @param p Share_ptr on the Prefix to check
* @param entry The entry to put at the prefix p
* @param end_cb Callback to use at the end of counting
*/
void getRealPrefix(const std::shared_ptr<Prefix>& p, IndexEntry entry, RealInsertCallback end_cb);
/**
* Looking where to put the data cause if there is free space on the node
* above then this node will became the real leave.
*
* @param p Share_ptr on the Prefix to check
* @param entry The entry to put at the prefix p
* @param end_cb Callback to use at the end of counting
*/
void checkPhtUpdate(Prefix p, IndexEntry entry, time_point time_p);
/**
* Search for the split location by comparing 'compared' to all values in vals.
*
* @param compared : Value which going to be compared
* @param vals : The vector of values to compare with comapred
* @return position compared diverge from all others
*/
static size_t findSplitLocation(const Prefix& compared, const std::vector<std::shared_ptr<IndexEntry>>& vals)
{
for (size_t i = 0; i < compared.content_.size() * 8 - 1; i++)
for (auto const& v : vals)
if (Prefix(v->prefix).isContentBitActive(i) != compared.isContentBitActive(i))
return i + 1;
return compared.content_.size() * 8 - 1;
}
/**
* Put canary from the split point until the last known canary and add the prefix at the good place
*
* @param insert : Prefix to insertm but also prefix which going to check where we need to split
* @param vals : Vector of vals for the comparaison
* @param entry : Entry to put on the pht
* @param end_cb : Callback to apply to the insert prefi (here does the insert)
*/
void split(const Prefix& insert,
const std::vector<std::shared_ptr<IndexEntry>>& vals,
IndexEntry entry,
RealInsertCallback end_cb);
/**
* Tells if the key is valid according to the key spec.
*/
bool validKey(const Key& k) const
{
return k.size() == keySpec_.size()
and std::equal(k.begin(),
k.end(),
keySpec_.begin(),
[&](const Key::value_type& key, const KeySpec::value_type& key_spec) {
return key.first == key_spec.first and key.second.size() <= key_spec.second;
});
}
/**
* Updates the canary token on the node responsible for the specified
* Prefix.
*/
void updateCanary(Prefix p);
const std::string name_;
const std::string canary_;
const KeySpec keySpec_;
Cache cache_;
std::shared_ptr<DhtRunner> dht_;
};
} // namespace indexation
} // namespace dht
+345 -122
View File
@@ -1,25 +1,12 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include "rng.h"
#include <msgpack.hpp>
#include <fmt/core.h>
#ifndef _WIN32
#include <netinet/in.h>
@@ -38,90 +25,155 @@ typedef uint16_t in_port_t;
#include <iomanip>
#include <array>
#include <vector>
#include <string_view>
#include <algorithm>
#include <stdexcept>
#include <sstream>
#include <cstring>
// bytes
#define HASH_LEN 20u
#include <cstddef>
namespace dht {
/**
* Represents an InfoHash.
* An InfoHash is a byte array of HASH_LEN bytes.
* InfoHashes identify nodes and values in the Dht.
*/
class InfoHash final : public std::array<uint8_t, HASH_LEN> {
public:
constexpr InfoHash() : std::array<uint8_t, HASH_LEN>() {}
constexpr InfoHash(const std::array<uint8_t, HASH_LEN>& h) : std::array<uint8_t, HASH_LEN>(h) {}
InfoHash(const uint8_t* h, size_t h_len) : std::array<uint8_t, HASH_LEN>() {
if (h_len < HASH_LEN)
fill(0);
else
std::copy_n(h, HASH_LEN, begin());
}
using byte = uint8_t;
namespace crypto {
OPENDHT_PUBLIC void hash(const uint8_t* data, size_t data_length, uint8_t* hash, size_t hash_length);
}
/**
* Represents an Hash, a byte array of N bytes.
* Hashes identify nodes and values in the Dht.
*/
template<size_t N>
class Hash
{
public:
using T = std::array<uint8_t, N>;
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
constexpr Hash() noexcept
: data_ {}
{}
constexpr Hash(const uint8_t* h, size_t data_len)
: data_(fromBytes(h, data_len))
{}
/**
* Constructor from an hexadecimal string (without "0x").
* hex must be at least 2.HASH_LEN characters long.
* If too long, only the first 2.HASH_LEN characters are read.
* hex must be at least 2.N characters long.
* If too long, only the first 2.N characters are read.
*/
explicit InfoHash(const std::string& hex);
explicit constexpr Hash(std::string_view hex)
: data_(fromString(hex))
{}
InfoHash(const msgpack::object& o) {
msgpack_unpack(o);
Hash(const msgpack::object& o) { msgpack_unpack(o); }
static constexpr size_t size() noexcept { return N; }
constexpr const uint8_t* data() const { return data_.data(); }
uint8_t* data() { return data_.data(); }
iterator begin() { return data_.begin(); }
const_iterator cbegin() const { return data_.cbegin(); }
iterator end() { return data_.end(); }
const_iterator cend() const { return data_.cend(); }
static constexpr inline Hash zero() noexcept { return Hash {}; }
constexpr bool operator==(const Hash& h) const
{
#if __cplusplus >= 202002L
return data_ == h.data_;
#else
for (size_t i = 0; i < N; ++i) {
if (data_[i] != h.data_[i])
return false;
}
return true;
#endif
}
constexpr bool operator!=(const Hash& h) const { return !(*this == h); }
constexpr bool operator<(const Hash& o) const
{
for (unsigned i = 0; i < N; i++) {
if (data_[i] != o.data_[i])
return data_[i] < o.data_[i];
}
return false;
}
constexpr Hash operator^(const Hash& o) const
{
Hash result;
for (auto i = 0u; i < N; i++) {
result[i] = data_[i] ^ o.data_[i];
}
return result;
}
explicit constexpr operator bool() const
{
#if __cplusplus >= 202002L
auto a = reinterpret_cast<const uint32_t*>(data_.data());
auto b = reinterpret_cast<const uint32_t*>(data_.data() + N);
for (; a != b; a++) {
if (*a)
return true;
}
return false;
#else
for (size_t i = 0; i < N; ++i) {
if (data_[i] != 0)
return true;
}
return false;
#endif
}
uint8_t& operator[](size_t index) { return data_[index]; }
constexpr const uint8_t& operator[](size_t index) const { return data_[index]; }
/**
* Find the lowest 1 bit in an id.
* Result will allways be lower than 8*HASH_LEN
* Result will allways be lower than 8*N
*/
inline unsigned lowbit() const {
int i, j;
for(i = HASH_LEN-1; i >= 0; i--)
if((*this)[i] != 0)
constexpr int lowbit() const
{
int i = N - 1;
for (; i >= 0; i--)
if (data_[i] != 0)
break;
if(i < 0)
if (i < 0)
return -1;
for(j = 7; j >= 0; j--)
if(((*this)[i] & (0x80 >> j)) != 0)
int j = 7;
for (; j >= 0; j--)
if ((data_[i] & (0x80 >> j)) != 0)
break;
return 8 * i + j;
}
/**
* Forget about the ``XOR-metric''. An id is just a path from the
* root of the tree, so bits are numbered from the start.
*/
#ifdef WIN32_NATIVE
static inline int cmp(const InfoHash& __restrict id1, const InfoHash& __restrict id2) {
#else
static inline int cmp(const InfoHash& __restrict__ id1, const InfoHash& __restrict__ id2) {
#endif
return std::memcmp(id1.data(), id2.data(), HASH_LEN);
static inline int cmp(const Hash& id1, const Hash& id2)
{
return std::memcmp(id1.data_.data(), id2.data_.data(), N);
}
/** Find how many bits two ids have in common. */
static inline unsigned
commonBits(const InfoHash& id1, const InfoHash& id2)
static constexpr inline unsigned commonBits(const Hash& id1, const Hash& id2)
{
unsigned i, j;
uint8_t x;
for(i = 0; i < HASH_LEN; i++) {
if(id1[i] != id2[i])
unsigned i = 0;
for (; i < N; i++) {
if (id1.data_[i] != id2.data_[i])
break;
}
if(i == HASH_LEN)
return 8*HASH_LEN;
if (i == N)
return 8 * N;
x = id1[i] ^ id2[i];
uint8_t x = id1.data_[i] ^ id2.data_[i];
j = 0;
while((x & 0x80) == 0) {
unsigned j = 0;
while ((x & 0x80) == 0) {
x <<= 1;
j++;
}
@@ -130,97 +182,268 @@ public:
}
/** Determine whether id1 or id2 is closer to this */
int
xorCmp(const InfoHash& id1, const InfoHash& id2) const
constexpr int xorCmp(const Hash& id1, const Hash& id2) const
{
for(unsigned i = 0; i < HASH_LEN; i++) {
uint8_t xor1, xor2;
if(id1[i] == id2[i])
for (unsigned i = 0; i < N; i++) {
if (id1.data_[i] == id2.data_[i])
continue;
xor1 = id1[i] ^ (*this)[i];
xor2 = id2[i] ^ (*this)[i];
if(xor1 < xor2)
return -1;
else
return 1;
uint8_t xor1 = id1.data_[i] ^ data_[i];
uint8_t xor2 = id2.data_[i] ^ data_[i];
return (xor1 < xor2) ? -1 : 1;
}
return 0;
}
bool
getBit(unsigned nbit) const
constexpr bool getBit(unsigned nbit) const
{
auto& num = *(cbegin()+(nbit/8));
auto& num = *(data_.cbegin() + (nbit / 8));
unsigned bit = 7 - (nbit % 8);
return (num >> bit) & 1;
}
void
setBit(unsigned nbit, bool b)
void setBit(unsigned nbit, bool b)
{
auto& num = (*this)[nbit/8];
auto& num = data_[nbit / 8];
unsigned bit = 7 - (nbit % 8);
num ^= (-b ^ num) & (1 << bit);
}
double
toFloat() const
double toFloat() const
{
using D = size_t;
double v = 0.;
for (unsigned i = 0; i < std::min<size_t>(HASH_LEN, sizeof(unsigned)-1); i++)
v += *(cbegin()+i)/(double)(1<<(8*(i+1)));
for (size_t i = 0; i < std::min<size_t>(N, sizeof(D) - 1); i++)
v += *(data_.cbegin() + i) / (double) ((D) 1 << 8 * (i + 1));
return v;
}
bool
operator<(const InfoHash& o) const {
for(unsigned i = 0; i < HASH_LEN; i++) {
if((*this)[i] != o[i])
return (*this)[i] < o[i];
}
return false;
}
static inline Hash get(std::string_view data) { return get((const uint8_t*) data.data(), data.size()); }
static inline InfoHash get(const std::string& data) {
return get((const uint8_t*)data.data(), data.size());
}
static inline Hash get(const std::vector<uint8_t>& data) { return get(data.data(), data.size()); }
static inline InfoHash get(const std::vector<uint8_t>& data) {
return get(data.data(), data.size());
template<size_t H>
static Hash get(const Hash<H>& o)
{
return get(o.data(), o.size());
}
/**
* Computes the hash from a given data buffer of size data_len.
*/
static InfoHash get(const uint8_t* data, size_t data_len);
static Hash get(const uint8_t* data, size_t data_len)
{
Hash ret;
crypto::hash(data, data_len, ret.data(), N);
return ret;
}
static InfoHash getRandom();
static Hash getRandom();
friend std::ostream& operator<< (std::ostream& s, const InfoHash& h);
template<typename Rd>
static Hash getRandom(Rd&);
template<size_t M>
friend std::ostream& operator<<(std::ostream& s, const Hash<M>& h);
template<size_t M>
friend std::istream& operator>>(std::istream& s, Hash<M>& h);
/** Returns view to thread-allocated memory, only valid until the next call to this function. */
std::string_view to_view() const { return std::string_view(to_c_str(), N * 2); }
const char* to_c_str() const;
std::string toString() const;
template <typename Packer>
template<typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_bin(HASH_LEN);
pk.pack_bin_body((char*)data(), HASH_LEN);
pk.pack_bin(N);
pk.pack_bin_body((char*) data_.data(), N);
}
void msgpack_unpack(msgpack::object o) {
if (o.type != msgpack::type::BIN or o.via.bin.size != HASH_LEN)
void msgpack_unpack(msgpack::object o)
{
if (o.type != msgpack::type::BIN or o.via.bin.size != N)
throw msgpack::type_error();
std::copy_n(o.via.bin.ptr, HASH_LEN, data());
std::copy_n(o.via.bin.ptr, N, data_.data());
}
private:
T data_;
static constexpr T fromBytes(const uint8_t*, size_t);
static constexpr T fromString(std::string_view);
};
static constexpr const InfoHash zeroes {};
struct NodeExport {
InfoHash id;
sockaddr_storage ss;
socklen_t sslen;
};
#define HASH_LEN 20u
using InfoHash = Hash<HASH_LEN>;
using h256 = Hash<32>;
using PkId = h256;
template<size_t N>
std::ostream&
operator<<(std::ostream& s, const Hash<N>& h)
{
s.write(h.to_c_str(), N * 2);
return s;
}
template<size_t N>
std::istream&
operator>>(std::istream& s, Hash<N>& h)
{
std::array<char, h.size() * 2> dat;
s.exceptions(std::istream::eofbit | std::istream::failbit);
s.read(&(*dat.begin()), dat.size());
h = Hash<N>(std::string_view(dat.data(), dat.size()));
return s;
}
template<size_t N>
constexpr typename Hash<N>::T
Hash<N>::fromBytes(const uint8_t* in, size_t size)
{
T data {};
if (size < N)
return data;
for (size_t i = 0; i < N; ++i)
data[i] = in[i];
return data;
}
template<size_t N>
constexpr typename Hash<N>::T
Hash<N>::fromString(std::string_view in)
{
T data {};
if (in.size() < 2 * N)
return data;
constexpr auto hex2bin = [](char c, bool& valid) -> uint8_t {
if (c >= 'a' and c <= 'f')
return 10 + c - 'a';
else if (c >= 'A' and c <= 'F')
return 10 + c - 'A';
else if (c >= '0' and c <= '9')
return c - '0';
else {
valid = false;
return 0;
}
};
bool valid = true;
for (size_t i = 0; i < N && valid; i++) {
uint8_t high = hex2bin(in[2 * i], valid);
uint8_t low = hex2bin(in[2 * i + 1], valid);
data[i] = (high << 4) | low;
}
if (!valid)
return {};
return data;
}
template<size_t N>
Hash<N>
Hash<N>::getRandom()
{
Hash h;
std::random_device rdev;
std::uniform_int_distribution<uint32_t> rand_int;
auto a = reinterpret_cast<uint32_t*>(h.data());
auto b = reinterpret_cast<uint32_t*>(h.data() + h.size());
std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
return h;
}
template<size_t N>
template<typename Rd>
Hash<N>
Hash<N>::getRandom(Rd& rdev)
{
Hash h;
std::uniform_int_distribution<uint32_t> rand_int;
auto a = reinterpret_cast<uint32_t*>(h.data());
auto b = reinterpret_cast<uint32_t*>(h.data() + h.size());
std::generate(a, b, std::bind(rand_int, std::ref(rdev)));
return h;
}
struct alignas(std::max_align_t) HexMap : public std::array<std::array<char, 2>, 256>
{
constexpr HexMap()
: std::array<std::array<char, 2>, 256>()
{
for (size_t i = 0; i < size(); i++) {
auto& e = (*this)[i];
e[0] = hex_digits[(i >> 4) & 0x0F];
e[1] = hex_digits[i & 0x0F];
}
}
private:
static constexpr const char* hex_digits = "0123456789abcdef";
};
inline constexpr HexMap hex_map {};
inline std::string
toHex(const uint8_t* data, size_t size)
{
std::string ret(size * 2, '\0');
for (size_t i = 0; i < size; i++) {
auto b = ret.data() + i * 2;
const auto& m = hex_map[data[i]];
*((uint16_t*) b) = *((uint16_t*) &m);
}
return ret;
}
inline std::string
toHex(const std::vector<uint8_t>& data)
{
return toHex(data.data(), data.size());
}
template<size_t N>
constexpr std::array<char, N * 2>
toHexArray(const Hash<N>& h)
{
std::array<char, N * 2> ret {};
for (size_t i = 0; i < N; i++) {
const auto& m = hex_map[h[i]];
ret[i * 2] = m[0];
ret[i * 2 + 1] = m[1];
}
return ret;
}
template<size_t N>
const char*
Hash<N>::to_c_str() const
{
alignas(std::max_align_t) thread_local std::array<char, N * 2 + 1> buf;
for (size_t i = 0; i < N; i++) {
auto b = buf.data() + i * 2;
const auto& m = hex_map[data_[i]];
*((uint16_t*) b) = *((uint16_t*) &m);
}
buf[N * 2] = '\0';
return buf.data();
}
template<size_t N>
std::string
Hash<N>::toString() const
{
return std::string(to_c_str(), N * 2);
}
} // namespace dht
template<size_t N>
struct fmt::formatter<dht::Hash<N>> : formatter<string_view>
{
constexpr auto format(const dht::Hash<N>& c, format_context& ctx) const
{
return formatter<string_view>::format(c.to_view(), ctx);
}
};
+23 -93
View File
@@ -1,108 +1,38 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "dhtrunner.h"
#include "def.h"
#include "logger.h"
#include <iostream>
#include <fstream>
#include <memory>
namespace dht {
class DhtRunner;
/**
* Logging-related functions
*/
namespace log {
/**
* Terminal colors for logging
*/
namespace Color {
enum Code {
FG_RED = 31,
FG_GREEN = 32,
FG_YELLOW = 33,
FG_BLUE = 34,
FG_DEFAULT = 39,
BG_RED = 41,
BG_GREEN = 42,
BG_BLUE = 44,
BG_DEFAULT = 49
};
class Modifier {
const Code code;
public:
constexpr Modifier(Code pCode) : code(pCode) {}
friend std::ostream&
operator<<(std::ostream& os, const Modifier& mod) {
return os << "\033[" << mod.code << 'm';
}
};
}
OPENDHT_PUBLIC
std::shared_ptr<Logger> getStdLogger();
constexpr const Color::Modifier def(Color::FG_DEFAULT);
constexpr const Color::Modifier red(Color::FG_RED);
constexpr const Color::Modifier yellow(Color::FG_YELLOW);
OPENDHT_PUBLIC
std::shared_ptr<Logger> getFileLogger(const std::string& path);
/**
* Print va_list to std::ostream (used for logging).
*/
void
printLog(std::ostream& s, char const* m, va_list args) {
static constexpr int BUF_SZ = 8192;
char buffer[BUF_SZ];
int ret = vsnprintf(buffer, sizeof(buffer), m, args);
if (ret < 0)
return;
s.write(buffer, std::min(ret, BUF_SZ));
if (ret >= BUF_SZ)
s << "[[TRUNCATED]]";
s.put('\n');
}
OPENDHT_PUBLIC
std::shared_ptr<Logger> getSyslogLogger(const char* name);
void
enableLogging(dht::DhtRunner& dht)
{
dht.setLoggers(
[](char const* m, va_list args){ std::cerr << red; printLog(std::cerr, m, args); std::cerr << def; },
[](char const* m, va_list args){ std::cout << yellow; printLog(std::cout, m, args); std::cout << def; },
[](char const* m, va_list args){ printLog(std::cout, m, args); }
);
}
OPENDHT_PUBLIC void enableLogging(dht::DhtRunner& dht);
void
enableFileLogging(dht::DhtRunner& dht, const std::string& path)
{
auto logfile = std::make_shared<std::fstream>();
logfile->open(path, std::ios::out);
OPENDHT_PUBLIC void enableFileLogging(dht::DhtRunner& dht, const std::string& path);
dht.setLoggers(
[=](char const* m, va_list args){ printLog(*logfile, m, args); },
[=](char const* m, va_list args){ printLog(*logfile, m, args); },
[=](char const* m, va_list args){ printLog(*logfile, m, args); }
);
}
OPENDHT_PUBLIC void disableLogging(dht::DhtRunner& dht);
void
disableLogging(dht::DhtRunner& dht)
{
dht.setLoggers(dht::NOLOG, dht::NOLOG, dht::NOLOG);
}
} /* log */
} /* dht */
OPENDHT_PUBLIC void enableSyslog(dht::DhtRunner& dht, const char* name);
} // namespace log
} // namespace dht
+206
View File
@@ -0,0 +1,206 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h"
#include <fmt/format.h>
#include <fmt/printf.h>
#include <functional>
#include <mutex>
#include <string_view>
#include <type_traits>
#include <cstdarg>
#if __cplusplus >= 202002L
#include <source_location>
#endif
namespace dht {
namespace log {
#if __cplusplus >= 202002L
/**
* Extracts the filename from a full file path at compile time.
*/
consteval std::string_view
getfilename(std::string_view path)
{
size_t pos = path.size();
for (size_t i = path.size(); i-- > 0;) {
if (path[i] == '/' || path[i] == '\\') {
pos = i + 1;
break;
}
}
return path.substr(pos);
}
consteval std::string_view
getfunctionname(std::string_view path)
{
size_t pos = 0;
size_t end = path.size();
for (size_t i = 0; i < path.size(); i++) {
if (path[i] == ' ' || path[i] == '\t' || path[i] == ':') {
pos = i + 1;
} else if (path[i] == '(') {
end = i;
break;
}
}
return path.substr(pos, end - pos);
}
#endif
struct source_loc
{
std::string_view file;
std::uint_least32_t line;
std::string_view function;
#if __cplusplus >= 202002L
consteval source_loc(const std::source_location& loc)
: file(getfilename(loc.file_name()))
, line(loc.line())
, function(getfunctionname(loc.function_name()))
{}
#else
constexpr source_loc()
: file()
, line(0)
, function()
{}
#endif
};
enum class LogLevel { debug, warning, error };
using LogMethod = std::function<void(source_loc, LogLevel, std::string_view, std::string&&)>;
template<typename... Args>
struct LogFormat
{
fmt::format_string<Args...> fmt;
source_loc loc;
#if __cplusplus >= 202002L
template<typename S>
consteval LogFormat(const S& s, const std::source_location& l = std::source_location::current())
: fmt(s)
, loc(l)
{}
#else
template<typename S>
constexpr LogFormat(const S& s)
: fmt(s)
, loc()
{}
#endif
};
#if __cplusplus < 202002L
template<class _Tp>
struct type_identity
{
typedef _Tp type;
};
template<class _Tp>
using type_identity_t = typename type_identity<_Tp>::type;
#else
using std::type_identity_t;
#endif
struct OPENDHT_PUBLIC Logger
{
Logger() = delete;
Logger(LogMethod&& l, std::string tag = "")
: logger_(std::move(l))
, tag_(std::move(tag))
, prefix_(tag_.empty() ? "" : fmt::format("[{}] ", tag_))
{
if (!logger_)
throw std::invalid_argument {"logger must be set"};
}
Logger(const Logger& parent, std::string tag)
: logger_(parent.logger_)
, tag_(std::move(tag))
, prefix_(fmt::format("{}[{}] ", parent.prefix_, tag_))
{}
std::shared_ptr<Logger> createChild(std::string tag)
{
std::lock_guard<std::mutex> lock {children_mutex_};
auto child = std::make_shared<Logger>(*this, std::move(tag));
children_.push_back(child);
return child;
}
void setFilter(std::string_view filter)
{
std::lock_guard<std::mutex> 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()) {
c->setFilter(enable_ ? std::string_view {} : filter);
++it;
} else {
it = children_.erase(it);
}
}
}
void setFilter(const InfoHash& f) { setFilter(f.to_view()); }
inline void log0(source_loc loc, LogLevel level, fmt::string_view format, fmt::printf_args args) const
{
if (enable_)
logger_(loc, level, prefix_, fmt::vsprintf(format, args));
}
template<typename... Args>
inline void debug(LogFormat<type_identity_t<Args>...> format, Args&&... args) const
{
if (enable_)
logger_(format.loc, LogLevel::debug, prefix_, fmt::format(format.fmt, std::forward<Args>(args)...));
}
template<typename... Args>
inline void warn(LogFormat<type_identity_t<Args>...> format, Args&&... args) const
{
if (enable_)
logger_(format.loc, LogLevel::warning, prefix_, fmt::format(format.fmt, std::forward<Args>(args)...));
}
template<typename... Args>
inline void error(LogFormat<type_identity_t<Args>...> format, Args&&... args) const
{
if (enable_)
logger_(format.loc, LogLevel::error, prefix_, fmt::format(format.fmt, std::forward<Args>(args)...));
}
template<typename... T>
inline void d(LogFormat<type_identity_t<T>...> format, T&&... args) const
{
log0(format.loc, LogLevel::debug, format.fmt, fmt::make_printf_args(args...));
}
template<typename... T>
inline void w(LogFormat<type_identity_t<T>...> format, T&&... args) const
{
log0(format.loc, LogLevel::warning, format.fmt, fmt::make_printf_args(args...));
}
template<typename... T>
inline void e(LogFormat<type_identity_t<T>...> format, T&&... args) const
{
log0(format.loc, LogLevel::error, format.fmt, fmt::make_printf_args(args...));
}
private:
const LogMethod logger_ = {};
const std::string tag_ {};
const std::string prefix_ {};
std::mutex children_mutex_;
std::vector<std::weak_ptr<Logger>> children_ {};
bool enable_ {true};
};
} // namespace log
using Logger = log::Logger;
} // namespace dht
+410 -290
View File
@@ -1,24 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "node_cache.h"
@@ -28,53 +9,92 @@
#include "scheduler.h"
#include "utils.h"
#include "rng.h"
#include "rate_limiter.h"
#include "logger.h"
#include "network_utils.h"
#include <vector>
#include <string>
#include <functional>
#include <algorithm>
#include <memory>
#include <random>
#include <queue>
namespace dht {
namespace net {
struct Request;
struct Socket;
struct TransId;
#ifndef MSG_CONFIRM
#define MSG_CONFIRM 0
#endif
class DhtProtocolException : public DhtException {
struct NetworkConfig
{
NetId network {0};
ssize_t max_req_per_sec {0};
ssize_t max_peer_req_per_sec {0};
bool is_client {false};
};
class DhtProtocolException : public DhtException
{
public:
// sent to another peer (http-like).
static const constexpr uint16_t NON_AUTHORITATIVE_INFORMATION {203}; /* incomplete request packet. */
static const constexpr uint16_t UNAUTHORIZED {401}; /* wrong tokens. */
static const constexpr uint16_t UNAUTHORIZED {401}; /* incorrect tokens. */
static const constexpr uint16_t NOT_FOUND {404}; /* storage not found */
// for internal use (custom).
static const constexpr uint16_t INVALID_TID_SIZE {421}; /* id was truncated. */
static const constexpr uint16_t UNKNOWN_TID {422}; /* unknown tid */
static const constexpr uint16_t WRONG_NODE_INFO_BUF_LEN {423}; /* node info length is wrong */
static const constexpr uint16_t INVALID_TID_SIZE {421}; /* id was truncated. */
static const constexpr uint16_t UNKNOWN_TID {422}; /* unknown tid */
static const constexpr uint16_t WRONG_NODE_INFO_BUF_LEN {423}; /* node info length is incorrect */
static const std::string GET_NO_INFOHASH; /* received "get" request with no infohash */
static const std::string LISTEN_NO_INFOHASH; /* got "listen" request without infohash */
static const std::string LISTEN_WRONG_TOKEN; /* wrong token in "listen" request */
static const std::string LISTEN_WRONG_TOKEN; /* incorrect token in "listen" request */
static const std::string PUT_NO_INFOHASH; /* no infohash in "put" request */
static const std::string PUT_WRONG_TOKEN; /* got "put" request with wrong token */
static const std::string PUT_WRONG_TOKEN; /* got "put" request with incorrect token */
static const std::string STORAGE_NOT_FOUND; /* got access request for an unknown storage */
static const std::string PUT_INVALID_ID; /* invalid id in "put" request */
DhtProtocolException(uint16_t code, const std::string& msg="", InfoHash failing_node_id={})
: DhtException(msg), msg(msg), code(code), failing_node_id(failing_node_id) {}
DhtProtocolException(uint16_t code, const std::string& msg = "", InfoHash failing_node_id = {})
: DhtException(msg)
, msg(msg)
, code(code)
, failing_node_id(failing_node_id)
{}
std::string getMsg() const { return msg; }
const std::string& getMsg() const { return msg; }
uint16_t getCode() const { return code; }
const InfoHash getNodeId() const { return failing_node_id; }
const InfoHash& getNodeId() const { return failing_node_id; }
private:
std::string msg;
uint16_t code;
const InfoHash failing_node_id;
InfoHash failing_node_id;
};
struct ParsedMessage;
/**
* Answer for a request.
*/
struct RequestAnswer
{
Blob ntoken {};
Value::Id vid {};
std::vector<Sp<Value>> values {};
std::vector<Value::Id> refreshed_values {};
std::vector<Value::Id> expired_values {};
std::vector<Sp<FieldValueIndex>> fields {};
std::vector<Sp<Node>> nodes4 {};
std::vector<Sp<Node>> nodes6 {};
RequestAnswer() {}
RequestAnswer(ParsedMessage&& msg);
};
/*!
* @class NetworkEngine
* @brief An abstraction of communication protocol on the network.
@@ -91,247 +111,319 @@ struct ParsedMessage;
* @param onGetValues callback for "get values" request.
* @param onListen callback for "listen" request.
* @param onAnnounce callback for "announce" request.
* @param onRefresh callback for "refresh" request.
*/
class NetworkEngine final {
struct TransPrefix : public std::array<uint8_t, 2> {
TransPrefix(const std::string& str) : std::array<uint8_t, 2>({{(uint8_t)str[0], (uint8_t)str[1]}}) {}
static const TransPrefix PING;
static const TransPrefix FIND_NODE;
static const TransPrefix GET_VALUES;
static const TransPrefix ANNOUNCE_VALUES;
static const TransPrefix LISTEN;
};
public:
/* Transaction-ids are 4-bytes long, with the first two bytes identifying
* the kind of request, and the remaining two a sequence number in
* host order.
*/
struct TransId final : public std::array<uint8_t, 4> {
static const constexpr uint16_t INVALID {0};
TransId() {}
TransId(const std::array<char, 4>& o) { std::copy(o.begin(), o.end(), begin()); }
TransId(const TransPrefix prefix, uint16_t seqno = 0) {
std::copy_n(prefix.begin(), prefix.size(), begin());
*reinterpret_cast<uint16_t*>(data()+prefix.size()) = seqno;
}
TransId(const char* q, size_t l) : array<uint8_t, 4>() {
if (l > 4) {
length = 0;
} else {
std::copy_n(q, l, begin());
length = l;
}
}
uint16_t getTid() const {
return *reinterpret_cast<const uint16_t*>(&(*this)[2]);
}
bool matches(const TransPrefix prefix, uint16_t* tid = nullptr) const {
if (std::equal(begin(), begin()+2, prefix.begin())) {
if (tid)
*tid = getTid();
return true;
} else
return false;
}
unsigned length {4};
};
/*!
* @class RequestAnswer
* @brief Answer for a request.
* @details
* Answer for a request to be (de)serialized. Used for reponding to a node
* and looking up the response from a node.
*/
struct RequestAnswer {
Blob ntoken {};
Value::Id vid {};
std::vector<std::shared_ptr<Value>> values {};
std::vector<std::shared_ptr<Node>> nodes4 {};
std::vector<std::shared_ptr<Node>> nodes6 {};
RequestAnswer() {}
RequestAnswer(ParsedMessage&& msg);
};
/**
* Cancel a request. Setting req->cancelled = true is not enough in the case
* a request is "persistent".
*/
void cancelRequest(std::shared_ptr<Request>& req);
void connectivityChanged();
class NetworkEngine final
{
private:
/**
* Called when we receive an error message.
*/
std::function<void(Sp<Request>, DhtProtocolException)> onError;
/**
* @brief when we receive an error message.
*
* @param node (type: std::shared_ptr<Request>) the associated request for
* which we got an error;
*/
std::function<void(std::shared_ptr<Request>, DhtProtocolException)> onError;
/**
* @brief when a new node happens.
*
* Called for every packets received for handling new nodes contacting us.
*
* @param id (type: InfoHash) id of the node.
* @param saddr (type: sockaddr*) sockaddr* pointer containing address ip information.
* @param saddr_len (type: socklen_t) lenght of the sockaddr struct.
* @param confirm (type: int) 1 if the node sent a message, 2 if it sent us a reply.
* @param node: the node
* @param confirm: 1 if the node sent a message, 2 if it sent us a reply.
*/
std::function<void(const std::shared_ptr<Node>&, int)> onNewNode;
std::function<void(const Sp<Node>&, int)> onNewNode;
/**
* @brief when an addres is reported from a distant node.
* Called when an addres is reported from a requested node.
*
* @param id (type: InfoHash) id of the node.
* @param saddr (type: sockaddr*) sockaddr* pointer containing address ip information.
* @param h: id
* @param saddr_len (type: socklen_t) lenght of the sockaddr struct.
*/
std::function<void(const InfoHash&, sockaddr*, socklen_t)> onReportedAddr;
std::function<void(const InfoHash&, const SockAddr&)> onReportedAddr;
/**
* @brief on ping request callback.
* Called on ping reception.
*
* @param node (type: std::shared_ptr<Node>) the requesting node.
* @param node (type: Sp<Node>) the requesting node.
*/
std::function<RequestAnswer(std::shared_ptr<Node>)> onPing {};
std::function<RequestAnswer(Sp<Node>)> onPing {};
/**
* @brief on find node request callback.
* Called on find node request.
*
* @param node (type: std::shared_ptr<Node>) the requesting node.
* @param vhash (type: InfoHash) hash of the value of interest.
* @param node (type: Sp<Node>) the requesting node.
* @param h (type: InfoHash) hash of the value of interest.
* @param want (type: want_t) states if nodes sent in the response are ipv4
* or ipv6.
*/
std::function<RequestAnswer(std::shared_ptr<Node>,
InfoHash&,
want_t)> onFindNode {};
std::function<RequestAnswer(Sp<Node>, const InfoHash&, want_t)> onFindNode {};
/**
* @brief on "get values" request callback.
* Called on "get values" request.
*
* @param node (type: std::shared_ptr<Node>) the requesting node.
* @param vhash (type: InfoHash) hash of the value of interest.
* @param node (type: Sp<Node>) the requesting node.
* @param h (type: InfoHash) hash of the value of interest.
* @param want (type: want_t) states if nodes sent in the response are ipv4
* or ipv6.
*/
std::function<RequestAnswer(std::shared_ptr<Node>,
InfoHash&,
want_t)> onGetValues {};
std::function<RequestAnswer(Sp<Node>, const InfoHash&, want_t, const Query&)> onGetValues {};
/**
* @brief on listen request callback.
* Called on listen request.
*
* @param node (type: std::shared_ptr<Node>) the requesting node.
* @param vhash (type: InfoHash) hash of the value of interest.
* @param node (type: Sp<Node>) the requesting node.
* @param h (type: InfoHash) hash of the value of interest.
* @param token (type: Blob) security token.
* @param rid (type: uint16_t) request id.
*/
std::function<RequestAnswer(std::shared_ptr<Node>,
InfoHash&,
Blob&,
uint16_t)> onListen {};
std::function<RequestAnswer(Sp<Node>, const InfoHash&, const Blob&, Tid, const Query&, int)> onListen {};
/**
* @brief on announce request callback.
* Called on announce request.
*
* @param node (type: std::shared_ptr<Node>) the requesting node.
* @param vhash (type: InfoHash) hash of the value of interest.
* @param node (type: Sp<Node>) the requesting node.
* @param h (type: InfoHash) hash of the value of interest.
* @param token (type: Blob) security token.
* @param values (type: std::vector<std::shared_ptr<Value>>) values to store.
* @param values (type: std::vector<Sp<Value>>) values to store.
* @param created (type: time_point) time when the value was created.
*/
std::function<RequestAnswer(std::shared_ptr<Node>,
InfoHash&,
Blob&,
std::vector<std::shared_ptr<Value>>,
time_point)> onAnnounce {};
std::function<RequestAnswer(Sp<Node>, const InfoHash&, const Blob&, const std::vector<Sp<Value>>&, const time_point&)>
onAnnounce {};
/**
* Called on refresh request.
*
* @param node (type: Sp<Node>) the requesting node.
* @param h (type: InfoHash) hash of the value of interest.
* @param token (type: Blob) security token.
* @param vid (type: Value::id) the value id.
*/
std::function<RequestAnswer(Sp<Node>, const InfoHash&, const Blob&, const Value::Id&)> onRefresh {};
public:
using RequestCb = std::function<void(const Request&, RequestAnswer&&)>;
using RequestErrorCb = std::function<bool(const Request&, DhtProtocolException&&)>;
using RequestExpiredCb = std::function<void(const Request&, bool)>;
NetworkEngine(Logger& log, Scheduler& scheduler) : myid(zeroes), DHT_LOG(log), scheduler(scheduler) {}
NetworkEngine(InfoHash& myid, int s, int s6, Logger& log, Scheduler& scheduler,
decltype(NetworkEngine::onError) onError,
decltype(NetworkEngine::onNewNode) onNewNode,
decltype(NetworkEngine::onReportedAddr) onReportedAddr,
decltype(NetworkEngine::onPing) onPing,
decltype(NetworkEngine::onFindNode) onFindNode,
decltype(NetworkEngine::onGetValues) onGetValues,
decltype(NetworkEngine::onListen) onListen,
decltype(NetworkEngine::onAnnounce) onAnnounce) :
onError(onError), onNewNode(onNewNode), onReportedAddr(onReportedAddr), onPing(onPing), onFindNode(onFindNode),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), myid(myid),
dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{
transaction_id = std::uniform_int_distribution<decltype(transaction_id)>{1}(rd_device);
}
virtual ~NetworkEngine() {
clear();
};
NetworkEngine(InfoHash& myid,
NetworkConfig config,
std::unique_ptr<DatagramSocket>&& sock,
const Sp<Logger>& log,
std::mt19937_64& rd,
Scheduler& scheduler,
decltype(NetworkEngine::onError)&& onError,
decltype(NetworkEngine::onNewNode)&& onNewNode,
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
decltype(NetworkEngine::onPing)&& onPing,
decltype(NetworkEngine::onFindNode)&& onFindNode,
decltype(NetworkEngine::onGetValues)&& onGetValues,
decltype(NetworkEngine::onListen)&& onListen,
decltype(NetworkEngine::onAnnounce)&& onAnnounce,
decltype(NetworkEngine::onRefresh)&& onRefresh);
~NetworkEngine();
net::DatagramSocket* getSocket() const { return dht_socket.get(); };
void clear();
/**
* Sends values (with closest nodes) to a listenner.
* Sends values (with closest nodes) to a listener.
*
* @param sa The address of the listenner.
* @param sslen The length of the sockaddr structure.
* @param rid The request id of the initial listen request.
* @param hash The hash key of the value.
* @param want Wether to send ipv4 and/or ipv6 nodes.
* @param ntoken Listen security token.
* @param nodes The ipv4 closest nodes.
* @param nodes6 The ipv6 closest nodes.
* @param values The values to send.
* @deprecated
* @param sa The address of the listener.
* @param sslen The length of the sockaddr structure.
* @param socket_id The tid to use to write to the request socket.
* @param hash The hash key of the value.
* @param want Wether to send ipv4 and/or ipv6 nodes.
* @param ntoken Listen security token.
* @param nodes The ipv4 closest nodes.
* @param nodes6 The ipv6 closest nodes.
* @param values The values to send.
* @param version If version = 1, a request will be used to answer to the listener
*/
void tellListener(std::shared_ptr<Node> n, uint16_t rid, InfoHash hash, want_t want, Blob ntoken,
std::vector<std::shared_ptr<Node>> nodes, std::vector<std::shared_ptr<Node>> nodes6,
std::vector<std::shared_ptr<Value>> values);
void tellListener(const Sp<Node>& n,
Tid socket_id,
const InfoHash& hash,
want_t want,
const Blob& ntoken,
std::vector<Sp<Node>>&& nodes,
std::vector<Sp<Node>>&& nodes6,
std::vector<Sp<Value>>&& values,
const Query& q,
int version);
void tellListenerRefreshed(const Sp<Node>& n,
Tid socket_id,
const InfoHash& hash,
const Blob& ntoken,
const std::vector<Value::Id>& values,
int version);
void tellListenerExpired(const Sp<Node>& n,
Tid socket_id,
const InfoHash& hash,
const Blob& ntoken,
const std::vector<Value::Id>& values,
int version);
bool isRunning(sa_family_t af) const;
inline want_t want () const { return dht_socket >= 0 && dht_socket6 >= 0 ? (WANT4 | WANT6) : -1; }
inline want_t want() const { return dht_socket->hasIPv4() and dht_socket->hasIPv6() ? (WANT4 | WANT6) : -1; }
void connectivityChanged(sa_family_t);
/**************
* Requests *
**************/
std::shared_ptr<Request>
sendPing(std::shared_ptr<Node> n, RequestCb on_done, RequestExpiredCb on_expired);
std::shared_ptr<Request>
sendPing(const sockaddr* sa, socklen_t salen, RequestCb on_done, RequestExpiredCb on_expired) {
return sendPing(std::make_shared<Node>(zeroes, sa, salen), on_done, on_expired);
}
std::shared_ptr<Request>
sendFindNode(std::shared_ptr<Node> n,
const InfoHash& target,
want_t want,
RequestCb on_done,
RequestExpiredCb on_expired);
std::shared_ptr<Request>
sendGetValues(std::shared_ptr<Node> n,
const InfoHash& target,
want_t want,
RequestCb on_done,
RequestExpiredCb on_expired);
std::shared_ptr<Request>
sendListen(std::shared_ptr<Node> n,
const InfoHash& infohash,
const Blob& token,
RequestCb on_done,
RequestExpiredCb on_expired);
std::shared_ptr<Request>
sendAnnounceValue(std::shared_ptr<Node> n,
const InfoHash& infohash,
const Value& v,
time_point created,
const Blob& token,
RequestCb on_done,
RequestExpiredCb on_expired);
/**
* Send a "ping" request to a given node.
*
* @param n The node.
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendPing(const Sp<Node>& n, RequestCb&& on_done, RequestExpiredCb&& on_expired);
/**
* Send a "ping" request to a given node.
*
* @param sa The node's ip sockaddr info.
* @param salen The associated sockaddr struct length.
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendPing(SockAddr&& sa, RequestCb&& on_done, RequestExpiredCb&& on_expired)
{
return sendPing(std::make_shared<Node>(InfoHash::zero(), std::move(sa), rd),
std::forward<RequestCb>(on_done),
std::forward<RequestExpiredCb>(on_expired));
}
/**
* Send a "find node" request to a given node.
*
* @param n The node.
* @param target The target hash.
* @param want Indicating wether IPv4 or IPv6 are wanted in response.
* Use NetworkEngine::want()
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendFindNode(const Sp<Node>& n,
const InfoHash& hash,
want_t want = -1,
RequestCb&& on_done = {},
RequestExpiredCb&& on_expired = {});
/**
* Send a "get" request to a given node.
*
* @param n The node.
* @param hash The target hash.
* @param query The query describing filters.
* @param token A security token.
* @param want Indicating wether IPv4 or IPv6 are wanted in response.
* Use NetworkEngine::want()
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendGetValues(const Sp<Node>& n,
const InfoHash& hash,
const Query& query,
want_t want,
RequestCb&& on_done,
RequestExpiredCb&& on_expired);
/**
* Send a "listen" request to a given node.
*
* @param n The node.
* @param hash The storage's hash.
* @param query The query describing filters.
* @param token A security token.
* @param previous The previous request "listen" sent to this node.
* @param socket **UNUSED** The socket for further response.
*
* For backward compatibility purposes, sendListen has to
* handle creation of the socket. Therefore, you are unable to
* use openSocket yourself.
* TODO: Once we don't support the old "listen" negotiation,
* sendListen shall not create the socket itself.
*
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
* @param socket_cb Callback to execute each time new updates arrive on
* the socket.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendListen(const Sp<Node>& n,
const InfoHash& hash,
const Query& query,
const Blob& token,
Tid socketId,
RequestCb&& on_done,
RequestExpiredCb&& on_expired);
/**
* Send a "announce" request to a given node.
*
* @param n The node.
* @param hash The target hash.
* @param created The time when the value was created (avoiding extended
* value lifetime)
* @param token A security token.
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendAnnounceValue(const Sp<Node>& n,
const InfoHash& hash,
const Sp<Value>& v,
time_point created,
const Blob& token,
RequestCb&& on_done,
RequestExpiredCb&& on_expired);
/**
* Send a "refresh" request to a given node. Asks a node to keep the
* associated value Value.type.expiration more minutes in its storage.
*
* @param n The node.
* @param hash The target hash.
* @param vid The value id.
* @param token A security token.
* @param on_done Request callback when the request is completed.
* @param on_expired Request callback when the request expires.
*
* @return the request with information concerning its success.
*/
Sp<Request> sendRefreshValue(const Sp<Node>& n,
const InfoHash& hash,
const Value::Id& vid,
const Blob& token,
RequestCb&& on_done,
RequestErrorCb&& on_error,
RequestExpiredCb&& on_expired);
/**
* Send a "update" request to a given node. Used for Listen operations
*
* @param n The node.
* @param hash The target hash.
* @param values The values.
* @param created Time id.
* @param token A security token.
* @param sid The socket id.
*
* @return the request with information concerning its success.
*/
void sendUpdateValues(const Sp<Node>& n,
const InfoHash& infohash,
std::vector<Sp<Value>>&& values,
time_point created,
const Blob& token,
size_t sid);
Sp<Request> sendUpdateValues(const Sp<Node>& n,
const InfoHash& infohash,
std::vector<Sp<Value>>::iterator begin,
std::vector<Sp<Value>>::iterator end,
time_point created,
const Blob& token,
size_t sid);
/**
* Parses a message and calls appropriate callbacks.
@@ -342,126 +434,154 @@ public:
* @param fromlen The length of the corresponding sockaddr structure.
* @param now The time to adjust the clock in the network engine.
*/
void processMessage(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen);
void processMessage(const uint8_t* buf, size_t buflen, SockAddr addr);
std::shared_ptr<Node> insertNode(const InfoHash& myid, const sockaddr* from, socklen_t fromlen) {
return cache.getNode(myid, from, fromlen, scheduler.time(), 0);
Sp<Node> insertNode(const InfoHash& id, const SockAddr& addr)
{
auto n = cache.getNode(id, addr, scheduler.time(), 0);
onNewNode(n, 0);
return n;
}
std::vector<unsigned> getNodeMessageStats(bool in) {
std::vector<unsigned> getNodeMessageStats(bool in)
{
auto& st = in ? in_stats : out_stats;
std::vector<unsigned> stats {st.ping, st.find, st.get, st.listen, st.put};
std::vector<unsigned> stats {st.ping, st.find, st.get, st.listen, st.put};
st = {};
return stats;
}
void blacklistNode(const std::shared_ptr<Node>& n);
void blacklistNode(const Sp<Node>& n);
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count)
{
return cache.getCachedNodes(id, sa_f, count);
}
size_t getNodeCacheSize() const { return cache.size(); }
size_t getNodeCacheSize(sa_family_t af) const { return cache.size(af); }
size_t getRateLimiterSize() const { return address_rate_limiter.size(); }
size_t getPartialCount() const { return partial_messages.size(); }
private:
struct PartialMessage;
/***************
* Constants *
***************/
static constexpr long unsigned MAX_REQUESTS_PER_SEC {1600};
/* the length of a node info buffer in ipv4 format */
static const constexpr size_t NODE4_INFO_BUF_LEN {26};
static const constexpr size_t NODE4_INFO_BUF_LEN {HASH_LEN + sizeof(in_addr) + sizeof(in_port_t)};
/* the length of a node info buffer in ipv6 format */
static const constexpr size_t NODE6_INFO_BUF_LEN {38};
/* TODO */
static const constexpr size_t NODE6_INFO_BUF_LEN {HASH_LEN + sizeof(in6_addr) + sizeof(in_port_t)};
/* after a UDP reply, the period during which we tell the link layer about it */
static constexpr std::chrono::seconds UDP_REPLY_TIME {15};
/* Max. time to receive a full fragmented packet */
static constexpr std::chrono::seconds RX_MAX_PACKET_TIME {10};
/* Max. time between packet fragments */
static constexpr std::chrono::seconds RX_TIMEOUT {3};
/* The maximum number of nodes that we snub. There is probably little
reason to increase this value. */
static constexpr unsigned BLACKLISTED_MAX {10};
/* TODO */
static const std::string my_v;
/* DHT info */
const InfoHash& myid;
const int dht_socket {-1};
const int dht_socket6 {-1};
const Logger& DHT_LOG;
static constexpr size_t MTU {1280};
static constexpr size_t MAX_PACKET_VALUE_SIZE {600};
static constexpr size_t MAX_MESSAGE_VALUE_SIZE {56 * 1024};
NodeCache cache {};
sockaddr_storage blacklist[BLACKLISTED_MAX] {};
unsigned next_blacklisted = 0;
void process(std::unique_ptr<ParsedMessage>&&, const SockAddr& from);
bool rateLimit();
bool rateLimit(const SockAddr& addr);
static bool isMartian(const sockaddr* sa, socklen_t len);
bool isNodeBlacklisted(const sockaddr*, socklen_t) const;
static bool isMartian(const SockAddr& addr);
bool isNodeBlacklisted(const SockAddr& addr) const;
void requestStep(std::shared_ptr<Request> req);
void requestStep(Sp<Request> req);
/**
* Sends a request to a node. Request::MAX_ATTEMPT_COUNT attempts will
* be made before the request expires.
*/
void sendRequest(std::shared_ptr<Request>& request);
void sendRequest(const Sp<Request>& request);
/**
* Generates a new request id, skipping the invalid id.
*
* @return the new id.
*/
uint16_t getNewTid() {
++transaction_id;
return transaction_id == TransId::INVALID ? ++transaction_id : transaction_id;
}
struct MessageStats {
struct MessageStats
{
unsigned ping {0};
unsigned find {0};
unsigned get {0};
unsigned put {0};
unsigned listen {0};
unsigned refresh {0};
unsigned updateValue {0};
};
// basic wrapper for socket sendto function
int send(const char *buf, size_t len, int flags, const sockaddr *sa, socklen_t salen);
int send(const SockAddr& addr, const char* buf, size_t len, bool confirmed = false);
void sendValueParts(Tid tid, const std::vector<Blob>& svals, const SockAddr& addr);
std::vector<Blob> packValueHeader(msgpack::sbuffer&,
std::vector<Sp<Value>>::const_iterator,
std::vector<Sp<Value>>::const_iterator) const;
std::vector<Blob> packValueHeader(msgpack::sbuffer& buf, const std::vector<Sp<Value>>& values) const
{
return packValueHeader(buf, values.begin(), values.end());
}
void maintainRxBuffer(Tid tid);
/*************
* Answers *
*************/
/* answer to a ping request */
void sendPong(const sockaddr* sa, socklen_t salen, TransId tid);
void sendPong(const SockAddr& addr, Tid tid);
/* answer to findnodes/getvalues request */
void sendNodesValues(const sockaddr* sa,
socklen_t salen,
TransId tid,
const Blob& nodes,
const Blob& nodes6,
const std::vector<std::shared_ptr<Value>>& st,
const Blob& token);
Blob bufferNodes(sa_family_t af, const InfoHash& id, std::vector<std::shared_ptr<Node>>& nodes);
void sendNodesValues(const SockAddr& addr,
Tid tid,
const Blob& nodes,
const Blob& nodes6,
const std::vector<Sp<Value>>& st,
const Query& query,
const Blob& token);
Blob bufferNodes(sa_family_t af, const InfoHash& id, std::vector<Sp<Node>>& nodes);
std::pair<Blob, Blob> bufferNodes(sa_family_t af,
const InfoHash& id,
want_t want,
std::vector<std::shared_ptr<Node>>& nodes,
std::vector<std::shared_ptr<Node>>& nodes6);
std::pair<Blob, Blob> bufferNodes(
sa_family_t af, const InfoHash& id, want_t want, std::vector<Sp<Node>>& nodes, std::vector<Sp<Node>>& nodes6);
/* answer to a listen request */
void sendListenConfirmation(const sockaddr* sa, socklen_t salen, TransId tid);
void sendListenConfirmation(const SockAddr& addr, Tid tid, const Blob& token = {});
/* answer to put request */
void sendValueAnnounced(const sockaddr* sa, socklen_t salen, TransId, Value::Id);
void sendValueAnnounced(const SockAddr& addr, Tid, Value::Id);
/* answer in case of error */
void sendError(const sockaddr* sa,
socklen_t salen,
TransId tid,
uint16_t code,
const std::string& message,
bool include_id=false);
void sendError(const SockAddr& addr, Tid tid, uint16_t code, const std::string& message, bool include_id = false);
void deserializeNodesValues(ParsedMessage& msg);
void deserializeNodes(ParsedMessage& msg, const SockAddr& from);
std::queue<time_point> rate_limit_time {};
static std::mt19937 rd_device;
/* DHT info */
const InfoHash& myid;
const NetworkConfig config {};
const std::unique_ptr<DatagramSocket> dht_socket;
Sp<Logger> logger_;
std::mt19937_64& rd;
NodeCache cache;
// global limiting should be triggered by at least 8 different IPs
using IpLimiter = RateLimiter;
using IpLimiterMap = std::map<SockAddr, IpLimiter, SockAddr::ipCmp>;
IpLimiterMap address_rate_limiter;
RateLimiter rate_limiter;
ssize_t limiter_maintenance {0};
// requests handling
uint16_t transaction_id {1};
std::map<uint16_t, std::shared_ptr<Request>> requests {};
std::map<Tid, Sp<Request>> requests {};
std::map<Tid, PartialMessage> partial_messages;
MessageStats in_stats {}, out_stats {};
std::set<SockAddr> blacklist {};
Scheduler& scheduler;
bool logIncoming_ {false};
};
}
} /* namespace net */
} /* namespace dht */
+161
View File
@@ -0,0 +1,161 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include "sockaddr.h"
#include "utils.h"
#include "logger.h"
#ifdef _WIN32
#include <ws2tcpip.h>
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#include <functional>
#include <thread>
#include <atomic>
#include <mutex>
#include <list>
namespace dht {
namespace net {
static const constexpr in_port_t DHT_DEFAULT_PORT = 4222;
static const constexpr size_t RX_QUEUE_MAX_SIZE = 1024 * 64;
static const constexpr std::chrono::milliseconds RX_QUEUE_MAX_DELAY(650);
int bindSocket(const SockAddr& addr, SockAddr& bound);
bool setNonblocking(int fd, bool nonblocking = true);
#ifdef _WIN32
void udpPipe(int fds[2]);
#endif
struct ReceivedPacket
{
Blob data;
SockAddr from;
time_point received;
};
using PacketList = std::list<ReceivedPacket>;
class OPENDHT_PUBLIC DatagramSocket
{
public:
/** A function that takes a list of new received packets and
* optionally returns consumed packets for recycling.
**/
using OnReceive = std::function<PacketList(PacketList&& packets)>;
virtual ~DatagramSocket() {};
virtual int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) = 0;
inline void setOnReceive(OnReceive&& cb)
{
std::lock_guard<std::mutex> lk(lock);
rx_callback = std::move(cb);
}
virtual bool hasIPv4() const = 0;
virtual bool hasIPv6() const = 0;
SockAddr getBound(sa_family_t family = AF_UNSPEC) const
{
std::lock_guard<std::mutex> lk(lock);
return getBoundRef(family);
}
in_port_t getPort(sa_family_t family = AF_UNSPEC) const
{
std::lock_guard<std::mutex> lk(lock);
return getBoundRef(family).getPort();
}
virtual const SockAddr& getBoundRef(sa_family_t family = AF_UNSPEC) const = 0;
/** Virtual resolver mothod allows to implement custom resolver */
virtual std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {})
{
return SockAddr::resolve(host, service);
}
virtual void stop() = 0;
protected:
PacketList getNewPacket()
{
PacketList pkts;
if (toRecycle_.empty()) {
pkts.emplace_back();
} else {
auto begIt = toRecycle_.begin();
auto begItNext = std::next(begIt);
pkts.splice(pkts.end(), toRecycle_, begIt, begItNext);
}
return pkts;
}
inline void onReceived(PacketList&& packets)
{
std::lock_guard<std::mutex> lk(lock);
if (rx_callback) {
auto r = rx_callback(std::move(packets));
if (not r.empty() and toRecycle_.size() < RX_QUEUE_MAX_SIZE)
toRecycle_.splice(toRecycle_.end(), std::move(r));
}
}
protected:
mutable std::mutex lock;
private:
OnReceive rx_callback;
PacketList toRecycle_;
};
class OPENDHT_PUBLIC UdpSocket : public DatagramSocket
{
public:
UdpSocket(in_port_t port, const std::shared_ptr<Logger>& l = {});
UdpSocket(const SockAddr& bind4, const SockAddr& bind6, const std::shared_ptr<Logger>& l = {});
~UdpSocket();
int sendTo(const SockAddr& dest, const uint8_t* data, size_t size, bool replied) override;
const SockAddr& getBoundRef(sa_family_t family = AF_UNSPEC) const override
{
return (family == AF_INET6) ? bound6 : bound4;
}
bool hasIPv4() const override
{
std::lock_guard<std::mutex> lk(lock);
return s4 != -1;
}
bool hasIPv6() const override
{
std::lock_guard<std::mutex> lk(lock);
return s6 != -1;
}
void stop() override;
private:
std::shared_ptr<Logger> logger;
int s4 {-1};
int s6 {-1};
int stopfd {-1};
SockAddr bound4, bound6;
std::thread rcv_thread {};
std::atomic_bool running {false};
void openSockets(const SockAddr& bind4, const SockAddr& bind6);
};
} // namespace net
} // namespace dht
+113 -56
View File
@@ -1,83 +1,136 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "infohash.h" // includes socket structures
#include "utils.h"
#include "sockaddr.h"
#include "node_export.h"
#include <list>
#include <map>
namespace dht {
struct Node;
namespace net {
struct Request;
struct Socket;
struct RequestAnswer;
} /* namespace net */
struct Node {
friend class NetworkEngine;
using Tid = uint32_t;
using SocketCb = std::function<void(const Sp<Node>&, net::RequestAnswer&&)>;
struct Socket
{
Socket() {}
Socket(SocketCb&& on_receive)
: on_receive(std::move(on_receive))
{}
SocketCb on_receive {};
};
InfoHash id;
struct Node
{
const InfoHash id;
socklen_t sslen {0};
sockaddr_storage ss;
Node(const InfoHash& id, const SockAddr& addr, std::mt19937_64& rd, bool client = false);
Node(const InfoHash& id, SockAddr&& addr, std::mt19937_64& rd, bool client = false);
Node(const InfoHash& id, const sockaddr* sa, socklen_t salen, std::mt19937_64& rd)
: Node(id, SockAddr(sa, salen), rd)
{}
time_point time {time_point::min()}; /* last time eared about */
time_point reply_time {time_point::min()}; /* time of last correct reply received */
const InfoHash& getId() const { return id; }
const SockAddr& getAddr() const { return addr; }
std::string getAddrStr() const { return addr.toString(); }
bool isClient() const { return is_client; }
bool isIncoming() { return time > reply_time; }
Node(const InfoHash& id, const sockaddr* sa, socklen_t salen)
: id(id), sslen(salen), ss() {
std::copy_n((const uint8_t*)sa, salen, (uint8_t*)&ss);
if ((unsigned)salen < sizeof(ss))
std::fill_n((uint8_t*)&ss+salen, sizeof(ss)-salen, 0);
}
InfoHash getId() const {
return id;
}
std::pair<const sockaddr*, socklen_t> getAddr() const {
return {(const sockaddr*)&ss, sslen};
}
std::string getAddrStr() const {
return print_addr(ss, sslen);
const time_point& getTime() const { return time; }
const time_point& getReplyTime() const { return reply_time; }
void setTime(const time_point& t) { time = t; }
/**
* Makes notice about an additionnal authentication error with this node. Up
* to MAX_AUTH_ERRORS errors are accepted in order to let the node recover.
* Upon this limit, the node expires.
*/
void authError()
{
if (++auth_errors > MAX_AUTH_ERRORS)
setExpired();
}
void authSuccess() { auth_errors = 0; }
bool isExpired() const { return expired_; }
bool isGood(time_point now) const;
bool isPendingMessage() const;
size_t getPendingMessageCount() const;
NodeExport exportNode() const { return NodeExport {id, ss, sslen}; }
sa_family_t getFamily() const { return ss.ss_family; }
bool isOld(const time_point& now) const { return time + NODE_EXPIRE_TIME < now; }
bool isRemovable(const time_point& now) const { return isExpired() and isOld(now); }
void update(const sockaddr* sa, socklen_t salen);
NodeExport exportNode() const
{
NodeExport ne;
ne.id = id;
ne.addr = addr;
return ne;
}
sa_family_t getFamily() const { return addr.getFamily(); }
void requested(std::shared_ptr<Request>& req);
void received(time_point now, std::shared_ptr<Request> req);
void update(const SockAddr&);
void requested(const Sp<net::Request>& req);
void received(time_point now, const Sp<net::Request>& req);
Sp<net::Request> getRequest(Tid tid);
void cancelRequest(const Sp<net::Request>& req);
void setExpired();
/**
* Opens a socket on which a node will be able allowed to write for further
* additionnal updates following the response to a previous request.
*
* @param node The node which will be allowed to write on this socket.
* @param cb The callback to execute once updates arrive on the socket.
*
* @return the socket.
*/
Tid openSocket(SocketCb&& cb);
Sp<Socket> getSocket(Tid id);
/**
* Closes a socket so that no further data will be red on that socket.
*
* @param socket The socket to close.
*/
void closeSocket(Tid id);
/**
* Resets the state of the node so it's not expired anymore.
*/
void reset() { expired_ = false; }
void reset()
{
expired_ = false;
reply_time = time_point::min();
}
/**
* Generates a new request id, skipping the invalid id.
*
* @return the new id.
*/
Tid getNewTid()
{
++transaction_id;
return transaction_id ? transaction_id : ++transaction_id;
}
std::string toString() const;
friend std::ostream& operator<< (std::ostream& s, const Node& h);
OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const Node& h);
static constexpr const std::chrono::minutes NODE_GOOD_TIME {120};
@@ -88,16 +141,20 @@ struct Node {
static constexpr const std::chrono::seconds MAX_RESPONSE_TIME {1};
private:
/* Number of times we accept authentication errors from this node. */
static const constexpr unsigned MAX_AUTH_ERRORS {3};
std::list<std::weak_ptr<Request>> requests_ {};
SockAddr addr;
bool is_client {false};
time_point time {time_point::min()}; /* last time eared about */
time_point reply_time {time_point::min()}; /* time of last correct reply received */
unsigned auth_errors {0};
bool expired_ {false};
Tid transaction_id;
using TransactionDist = std::uniform_int_distribution<decltype(transaction_id)>;
void clearPendingQueue() {
requests_.remove_if([](std::weak_ptr<Request>& w) {
return w.expired();
});
}
std::map<Tid, Sp<net::Request>> requests_ {};
std::map<Tid, Sp<Socket>> sockets_;
};
}
} // namespace dht
+30 -26
View File
@@ -1,22 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "node.h"
@@ -26,9 +9,14 @@
namespace dht {
struct NodeCache {
std::shared_ptr<Node> getNode(const InfoHash& id, sa_family_t family);
std::shared_ptr<Node> getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed);
struct NodeCache
{
size_t size(sa_family_t family) const { return cache(family).count(); }
size_t size() const { return size(AF_INET) + size(AF_INET6); }
Sp<Node> getNode(const InfoHash& id, sa_family_t family);
Sp<Node> getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client = false);
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) const;
/**
* Reset the connectivity state of every node,
@@ -37,16 +25,32 @@ struct NodeCache {
*/
void clearBadNodes(sa_family_t family = 0);
NodeCache(std::mt19937_64& r)
: rd(r) {};
~NodeCache();
private:
class NodeMap : public std::map<InfoHash, std::weak_ptr<Node>> {
class NodeMap : private std::map<InfoHash, std::weak_ptr<Node>>
{
public:
std::shared_ptr<Node> getNode(const InfoHash& id);
std::shared_ptr<Node> getNode(const InfoHash& id, const sockaddr* sa, socklen_t sa_len, time_point now, int confirmed);
Sp<Node> getNode(const InfoHash& id);
Sp<Node> getNode(
const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client, std::mt19937_64& rd);
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, size_t count) const;
void clearBadNodes();
void setExpired();
void cleanup();
size_t count() const { return size(); }
private:
size_t cleanup_counter {0};
};
const NodeMap& cache(sa_family_t af) const { return af == AF_INET ? cache_4 : cache_6; }
NodeMap& cache(sa_family_t af) { return af == AF_INET ? cache_4 : cache_6; }
NodeMap cache_4;
NodeMap cache_6;
std::mt19937_64& rd;
};
}
} // namespace dht
+35
View File
@@ -0,0 +1,35 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include "infohash.h"
#include "sockaddr.h"
#include <string_view>
namespace dht {
using namespace std::literals;
struct OPENDHT_PUBLIC NodeExport
{
InfoHash id;
SockAddr addr;
template<typename Packer>
void msgpack_pack(Packer& pk) const
{
pk.pack_map(2);
pk.pack("id"sv);
pk.pack(id);
pk.pack("addr"sv);
pk.pack_bin(addr.getLength());
pk.pack_bin_body((const char*) addr.get(), (size_t) addr.getLength());
}
void msgpack_unpack(msgpack::object o);
OPENDHT_PUBLIC friend std::ostream& operator<<(std::ostream& s, const NodeExport& h);
};
} // namespace dht
+85
View File
@@ -0,0 +1,85 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include "sockaddr.h"
#include "infohash.h"
#include "logger.h"
#include "utils.h"
#include <asio/steady_timer.hpp>
#include <thread>
namespace asio {
class io_context;
}
namespace dht {
class OPENDHT_PUBLIC PeerDiscovery
{
public:
static constexpr in_port_t DEFAULT_PORT = 8888;
using ServiceDiscoveredCallback = std::function<void(msgpack::object&&, SockAddr&&)>;
PeerDiscovery(in_port_t port = DEFAULT_PORT,
std::shared_ptr<asio::io_context> ioContext = {},
std::shared_ptr<Logger> logger = {});
~PeerDiscovery();
/**
* startDiscovery - Keep Listening data from the sender until node is joinned
* or stop is called
*/
void startDiscovery(std::string_view type, ServiceDiscoveredCallback callback);
template<typename T>
void startDiscovery(std::string_view type, std::function<void(T&&, SockAddr&&)> cb)
{
startDiscovery(type, [cb](msgpack::object&& ob, SockAddr&& addr) { cb(ob.as<T>(), std::move(addr)); });
}
/**
* startPublish - Keeping sending data until node is joinned or stop is called
*/
void startPublish(std::string_view type, const msgpack::sbuffer& pack_buf);
void startPublish(sa_family_t domain, std::string_view type, const msgpack::sbuffer& pack_buf);
template<typename T>
void startPublish(std::string_view type, const T& object)
{
msgpack::sbuffer buf;
msgpack::pack(buf, object);
startPublish(type, buf);
}
/**
* Thread Stopper
*/
void stop();
/**
* Remove possible callBack to discovery
*/
bool stopDiscovery(std::string_view type);
/**
* Remove different serivce message to send
*/
bool stopPublish(std::string_view type);
bool stopPublish(sa_family_t domain, std::string_view type);
void connectivityChanged();
void stopConnectivityChanged();
private:
class DomainPeerDiscovery;
std::unique_ptr<DomainPeerDiscovery> peerDiscovery4_;
std::unique_ptr<DomainPeerDiscovery> peerDiscovery6_;
std::shared_ptr<asio::io_context> ioContext_;
std::thread ioRunnner_;
};
} // namespace dht
+16
View File
@@ -0,0 +1,16 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include <chrono>
namespace dht {
namespace proxy {
constexpr const std::chrono::hours OP_TIMEOUT {24}; // one day
constexpr const std::chrono::hours OP_MARGIN {2}; // two hours
using ListenToken = uint64_t;
} // namespace proxy
} // namespace dht
+44
View File
@@ -0,0 +1,44 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "utils.h"
#include <queue>
namespace dht {
class RateLimiter
{
public:
RateLimiter(size_t quota, const duration& period = std::chrono::seconds(1))
: quota_(quota)
, period_(period)
{}
/** Clear outdated records and return current quota usage */
size_t maintain(const time_point& now)
{
auto limit = now - period_;
while (not records.empty() and records.front() < limit)
records.pop();
return records.size();
}
/** Return false if quota is reached, insert record and return true otherwise. */
bool limit(const time_point& now)
{
if (quota_ == std::numeric_limits<size_t>::max())
return true;
if (maintain(now) >= quota_)
return false;
records.emplace(now);
return true;
}
bool empty() const { return records.empty(); }
private:
const size_t quota_;
const duration period_;
std::queue<time_point> records {};
};
} // namespace dht
-113
View File
@@ -1,113 +0,0 @@
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
namespace dht {
class NetworkEngine;
struct ParsedMessage;
/*!
* @class Request
* @brief An atomic request destined to a node.
* @details
* A request contains data used by the NetworkEngine to process a request
* desitned to specific node and std::function callbacks to execute when the
* request is done.
*/
struct Request {
friend class dht::NetworkEngine;
std::shared_ptr<Node> node {}; /* the node to whom the request is destined. */
time_point reply_time {time_point::min()}; /* time when we received the response to the request. */
enum class State
{
PENDING,
CANCELLED,
EXPIRED,
COMPLETED
};
bool expired() const { return state_ == State::EXPIRED; }
bool completed() const { return state_ == State::COMPLETED; }
bool cancelled() const { return state_ == State::CANCELLED; }
bool pending() const { return state_ == State::PENDING; }
bool over() const { return not pending(); }
State getState() const { return state_; }
Request() {}
Request(uint16_t tid,
std::shared_ptr<Node> node,
Blob&& msg,
std::function<void(const Request& req_status, ParsedMessage&&)> on_done,
std::function<void(const Request& req_status, bool)> on_expired,
bool persistent = false) :
node(node), on_done(on_done), on_expired(on_expired), tid(tid), msg(std::move(msg)), persistent(persistent) { }
void setExpired() {
if (pending()) {
state_ = Request::State::EXPIRED;
on_expired(*this, true);
clear();
}
}
void setDone(ParsedMessage&& msg) {
if (pending() or persistent) {
state_ = Request::State::COMPLETED;
on_done(*this, std::forward<ParsedMessage>(msg));
if (not persistent)
clear();
}
}
void cancel() {
if (pending()) {
state_ = State::CANCELLED;
clear();
}
}
private:
static const constexpr size_t MAX_ATTEMPT_COUNT {3};
bool isExpired(time_point now) const {
return pending() and now > last_try + Node::MAX_RESPONSE_TIME and attempt_count >= Request::MAX_ATTEMPT_COUNT;
}
void clear() {
on_done = {};
on_expired = {};
msg.clear();
}
State state_ {State::PENDING};
unsigned attempt_count {0}; /* number of attempt to process the request. */
time_point start {time_point::min()}; /* time when the request is created. */
time_point last_try {time_point::min()}; /* time of the last attempt to process the request. */
std::function<void(const Request& req_status, ParsedMessage&&)> on_done {};
std::function<void(const Request& req_status, bool)> on_expired {};
const uint16_t tid {0}; /* the request id. */
Blob msg {}; /* the serialized message. */
const bool persistent {false}; /* the request is not erased upon completion. */
};
}
+51 -99
View File
@@ -1,110 +1,62 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include <random>
#include <algorithm>
#include <functional>
#include <thread>
#include <stdexcept>
namespace dht {
namespace crypto {
#ifndef WIN32_NATIVE
#ifdef _WIN32
/**
* Generate a seeded random engine.
*/
template<class T = std::mt19937, std::size_t N = T::state_size + 1>
auto
getSeededRandomEngine() -> typename std::enable_if<!!N, T>::type
{
std::array<typename T::result_type, N> random_data;
constexpr auto gen = [](std::random_device& source) -> typename T::result_type {
for (unsigned j = 0; j < 64; j++) {
try {
return source();
} catch (...) {
std::this_thread::sleep_for(std::chrono::microseconds(500));
}
}
throw std::runtime_error("Can't generate random number");
};
for (unsigned i = 0; i < 8; i++) {
try {
std::random_device source;
for (auto& r : random_data)
r = gen(source);
std::seed_seq seed((std::seed_seq::result_type*) random_data.data(),
(std::seed_seq::result_type*) (random_data.data() + random_data.size()));
return T(seed);
} catch (...) {
std::this_thread::sleep_for(std::chrono::microseconds(500));
}
}
throw std::runtime_error("Can't seed random seed");
}
/**
* Hardware random number generator using Intel RDRAND/RDSEED,
* API-compatible with std::random_device.
* Generate a random engine from another source.
*/
class random_device {
public:
using result_type = std::random_device::result_type;
using pseudo_engine = std::mt19937_64;
template<class T = std::mt19937, std::size_t N = T::state_size + 1>
auto
getDerivedRandomEngine(T& source) -> typename std::enable_if<!!N, T>::type
{
std::array<typename T::result_type, N> random_data;
std::generate(random_data.begin(), random_data.end(), std::ref(source));
std::seed_seq seed((std::seed_seq::result_type*) random_data.data(),
(std::seed_seq::result_type*) (random_data.data() + random_data.size()));
return T(seed);
}
/**
* Current implementation assumption : result_type must be of a size
* supported by Intel RDRAND/RDSEED.
* result_type is unsigned int so this is currently safe.
*/
static_assert(
sizeof(result_type) == 2 ||
sizeof(result_type) == 4 ||
sizeof(result_type) == 8,
"result_type must be 16, 32 or 64 bits");
random_device();
result_type operator()();
static constexpr result_type min() {
return std::numeric_limits<result_type>::lowest();
}
static constexpr result_type max() {
return std::numeric_limits<result_type>::max();
}
double entropy() const {
if (hasRdrand() or hasRdseed())
return 1.;
return 0.;
}
static bool hasRdrand() {
static const bool hasrdrand = _hasRdrand();
return hasrdrand;
}
static bool hasRdseed() {
static const bool hasrdseed = _hasRdseed();
return hasrdseed;
}
private:
random_device& operator=(random_device&) = delete;
pseudo_engine gen;
std::uniform_int_distribution<result_type> dis {};
static bool hasIntelCpu();
static bool _hasRdrand();
static bool _hasRdseed();
struct CPUIDinfo {
unsigned int EAX;
unsigned int EBX;
unsigned int ECX;
unsigned int EDX;
CPUIDinfo(const unsigned int func, const unsigned int subfunc);
};
bool rdrandStep(result_type* r);
bool rdrand(result_type* r);
bool rdseedStep(result_type* r);
bool rdseed(result_type* r);
};
#else
using random_device = std::random_device;
#endif
#else
using random_device = std::random_device;
#endif
}} // dht::crypto
} // namespace crypto
} // namespace dht
+50 -34
View File
@@ -1,49 +1,56 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "node.h"
namespace dht {
struct Bucket {
Bucket() : cached() {}
static constexpr unsigned TARGET_NODES {8};
namespace net {
class NetworkEngine;
}
struct Bucket
{
Bucket()
: cached()
{}
Bucket(sa_family_t af, const InfoHash& f = {}, time_point t = time_point::min())
: af(af), first(f), time(t), cached() {}
: af(af)
, first(f)
, time(t)
, cached()
{}
sa_family_t af {0};
InfoHash first {};
time_point time {time_point::min()}; /* time of last reply in this bucket */
std::list<std::shared_ptr<Node>> nodes {};
std::shared_ptr<Node> cached; /* the address of a likely candidate */
time_point time {time_point::min()}; /* time of last reply in this bucket */
std::list<Sp<Node>> nodes {};
Sp<Node> cached; /* the address of a likely candidate */
/** Return a random node in a bucket. */
std::shared_ptr<Node> randomNode();
Sp<Node> randomNode(std::mt19937_64& rd);
void sendCachedPing(net::NetworkEngine& ne);
void connectivityChanged()
{
time = time_point::min();
for (auto& node : nodes)
node->setTime(time_point::min());
}
};
class RoutingTable : public std::list<Bucket> {
class RoutingTable : public std::list<Bucket>
{
public:
using std::list<Bucket>::list;
time_point grow_time {time_point::min()};
bool is_client {false};
InfoHash middle(const RoutingTable::const_iterator&) const;
std::vector<std::shared_ptr<Node>> findClosestNodes(const InfoHash id, time_point now, size_t count = TARGET_NODES) const;
std::vector<Sp<Node>> findClosestNodes(const InfoHash id, time_point now, size_t count = TARGET_NODES) const;
RoutingTable::iterator findBucket(const InfoHash& id);
RoutingTable::const_iterator findBucket(const InfoHash& id) const;
@@ -51,22 +58,31 @@ public:
/**
* Return true if the id is in the bucket's range.
*/
inline bool contains(const RoutingTable::const_iterator& bucket, const InfoHash& id) const {
inline bool contains(const RoutingTable::const_iterator& bucket, const InfoHash& id) const
{
return InfoHash::cmp(bucket->first, id) <= 0
&& (std::next(bucket) == end() || InfoHash::cmp(id, std::next(bucket)->first) < 0);
&& (std::next(bucket) == end() || InfoHash::cmp(id, std::next(bucket)->first) < 0);
}
/**
* Return true if the table has no bucket ore one empty buket.
*/
inline bool isEmpty() const {
return empty() || (size() == 1 && front().nodes.empty());
inline bool isEmpty() const { return empty() || (size() == 1 && front().nodes.empty()); }
void connectivityChanged(const time_point& now)
{
grow_time = now;
for (auto& b : *this)
b.connectivityChanged();
}
bool onNewNode(
const Sp<Node>& node, int comfirm, const time_point& now, const InfoHash& myid, net::NetworkEngine& ne);
/**
* Return a random id in the bucket's range.
*/
InfoHash randomId(const RoutingTable::const_iterator& bucket) const;
InfoHash randomId(const RoutingTable::const_iterator& bucket, std::mt19937_64& rd) const;
unsigned depth(const RoutingTable::const_iterator& bucket) const;
@@ -76,4 +92,4 @@ public:
bool split(const RoutingTable::iterator& b);
};
}
} // namespace dht
+48 -45
View File
@@ -1,24 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <sim.desaulniers@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "utils.h"
@@ -34,11 +15,18 @@ namespace dht {
* @details
* Maintains the timings upon which to execute a job.
*/
class Scheduler {
class Scheduler
{
public:
struct Job {
Job(std::function<void()>&& f) : do_(std::forward<std::function<void()>>(f)) {}
struct Job
{
Job(std::function<void()>&& f, time_point t)
: do_(std::move(f))
, t_(t)
{}
std::function<void()> do_;
const time_point t_;
void cancel() { do_ = {}; }
};
/**
@@ -49,8 +37,9 @@ public:
*
* @return pointer to the newly scheduled job.
*/
std::shared_ptr<Scheduler::Job> add(time_point t, std::function<void()>&& job_func) {
auto job = std::make_shared<Job>(std::forward<std::function<void()>>(job_func));
Sp<Scheduler::Job> add(time_point t, std::function<void()>&& job_func)
{
auto job = std::make_shared<Job>(std::move(job_func), t);
if (t != time_point::max())
timers.emplace(std::move(t), job);
return job;
@@ -59,17 +48,33 @@ public:
/**
* Reschedules a job.
*
* @param time The time at which the job shall be rescheduled.
* @param job The job to edit.
*
* @return pointer to the newly scheduled job.
* @param t The time at which the job shall be rescheduled.
*/
void edit(std::shared_ptr<Scheduler::Job>& job, time_point t) {
if (not job) {
std::cerr << "editing an empty job" << std::endl;
void edit(Sp<Scheduler::Job>& job, time_point t)
{
if (not job)
return;
// std::function move doesn't garantee to leave the object empty.
// Force clearing old value.
auto task = std::move(job->do_);
cancel(job);
job = add(t, std::move(task));
}
bool cancel(Sp<Scheduler::Job>& job)
{
if (job) {
job->cancel();
for (auto r = timers.equal_range(job->t_); r.first != r.second; ++r.first) {
if (r.first->second == job) {
timers.erase(r.first);
job.reset();
return true;
}
}
}
job = add(t, std::move(job->do_));
return false;
}
/**
@@ -77,8 +82,8 @@ public:
*
* @return The time for the next job to run.
*/
time_point run() {
syncTime();
time_point run()
{
while (not timers.empty()) {
auto timer = timers.begin();
/*
@@ -89,19 +94,16 @@ public:
if (timer->first > now)
break;
const auto& job = *timer->second;
if (job.do_)
job.do_();
auto job = std::move(timer->second);
timers.erase(timer);
if (job->do_)
job->do_();
}
return getNextJobTime();
}
inline time_point getNextJobTime() const {
//if (not timers.empty())
// std::cout << "Next job in " << print_dt(timers.begin()->first - clock::now()) << std::endl;
return timers.empty() ? time_point::max() : timers.begin()->first;
}
inline time_point getNextJobTime() const { return timers.empty() ? time_point::max() : timers.begin()->first; }
/**
* Accessors for the common time reference used for synchronizing
@@ -109,10 +111,11 @@ public:
*/
inline const time_point& time() const { return now; }
inline time_point syncTime() { return (now = clock::now()); }
inline void syncTime(const time_point& n) { now = n; }
private:
time_point now {clock::now()};
std::multimap<time_point, std::shared_ptr<Job>> timers {}; /* the jobs ordered by time */
std::multimap<time_point, Sp<Job>> timers {}; /* the jobs ordered by time */
};
}
} // namespace dht
+291 -91
View File
@@ -1,33 +1,5 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "dht.h"
@@ -40,14 +12,20 @@
namespace dht {
class SecureDht : public Dht {
class OPENDHT_PUBLIC SecureDht final : public DhtInterface
{
public:
typedef std::function<void(bool)> SignatureCheckCallback;
using Config = SecureDhtConfig;
SecureDht() {}
static dht::Config getConfig(const SecureDht::Config& conf)
{
auto c = conf.node_config;
if (not c.node_id and conf.id.second)
c.node_id = InfoHash::get("node:" + conf.id.second->getId().toString());
return c;
}
/**
* s, s6: bound socket descriptors for IPv4 and IPv6, respectively.
@@ -55,54 +33,78 @@ public:
* id: the identity to use for the crypto layer and to compute
* our own hash on the Dht.
*/
SecureDht(int s, int s6, Config config);
SecureDht(std::unique_ptr<DhtInterface> dht,
Config config,
IdentityAnnouncedCb iacb = {},
const std::shared_ptr<Logger>& l = {});
virtual ~SecureDht();
InfoHash getId() const {
return key_ ? key_->getPublicKey().getId() : InfoHash();
}
InfoHash getId() const { return key_ ? key_->getPublicKey().getId() : InfoHash(); }
PkId getLongId() const { return key_ ? key_->getPublicKey().getLongId() : PkId(); }
Sp<crypto::PublicKey> getPublicKey() const { return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey> {}; }
ValueType secureType(ValueType&& type);
ValueType secureType(const ValueType& type) {
ValueType secureType(const ValueType& type)
{
ValueType tmp_type = type;
return secureType(std::move(tmp_type));
}
virtual void registerType(const ValueType& type) {
Dht::registerType(secureType(type));
void registerType(const ValueType& type) override
{
if (dht_)
dht_->registerType(secureType(type));
}
virtual void registerType(ValueType&& type) {
Dht::registerType(secureType(std::forward<ValueType>(type)));
void registerType(ValueType&& type)
{
if (dht_)
dht_->registerType(secureType(std::forward<ValueType>(type)));
}
virtual void registerInsecureType(const ValueType& type) {
Dht::registerType(type);
void registerInsecureType(const ValueType& type)
{
if (dht_)
dht_->registerType(type);
}
/**
* "Secure" get(), that will check the signature of signed data, and decrypt encrypted data.
* If the signature can't be checked, or if the data can't be decrypted, it is not returned.
* If the signature is unable to be checked, or if the data is unable to be decrypted, it is not returned.
* Public, non-signed & non-encrypted data is retransmitted as-is.
*/
virtual void get(const InfoHash& id, GetCallback cb, DoneCallback donecb={}, Value::Filter&& = {}) override;
virtual void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}) override {
get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f));
void get(const InfoHash& id, GetCallback cb, DoneCallback donecb = {}, Value::Filter&& = {}, Where&& w = {}) override;
void get(const InfoHash& id,
GetCallback cb,
DoneCallbackSimple donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}) override {
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f));
void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallback donecb = {},
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}) override {
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f));
void get(const InfoHash& key,
GetCallbackSimple cb,
DoneCallbackSimple donecb,
Value::Filter&& f = {},
Where&& w = {}) override
{
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
virtual size_t listen(const InfoHash& id, GetCallback cb, Value::Filter&& = {}) override;
/**
* Will take ownership of the value, sign it using our private key and put it in the DHT.
*/
void putSigned(const InfoHash& hash, std::shared_ptr<Value> val, DoneCallback callback, bool permanent = false);
void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false) {
void putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback, bool permanent = false);
void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false)
{
putSigned(hash, std::make_shared<Value>(std::move(v)), callback, permanent);
}
@@ -111,10 +113,28 @@ 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, std::shared_ptr<Value> val, DoneCallback callback, bool permanent = false);
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
void putEncrypted(
const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false)
{
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
}
void putEncrypted(const InfoHash& hash,
const crypto::PublicKey& to,
Sp<Value> val,
DoneCallback callback,
bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(
const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false)
{
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
}
void putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
/**
* Take ownership of the value and sign it using our private key.
@@ -125,61 +145,241 @@ public:
Value decrypt(const Value& v);
void findCertificate(const InfoHash& node, std::function<void(const std::shared_ptr<crypto::Certificate>)> cb);
void findPublicKey(const InfoHash& node, std::function<void(const std::shared_ptr<const crypto::PublicKey>)> cb);
[[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);
const std::shared_ptr<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
void registerCertificate(std::shared_ptr<crypto::Certificate>& cert);
void findCertificate(const PkId& id, const std::function<void(const Sp<crypto::Certificate>)>& cb);
void findPublicKey(const PkId& id, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
const std::shared_ptr<crypto::Certificate> getCertificate(const InfoHash& node) const;
const std::shared_ptr<const crypto::PublicKey> getPublicKey(const InfoHash& node) const;
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;
/**
* Allows to set a custom callback called by the library to find a locally-stored certificate.
* The search key used is the public key ID, so there may be multiple certificates retured, signed with
* the same private key.
*/
void setLocalCertificateStore(CertificateStoreQuery&& query_method) {
localQueryMethod_ = std::move(query_method);
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); }
/**
* SecureDht to Dht proxy
*/
void shutdown(ShutdownCallback cb, bool stop = false) override { dht_->shutdown(cb, stop); }
void dumpTables() const override { dht_->dumpTables(); }
inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
std::pair<size_t, size_t> getStoreSize() const override { return dht_->getStoreSize(); }
std::pair<size_t, size_t> getLocalStoreSize() const override { return dht_->getLocalStoreSize(); }
std::string getStorageLog() const override { return dht_->getStorageLog(); }
std::string getStorageLog(const InfoHash& h) const override { return dht_->getStorageLog(h); }
void setStorageLimit(size_t limit = 0) override { dht_->setStorageLimit(limit); }
size_t getStorageLimit() const override { return dht_->getStorageLimit(); }
void setLocalStorageLimit(size_t limit = 0) override { dht_->setLocalStorageLimit(limit); }
size_t getLocalStorageLimit() const override { return dht_->getLocalStorageLimit(); }
std::vector<NodeExport> exportNodes() const override { return dht_->exportNodes(); }
std::vector<ValuesExport> exportValues() const override { return dht_->exportValues(); }
void importValues(const std::vector<ValuesExport>& v) override { dht_->importValues(v); }
NodeStats getNodesStats(sa_family_t af) const override { return dht_->getNodesStats(af); }
NodeInfo getNodeInfo()
{
NodeInfo info;
info.id = getId();
info.node_id = getNodeId();
info.ipv4 = getNodesStats(AF_INET);
info.ipv6 = getNodesStats(AF_INET6);
std::tie(info.storage_size, info.storage_values) = getStoreSize();
std::tie(info.local_storage_size, info.local_storage_values) = getLocalStoreSize();
if (auto sock = getSocket()) {
info.bound4 = sock->getBoundRef(AF_INET).getPort();
info.bound6 = sock->getBoundRef(AF_INET6).getPort();
}
return info;
}
std::vector<unsigned> getNodeMessageStats(bool in = false) override { return dht_->getNodeMessageStats(in); }
std::string getRoutingTablesLog(sa_family_t af) const override { return dht_->getRoutingTablesLog(af); }
std::string getSearchesLog(sa_family_t af) const override { return dht_->getSearchesLog(af); }
std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override
{
return dht_->getSearchLog(h, af);
}
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override { return dht_->getPublicAddress(family); }
time_point periodic(const uint8_t* buf, size_t buflen, SockAddr sa, const time_point& now) override
{
return dht_->periodic(buf, buflen, std::move(sa), now);
}
time_point periodic(
const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override
{
return dht_->periodic(buf, buflen, from, fromlen, now);
}
NodeStatus updateStatus(sa_family_t af) override { return dht_->updateStatus(af); }
NodeStatus getStatus(sa_family_t af) const override { return dht_->getStatus(af); }
NodeStatus getStatus() const override { return dht_->getStatus(); }
net::DatagramSocket* getSocket() const override { return dht_->getSocket(); };
bool isRunning(sa_family_t af = 0) const override { return dht_->isRunning(af); }
const ValueType& getType(ValueType::Id type_id) const override { return dht_->getType(type_id); }
void addBootstrap(const std::string& host, const std::string& service) override
{
dht_->addBootstrap(host, service);
}
void clearBootstrap() override { dht_->clearBootstrap(); }
void insertNode(const InfoHash& id, const SockAddr& sa) override { dht_->insertNode(id, sa); }
void insertNode(const NodeExport& n) override { dht_->insertNode(n); }
void pingNode(SockAddr sa, DoneCallbackSimple&& cb = {}) override { dht_->pingNode(std::move(sa), std::move(cb)); }
void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override
{
dht_->query(key, cb, done_cb, std::move(q));
}
void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override
{
dht_->query(key, cb, done_cb, std::move(q));
}
std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override
{
return dht_->getLocal(key, f);
}
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override { return dht_->getLocalById(key, vid); }
void put(const InfoHash& key,
Sp<Value> v,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override
{
dht_->put(key, v, cb, created, permanent);
}
void put(const InfoHash& key,
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
dht_->put(key, v, cb, created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallback cb = nullptr,
time_point created = time_point::max(),
bool permanent = false) override
{
dht_->put(key, std::move(v), cb, created, permanent);
}
void put(const InfoHash& key,
Value&& v,
DoneCallbackSimple cb,
time_point created = time_point::max(),
bool permanent = false) override
{
dht_->put(key, std::move(v), cb, created, permanent);
}
std::vector<Sp<Value>> getPut(const InfoHash& h) const override { return dht_->getPut(h); }
Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) const override { return dht_->getPut(h, vid); }
bool cancelPut(const InfoHash& h, const Value::Id& vid) override { return dht_->cancelPut(h, vid); }
size_t listen(const InfoHash& key, ValueCallback, Value::Filter = {}, Where = {}) override;
size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {}) override
{
return listen(key, bindGetCb(cb), f, w);
}
bool cancelListen(const InfoHash& h, size_t token) override { return dht_->cancelListen(h, token); }
void connectivityChanged(sa_family_t af) override { dht_->connectivityChanged(af); }
void connectivityChanged() override { dht_->connectivityChanged(); }
void forwardAllMessages(bool forward) { forward_all_ = forward; }
void setPushNotificationToken(const std::string& token = "") override { dht_->setPushNotificationToken(token); }
/**
* Call linked callback with push_notification
* @param notification to process
*/
PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& notification) override
{
return dht_->pushNotificationReceived(notification);
}
void setLogger(const std::shared_ptr<Logger>& logger) override
{
DhtInterface::setLogger(logger);
dht_->setLogger(logger);
}
/**
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
*/
void setLogFilter(const InfoHash& f) override
{
DhtInterface::setLogFilter(f);
dht_->setLogFilter(f);
}
private:
std::unique_ptr<DhtInterface> dht_;
// prevent copy
SecureDht(const SecureDht&) = delete;
SecureDht& operator=(const SecureDht&) = delete;
GetCallback getCallbackFilter(GetCallback, Value::Filter&&);
Sp<Value> checkValue(const Sp<Value>& v);
ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
std::shared_ptr<crypto::PrivateKey> key_ {};
std::shared_ptr<crypto::Certificate> certificate_ {};
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
Sp<crypto::Certificate> registerCertificate(const PkId& node, const Blob& cert);
Sp<crypto::PrivateKey> key_ {};
Sp<crypto::Certificate> certificate_ {};
// method to query the local certificate store
CertificateStoreQuery localQueryMethod_ {};
CertificateStoreQueryLegacy localQueryMethodLegacy_ {};
// our certificate cache
std::map<InfoHash, std::shared_ptr<crypto::Certificate>> nodesCertificates_ {};
std::map<InfoHash, std::shared_ptr<const crypto::PublicKey>> nodesPubKeys_ {};
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::uniform_int_distribution<Value::Id> rand_id {};
std::atomic_bool forward_all_ {false};
bool enableCache_ {false};
};
const ValueType CERTIFICATE_TYPE = {
8, "Certificate", std::chrono::hours(24 * 7),
// A certificate can only be stored at it's public key ID.
[](InfoHash id, std::shared_ptr<Value>& v, InfoHash, const sockaddr*, socklen_t) {
try {
crypto::Certificate crt(v->data);
// TODO check certificate signature
return crt.getPublicKey().getId() == id;
} catch (const std::exception& e) {}
return false;
},
[](InfoHash, const std::shared_ptr<Value>& o, std::shared_ptr<Value>& n, InfoHash, const sockaddr*, socklen_t) {
try {
return crypto::Certificate(o->data).getPublicKey().getId() == crypto::Certificate(n->data).getPublicKey().getId();
} catch (const std::exception& e) {}
return false;
}
};
const ValueType CERTIFICATE_TYPE = {8,
"Certificate",
std::chrono::hours(24 * 7),
// A certificate can only be stored at its public key ID.
[](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
try {
crypto::Certificate crt(v->data);
// TODO check certificate signature
return crt.getPublicKey().getId() == id
|| InfoHash::get(crt.getPublicKey().getLongId()) == id;
} catch (const std::exception& e) {
}
return false;
},
[](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
try {
return crypto::Certificate(o->data).getPublicKey().getLongId()
== crypto::Certificate(n->data).getPublicKey().getLongId();
} catch (const std::exception& e) {
}
return false;
}};
}
} // namespace dht
+339
View File
@@ -0,0 +1,339 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include <fmt/core.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef __ANDROID__
typedef uint16_t in_port_t;
#endif
#else
#include <iso646.h>
#include <stdint.h>
#include <winsock2.h>
#include <ws2def.h>
#include <ws2tcpip.h>
typedef uint16_t sa_family_t;
typedef uint16_t in_port_t;
#endif
#include <string>
#include <memory>
#include <vector>
#include <stdexcept>
#include <stdlib.h>
#include <cstring>
#include <cstddef>
namespace dht {
OPENDHT_PUBLIC void print_addr(std::ostream& os, const sockaddr* sa, socklen_t slen);
OPENDHT_PUBLIC std::string print_addr(const sockaddr* sa, socklen_t slen);
OPENDHT_PUBLIC std::string print_addr(const sockaddr_storage& ss, socklen_t sslen);
/**
* A Socket Address (sockaddr*), with abstraction for IPv4, IPv6 address families.
*/
class OPENDHT_PUBLIC SockAddr
{
public:
SockAddr() {}
SockAddr(const SockAddr& o) { set(o.get(), o.getLength()); }
SockAddr(SockAddr&& o) noexcept
: addr(std::move(o.addr))
, len(o.len)
{
o.len = 0;
}
/**
* Build from existing address.
*/
SockAddr(const sockaddr* sa, socklen_t length)
{
if (length > static_cast<socklen_t>(sizeof(sockaddr_storage)))
throw std::runtime_error("Socket address length is too large");
set(sa, length);
}
SockAddr(const sockaddr* sa)
{
socklen_t len = 0;
if (sa) {
if (sa->sa_family == AF_INET)
len = sizeof(sockaddr_in);
else if (sa->sa_family == AF_INET6)
len = sizeof(sockaddr_in6);
else
throw std::runtime_error("Unknown address family");
}
set(sa, len);
}
/**
* Build from an existing sockaddr_storage structure.
*/
SockAddr(const sockaddr_storage& ss, socklen_t len)
: SockAddr((const sockaddr*) &ss, len)
{}
static std::vector<SockAddr> resolve(const std::string& host, const std::string& service = {});
bool operator<(const SockAddr& o) const
{
if (len != o.len)
return len < o.len;
return std::memcmp((const uint8_t*) get(), (const uint8_t*) o.get(), len) < 0;
}
bool equals(const SockAddr& o) const
{
return len == o.len && std::memcmp((const uint8_t*) get(), (const uint8_t*) o.get(), len) == 0;
}
bool operator==(const SockAddr& o) const { return equals(o); }
bool operator!=(const SockAddr& o) const { return !equals(o); }
SockAddr& operator=(const SockAddr& o)
{
set(o.get(), o.getLength());
return *this;
}
SockAddr& operator=(SockAddr&& o)
{
len = o.len;
o.len = 0;
addr = std::move(o.addr);
return *this;
}
std::string toString() const { return print_addr(get(), getLength()); }
/**
* Returns the address family or AF_UNSPEC if the address is not set.
*/
sa_family_t getFamily() const { return len ? addr->sa_family : AF_UNSPEC; }
/**
* Resize the managed structure to the appropriate size (if needed),
* in which case the sockaddr structure is cleared to zero,
* and set the address family field (sa_family).
*/
void setFamily(sa_family_t af)
{
socklen_t new_length;
switch (af) {
case AF_INET:
new_length = sizeof(sockaddr_in);
break;
case AF_INET6:
new_length = sizeof(sockaddr_in6);
break;
default:
new_length = 0;
}
if (new_length != len) {
len = new_length;
if (len)
addr.reset((sockaddr*) ::calloc(len, 1));
else
addr.reset();
}
if (len)
addr->sa_family = af;
}
/**
* Set address to any
*/
void setAny()
{
auto family = getFamily();
switch (family) {
case AF_INET:
getIPv4().sin_addr.s_addr = htonl(INADDR_ANY);
break;
case AF_INET6:
getIPv6().sin6_addr = in6addr_any;
break;
}
}
/**
* Set address to loopback.
*/
void setLoopback()
{
auto family = getFamily();
switch (family) {
case AF_INET:
getIPv4().sin_addr.s_addr = htonl(INADDR_LOOPBACK);
break;
case AF_INET6:
getIPv6().sin6_addr = in6addr_loopback;
break;
}
}
/**
* Retreive the port (in host byte order) or 0 if the address is not
* of a supported family.
*/
in_port_t getPort() const
{
switch (getFamily()) {
case AF_INET:
return ntohs(getIPv4().sin_port);
case AF_INET6:
return ntohs(getIPv6().sin6_port);
default:
return 0;
}
}
/**
* Set the port. The address must be of a supported family.
* @param p The port in host byte order.
*/
void setPort(in_port_t p)
{
switch (getFamily()) {
case AF_INET:
getIPv4().sin_port = htons(p);
break;
case AF_INET6:
getIPv6().sin6_port = htons(p);
break;
}
}
/**
* Set the address part of the socket address from a numeric IP address (string representation).
* Family must be already set. Throws in case of parse failue.
*/
void setAddress(const char* address);
/**
* Returns the accessible byte length at the pointer returned by #get().
* If zero, #get() returns null.
*/
socklen_t getLength() const { return len; }
/**
* An address is defined to be true if its length is not zero.
*/
explicit operator bool() const noexcept { return len; }
/**
* Returns the address to the managed sockaddr structure.
* The accessible length is returned by #getLength().
*/
const sockaddr* get() const { return addr.get(); }
/**
* Returns the address to the managed sockaddr structure.
* The accessible length is returned by #getLength().
*/
sockaddr* get() { return addr.get(); }
inline const sockaddr_in& getIPv4() const { return *reinterpret_cast<const sockaddr_in*>(get()); }
inline const sockaddr_in6& getIPv6() const { return *reinterpret_cast<const sockaddr_in6*>(get()); }
inline sockaddr_in& getIPv4() { return *reinterpret_cast<sockaddr_in*>(get()); }
inline sockaddr_in6& getIPv6() { return *reinterpret_cast<sockaddr_in6*>(get()); }
/**
* Releases the ownership of the managed object, if any.
* The caller is responsible for deleting the object with free().
*/
inline sockaddr* release()
{
len = 0;
return addr.release();
}
/**
* Return true if address is a loopback IP address.
*/
bool isLoopback() const;
/**
* Return true if address is not a public IP address.
*/
bool isPrivate() const;
bool isUnspecified() const;
bool isMappedIPv4() const;
SockAddr getMappedIPv4();
SockAddr getMappedIPv6();
/**
* A comparator to classify IP addresses, only considering the
* first 64 bits in IPv6.
*/
struct ipCmp
{
bool operator()(const SockAddr& a, const SockAddr& b) const
{
if (a.len != b.len)
return a.len < b.len;
socklen_t start, len;
switch (a.getFamily()) {
case AF_INET:
start = offsetof(sockaddr_in, sin_addr);
len = sizeof(in_addr);
break;
case AF_INET6:
start = offsetof(sockaddr_in6, sin6_addr);
// don't consider more than 64 bits (IPv6)
len = 8;
break;
default:
start = 0;
len = a.len;
break;
}
return std::memcmp((uint8_t*) a.get() + start, (uint8_t*) b.get() + start, len) < 0;
}
};
friend std::ostream& operator<<(std::ostream& s, const SockAddr& h)
{
print_addr(s, h.get(), h.getLength());
return s;
}
private:
struct free_delete
{
void operator()(void* p) { ::free(p); }
};
std::unique_ptr<sockaddr, free_delete> addr {};
socklen_t len {0};
void set(const sockaddr* sa, socklen_t length)
{
if (len != length) {
len = length;
if (len)
addr.reset((sockaddr*) ::malloc(len));
else
addr.reset();
}
if (len)
std::memcpy((uint8_t*) get(), (const uint8_t*) sa, len);
}
};
} // namespace dht
#if FMT_VERSION >= 90000
template<>
struct fmt::formatter<dht::SockAddr> : ostream_formatter
{};
#endif
+162
View File
@@ -0,0 +1,162 @@
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#include "def.h"
#include <condition_variable>
#include <vector>
#include <queue>
#include <future>
#include <functional>
#include <ciso646> // fix windows compiler bug
namespace dht {
class OPENDHT_PUBLIC ThreadPool
{
public:
static ThreadPool& computation();
static ThreadPool& io();
ThreadPool();
ThreadPool(unsigned minThreads, unsigned maxThreads = 0);
~ThreadPool();
void run(std::function<void()>&& cb);
template<class T>
std::future<T> get(std::function<T()>&& cb)
{
auto ret = std::make_shared<std::promise<T>>();
run([cb = std::move(cb), ret]() mutable {
try {
ret->set_value(cb());
} catch (...) {
try {
ret->set_exception(std::current_exception());
} catch (...) {
}
}
});
return ret->get_future();
}
template<class T>
std::shared_future<T> getShared(std::function<T()>&& cb)
{
return get(std::move(cb));
}
void stop(bool wait = true);
void join();
void detach();
private:
std::mutex lock_;
std::condition_variable cv_ {};
std::queue<std::function<void()>> tasks_ {};
std::vector<std::unique_ptr<std::thread>> threads_;
unsigned readyThreads_ {0};
bool running_ {true};
unsigned minThreads_;
const unsigned maxThreads_;
std::chrono::steady_clock::duration threadExpirationDelay {std::chrono::minutes(5)};
double threadDelayRatio_ {2};
void threadEnded(std::thread&);
};
class OPENDHT_PUBLIC Executor : public std::enable_shared_from_this<Executor>
{
public:
Executor(ThreadPool& pool, unsigned maxConcurrent = 1)
: threadPool_(pool)
, maxConcurrent_(maxConcurrent)
{}
void run(std::function<void()>&& task);
private:
std::reference_wrapper<ThreadPool> threadPool_;
const unsigned maxConcurrent_ {1};
std::mutex lock_;
unsigned current_ {0};
std::queue<std::function<void()>> tasks_ {};
void run_(std::function<void()>&& task);
void schedule();
};
class OPENDHT_PUBLIC ExecutionContext
{
public:
ExecutionContext(ThreadPool& pool)
: threadPool_(pool)
, state_(std::make_shared<SharedState>())
{}
~ExecutionContext() { state_->destroy(); }
/** Wait for ongoing tasks to complete execution and drop other pending tasks */
void stop() { state_->destroy(false); }
void run(std::function<void()>&& task)
{
std::lock_guard<std::mutex> lock(state_->mtx);
if (state_->shutdown_)
return;
state_->pendingTasks++;
threadPool_.get().run([task = std::move(task), state = state_] { state->run(task); });
}
private:
struct SharedState
{
std::mutex mtx;
std::condition_variable cv {};
unsigned pendingTasks {0};
unsigned ongoingTasks {0};
/** When true, prevents new tasks to be scheduled */
bool shutdown_ {false};
/** When true, prevents scheduled tasks to be executed */
std::atomic_bool destroyed {false};
void destroy(bool wait = true)
{
std::unique_lock<std::mutex> lock(mtx);
if (destroyed)
return;
if (wait) {
cv.wait(lock, [this] { return pendingTasks == 0 && ongoingTasks == 0; });
}
shutdown_ = true;
if (not wait) {
cv.wait(lock, [this] { return ongoingTasks == 0; });
}
destroyed = true;
}
void run(const std::function<void()>& task)
{
{
std::lock_guard<std::mutex> lock(mtx);
pendingTasks--;
ongoingTasks++;
}
if (destroyed)
return;
task();
{
std::lock_guard<std::mutex> lock(mtx);
ongoingTasks--;
cv.notify_all();
}
}
};
std::reference_wrapper<ThreadPool> threadPool_;
std::shared_ptr<SharedState> state_;
};
} // namespace dht
+137 -107
View File
@@ -1,172 +1,202 @@
/*
* Copyright (C) 2014-2016 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
// SPDX-License-Identifier: MIT
#pragma once
#define WANT4 1
#define WANT6 2
#include "def.h"
#include <type_traits>
#include <msgpack.hpp>
#ifndef _WIN32
#include <sys/socket.h>
#else
#include <ws2def.h>
#include <ws2tcpip.h>
#endif
#include <fmt/format.h>
#include <chrono>
#include <random>
#include <functional>
#include <map>
#include <string_view>
#include <cstdarg>
#define WANT4 1
#define WANT6 2
/**
* OpenDHT C++ namespace
*/
namespace dht {
static constexpr unsigned TARGET_NODES {8};
using Address = std::pair<sockaddr_storage, socklen_t>;
using NetId = uint32_t;
using want_t = int_fast8_t;
std::string print_addr(const sockaddr* sa, socklen_t slen);
std::string print_addr(const sockaddr_storage& ss, socklen_t sslen);
std::string printAddr(const Address& addr);
OPENDHT_PUBLIC const char* version();
template <typename Key, typename Item, typename Condition>
void erase_if(std::map<Key, Item>& map, const Condition& condition)
// shortcut for std::shared_ptr
template<class T>
using Sp = std::shared_ptr<T>;
template<typename Key, typename Item, typename Condition>
void
erase_if(std::map<Key, Item>& map, const Condition& condition)
{
for (auto it = map.begin(); it != map.end(); ) {
for (auto it = map.begin(); it != map.end();) {
if (condition(*it)) {
it = map.erase(it);
} else { ++it; }
} else {
++it;
}
}
}
class DhtException : public std::runtime_error {
public:
DhtException(const std::string &str = "") :
std::runtime_error("DhtException occured: " + str) {}
template<typename... Args>
std::string
concat(Args&&... args)
{
static_assert((std::is_constructible_v<std::string_view, Args&&> && ...));
std::string s;
s.reserve((std::string_view {args}.size() + ...));
(s.append(std::forward<Args>(args)), ...);
return s;
}
/**
* Split "[host]:port" or "host:port" to pair<"host", "port">.
*/
OPENDHT_PUBLIC std::pair<std::string_view, std::string_view> splitPort(std::string_view s);
class OPENDHT_PUBLIC DhtException : public std::runtime_error
{
public:
DhtException(const std::string& str = "")
: std::runtime_error("DhtException occurred: " + str)
{}
};
class OPENDHT_PUBLIC SocketException : public DhtException
{
public:
SocketException(int err)
: DhtException(strerror(err))
{}
};
// Time related definitions and utility functions
using clock = std::chrono::steady_clock;
using system_clock = std::chrono::system_clock;
using time_point = clock::time_point;
using duration = clock::duration;
time_point from_time_t(std::time_t t);
std::time_t to_time_t(time_point t);
OPENDHT_PUBLIC time_point from_time_t(std::time_t t);
OPENDHT_PUBLIC std::time_t to_time_t(time_point t);
/**
* Converts std::chrono::duration to floating-point seconds.
*/
template <class DT>
static double
print_dt(DT d) {
return std::chrono::duration_cast<std::chrono::duration<double>>(d).count();
template<class DT>
static std::string
print_duration(DT d)
{
if (d < std::chrono::seconds(0)) {
return "-" + print_duration(-d);
} else if (d < std::chrono::milliseconds(1)) {
return fmt::format("{:.3g} us",
std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(d).count());
} else if (d < std::chrono::seconds(1)) {
return fmt::format("{:.3g} ms",
std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(d).count());
} else if (d < std::chrono::minutes(1)) {
return fmt::format("{:.3g} s", std::chrono::duration_cast<std::chrono::duration<double>>(d).count());
} else if (d < std::chrono::hours(1)) {
return fmt::format("{:.3g} min",
std::chrono::duration_cast<std::chrono::duration<double, std::ratio<60>>>(d).count());
} else if (d < std::chrono::hours(72)) {
return fmt::format("{:.3g} h",
std::chrono::duration_cast<std::chrono::duration<double, std::ratio<3600>>>(d).count());
} else {
return fmt::format("{:.3g} days",
std::chrono::duration_cast<std::chrono::duration<double, std::ratio<86400>>>(d).count());
}
}
static /*constexpr*/ const time_point TIME_INVALID = {time_point::min()};
static /*constexpr*/ const time_point TIME_MAX {time_point::max()};
template<class TimePoint>
static std::string
print_time_relative(TimePoint now, TimePoint d)
{
using namespace std::literals;
if (d == TimePoint::min())
return "never"s;
if (d == now)
return "now"s;
return (d > now) ? concat("in "sv, print_duration(d - now)) : concat(print_duration(now - d), " ago"sv);
}
template <typename Duration = duration>
class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep> {
OPENDHT_PUBLIC std::string printByteCount(size_t bytes);
template<typename Duration = duration>
class uniform_duration_distribution : public std::uniform_int_distribution<typename Duration::rep>
{
using Base = std::uniform_int_distribution<typename Duration::rep>;
using param_type = typename Base::param_type;
public:
uniform_duration_distribution(Duration min, Duration max) : Base(min.count(), max.count()) {}
template <class Generator>
Duration operator()(Generator && g) {
uniform_duration_distribution(Duration min, Duration max)
: Base(min.count(), max.count())
{}
template<class Generator>
Duration operator()(Generator&& g)
{
return Duration(Base::operator()(g));
}
template< class Generator >
Duration operator()( Generator && g, const param_type& params ) {
template<class Generator>
Duration operator()(Generator&& g, const param_type& params)
{
return Duration(Base::operator()(g, params));
}
};
// Logging related utility functions
/**
* Dummy function used to disable logging
*/
inline void NOLOG(char const*, va_list) {}
/**
* Wrapper for logging methods
*/
struct LogMethod {
LogMethod() = default;
template<typename T>
LogMethod(T&& t) : func(std::forward<T>(t)) {}
void operator()(char const* format, ...) const {
va_list args;
va_start(args, format);
func(format, args);
va_end(args);
}
void logPrintable(const uint8_t *buf, size_t buflen) const {
std::string buf_clean(buflen, '\0');
for (size_t i=0; i<buflen; i++)
buf_clean[i] = isprint(buf[i]) ? buf[i] : '.';
(*this)("%s", buf_clean.c_str());
}
private:
std::function<void(char const*, va_list)> func;
};
struct Logger {
LogMethod DEBUG = NOLOG;
LogMethod WARN = NOLOG;
LogMethod ERR = NOLOG;
};
// Serialization related definitions and utility functions
/**
* Arbitrary binary data.
*/
using Blob = std::vector<uint8_t>;
/**
* Provides backward compatibility with msgpack 1.0
*/
Blob unpackBlob(msgpack::object& o);
OPENDHT_PUBLIC Blob unpackBlob(const msgpack::object& o);
template <typename Type>
template<typename Type>
Blob
packMsg(const Type& t) {
packMsg(const Type& t)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack(t);
return {buffer.data(), buffer.data()+buffer.size()};
return {buffer.data(), buffer.data() + buffer.size()};
}
template <typename Type>
template<typename Type>
Type
unpackMsg(Blob b) {
msgpack::unpacked msg_res = msgpack::unpack((const char*)b.data(), b.size());
unpackMsg(const Blob& b)
{
msgpack::unpacked msg_res = msgpack::unpack((const char*) b.data(), b.size());
return msg_res.get().as<Type>();
}
msgpack::unpacked unpackMsg(Blob b);
inline msgpack::unpacked
unpackMsg(const Blob& b)
{
return msgpack::unpack((const char*) b.data(), b.size());
}
OPENDHT_PUBLIC msgpack::object* findMapValue(const msgpack::object& map, const char* key, size_t length);
inline msgpack::object*
findMapValue(const msgpack::object& map, const char* key)
{
return findMapValue(map, key, strlen(key));
}
inline msgpack::object*
findMapValue(const msgpack::object& map, std::string_view key)
{
return findMapValue(map, key.data(), key.size());
}
} // namespace dht
+794 -187
View File
File diff suppressed because it is too large. Load diff
-562
View File
@@ -1,562 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
# required and that the macro should error out if no mode with that
# support is found. If specified 'optional', then configuration proceeds
# regardless, after defining HAVE_CXX${VERSION} if and only if a
# supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 4
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [],
[$1], [14], [],
[$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
[$2], [noext], [],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
ax_cv_cxx_compile_cxx$1,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[ax_cv_cxx_compile_cxx$1=yes],
[ax_cv_cxx_compile_cxx$1=no])])
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
ac_success=yes
fi
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++$1 -std=gnu++0x; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
m4_if([$2], [ext], [], [dnl
if test x$ac_success = xno; then
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
fi
fi
if test x$ac_success = xno; then
HAVE_CXX$1=0
AC_MSG_NOTICE([No compiler with C++$1 support was found])
else
HAVE_CXX$1=1
AC_DEFINE(HAVE_CXX$1,1,
[define if the compiler supports basic C++$1 syntax])
fi
AC_SUBST(HAVE_CXX$1)
])
dnl Test body for checking C++11 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
// If the compiler admits that it is not ready for C++11, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#else
namespace cxx11
{
namespace test_static_assert
{
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
}
namespace test_final_override
{
struct Base
{
virtual void f() {}
};
struct Derived : public Base
{
virtual void f() override {}
};
}
namespace test_double_right_angle_brackets
{
template < typename T >
struct check {};
typedef check<void> single_type;
typedef check<check<void>> double_type;
typedef check<check<check<void>>> triple_type;
typedef check<check<check<check<void>>>> quadruple_type;
}
namespace test_decltype
{
int
f()
{
int a = 1;
decltype(a) b = 2;
return a + b;
}
}
namespace test_type_deduction
{
template < typename T1, typename T2 >
struct is_same
{
static const bool value = false;
};
template < typename T >
struct is_same<T, T>
{
static const bool value = true;
};
template < typename T1, typename T2 >
auto
add(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int
test(const int c, volatile int v)
{
static_assert(is_same<int, decltype(0)>::value == true, "");
static_assert(is_same<int, decltype(c)>::value == false, "");
static_assert(is_same<int, decltype(v)>::value == false, "");
auto ac = c;
auto av = v;
auto sumi = ac + av + 'x';
auto sumf = ac + av + 1.0;
static_assert(is_same<int, decltype(ac)>::value == true, "");
static_assert(is_same<int, decltype(av)>::value == true, "");
static_assert(is_same<int, decltype(sumi)>::value == true, "");
static_assert(is_same<int, decltype(sumf)>::value == false, "");
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
return (sumf > 0.0) ? sumi : add(c, v);
}
}
namespace test_noexcept
{
int f() { return 0; }
int g() noexcept { return 0; }
static_assert(noexcept(f()) == false, "");
static_assert(noexcept(g()) == true, "");
}
namespace test_constexpr
{
template < typename CharT >
unsigned long constexpr
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
{
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
}
template < typename CharT >
unsigned long constexpr
strlen_c(const CharT *const s) noexcept
{
return strlen_c_r(s, 0UL);
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("1") == 1UL, "");
static_assert(strlen_c("example") == 7UL, "");
static_assert(strlen_c("another\0example") == 7UL, "");
}
namespace test_rvalue_references
{
template < int N >
struct answer
{
static constexpr int value = N;
};
answer<1> f(int&) { return answer<1>(); }
answer<2> f(const int&) { return answer<2>(); }
answer<3> f(int&&) { return answer<3>(); }
void
test()
{
int i = 0;
const int c = 0;
static_assert(decltype(f(i))::value == 1, "");
static_assert(decltype(f(c))::value == 2, "");
static_assert(decltype(f(0))::value == 3, "");
}
}
namespace test_uniform_initialization
{
struct test
{
static const int zero {};
static const int one {1};
};
static_assert(test::zero == 0, "");
static_assert(test::one == 1, "");
}
namespace test_lambdas
{
void
test1()
{
auto lambda1 = [](){};
auto lambda2 = lambda1;
lambda1();
lambda2();
}
int
test2()
{
auto a = [](int i, int j){ return i + j; }(1, 2);
auto b = []() -> int { return '0'; }();
auto c = [=](){ return a + b; }();
auto d = [&](){ return c; }();
auto e = [a, &b](int x) mutable {
const auto identity = [](int y){ return y; };
for (auto i = 0; i < a; ++i)
a += b--;
return x + identity(a + b);
}(0);
return a + b + c + d + e;
}
int
test3()
{
const auto nullary = [](){ return 0; };
const auto unary = [](int x){ return x; };
using nullary_t = decltype(nullary);
using unary_t = decltype(unary);
const auto higher1st = [](nullary_t f){ return f(); };
const auto higher2nd = [unary](nullary_t f1){
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
};
return higher1st(nullary) + higher2nd(nullary)(unary);
}
}
namespace test_variadic_templates
{
template <int...>
struct sum;
template <int N0, int... N1toN>
struct sum<N0, N1toN...>
{
static constexpr auto value = N0 + sum<N1toN...>::value;
};
template <>
struct sum<>
{
static constexpr auto value = 0;
};
static_assert(sum<>::value == 0, "");
static_assert(sum<1>::value == 1, "");
static_assert(sum<23>::value == 23, "");
static_assert(sum<1, 2>::value == 3, "");
static_assert(sum<5, 5, 11>::value == 21, "");
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
}
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
// because of this.
namespace test_template_alias_sfinae
{
struct foo {};
template<typename T>
using member = typename T::member_type;
template<typename T>
void func(...) {}
template<typename T>
void func(member<T>*) {}
void test();
void test() { func<foo>(0); }
}
} // namespace cxx11
#endif // __cplusplus >= 201103L
]])
dnl Tests for new features in C++14
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
// If the compiler admits that it is not ready for C++14, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#else
namespace cxx14
{
namespace test_polymorphic_lambdas
{
int
test()
{
const auto lambda = [](auto&&... args){
const auto istiny = [](auto x){
return (sizeof(x) == 1UL) ? 1 : 0;
};
const int aretiny[] = { istiny(args)... };
return aretiny[0];
};
return lambda(1, 1L, 1.0f, '1');
}
}
namespace test_binary_literals
{
constexpr auto ivii = 0b0000000000101010;
static_assert(ivii == 42, "wrong value");
}
namespace test_generalized_constexpr
{
template < typename CharT >
constexpr unsigned long
strlen_c(const CharT *const s) noexcept
{
auto length = 0UL;
for (auto p = s; *p; ++p)
++length;
return length;
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("x") == 1UL, "");
static_assert(strlen_c("test") == 4UL, "");
static_assert(strlen_c("another\0test") == 7UL, "");
}
namespace test_lambda_init_capture
{
int
test()
{
auto x = 0;
const auto lambda1 = [a = x](int b){ return a + b; };
const auto lambda2 = [a = lambda1(x)](){ return a; };
return lambda2();
}
}
namespace test_digit_seperators
{
constexpr auto ten_million = 100'000'000;
static_assert(ten_million == 100000000, "");
}
namespace test_return_type_deduction
{
auto f(int& x) { return x; }
decltype(auto) g(int& x) { return x; }
template < typename T1, typename T2 >
struct is_same
{
static constexpr auto value = false;
};
template < typename T >
struct is_same<T, T>
{
static constexpr auto value = true;
};
int
test()
{
auto x = 0;
static_assert(is_same<int, decltype(f(x))>::value, "");
static_assert(is_same<int&, decltype(g(x))>::value, "");
return x;
}
}
} // namespace cxx14
#endif // __cplusplus >= 201402L
]])
+341
View File
@@ -0,0 +1,341 @@
project(
'opendht',
'c',
'cpp',
'cython',
license: 'MIT',
license_files: 'LICENSE',
version: '3.7.6',
meson_version: '>=1.1.0',
default_options: ['cpp_std=c++20', 'warning_level=3'],
)
gnutls = dependency('gnutls')
nettle = dependency('nettle')
msgpack = dependency('msgpack-cxx', required: false)
argon2 = dependency('libargon2')
fmt = dependency('fmt')
openssl = dependency('openssl', required: get_option('proxy_client'))
jsoncpp = dependency('jsoncpp', required: get_option('proxy_client'))
llhttp = dependency('llhttp', 'libllhttp', required: get_option('proxy_client'))
simdutf = dependency('simdutf', required: get_option('proxy_client'))
io_uring = host_machine.system() == 'linux' ? dependency('liburing', required: false) : disabler()
deps = [
fmt,
gnutls,
nettle,
msgpack,
argon2,
openssl,
jsoncpp,
simdutf,
llhttp,
]
if host_machine.system() == 'linux' and io_uring.found()
deps += io_uring
endif
conf_data = configuration_data()
add_project_arguments('-DMSGPACK_NO_BOOST', '-DASIO_STANDALONE', language: 'cpp')
if io_uring.found()
add_project_arguments('-DASIO_HAS_IO_URING', '-DASIO_DISABLE_EPOLL', language: 'cpp')
conf_data.set('iouring_lib', ', liburing')
endif
add_project_arguments(
[
'-Wno-return-type',
'-Wno-deprecated',
'-Wnon-virtual-dtor',
'-pedantic-errors',
'-fvisibility=hidden',
],
language: 'cpp',
)
opendht_inc = include_directories('include/opendht')
opendht_interface_inc = include_directories('include', is_system: true)
opendht_src = [
'src/utils.cpp',
'src/crypto.cpp',
'src/default_types.cpp',
'src/node.cpp',
'src/value.cpp',
'src/dht.cpp',
'src/callbacks.cpp',
'src/routing_table.cpp',
'src/node_cache.cpp',
'src/network_engine.cpp',
'src/securedht.cpp',
'src/dhtrunner.cpp',
'src/log.cpp',
'src/op_cache.cpp',
'src/network_utils.cpp',
'src/thread_pool.cpp',
]
if get_option('indexation').enabled()
opendht_src += 'src/indexation/pht.cpp'
add_project_arguments('-DOPENDHT_INDEXATION', language: 'cpp')
endif
if jsoncpp.found()
opendht_src += ['src/base64.cpp']
add_project_arguments('-DOPENDHT_JSONCPP', language: 'cpp')
conf_data.set('jsoncpp_lib', ', jsoncpp')
endif
if llhttp.found()
opendht_src += ['src/http.cpp', 'src/compat/os_cert.cpp']
if host_machine.system() == 'darwin'
deps += dependency('appleframeworks', modules: ['CoreFoundation', 'Security'])
endif
conf_data.set('http_lib', '-lllhttp')
endif
if openssl.found()
conf_data.set('openssl_lib', ', openssl')
endif
if get_option('proxy_client').enabled()
opendht_src += ['src/dht_proxy_client.cpp']
add_project_arguments('-DOPENDHT_PROXY_CLIENT', language: 'cpp')
endif
if get_option('proxy_server').enabled()
opendht_src += 'src/dht_proxy_server.cpp'
add_project_arguments('-DOPENDHT_PROXY_SERVER', language: 'cpp')
endif
if get_option('push_notifications').enabled()
add_project_arguments('-DOPENDHT_PUSH_NOTIFICATIONS', language: 'cpp')
endif
if get_option('peer_discovery').enabled()
opendht_src += 'src/peer_discovery.cpp'
add_project_arguments('-DOPENDHT_PEER_DISCOVERY', language: 'cpp')
endif
opendht = library(
'opendht',
opendht_src,
include_directories: opendht_inc,
dependencies: deps,
cpp_args: ['-DOPENDHT_BUILD', '-Dopendht_EXPORTS'],
install: true,
)
opendht_dep_args = []
if get_option('default_library') != 'static'
opendht_dep_args += '-Dopendht_EXPORTS'
endif
opendht_dep = declare_dependency(
link_with: opendht,
include_directories: opendht_interface_inc,
compile_args: opendht_dep_args,
)
# Install library headers.
install_subdir('include', install_dir: get_option('includedir'), strip_directory: true)
conf_data.set('VERSION', meson.project_version())
conf_data.set('prefix', get_option('prefix'))
conf_data.set('exec_prefix', get_option('prefix'))
conf_data.set('libdir', join_paths(get_option('prefix'), get_option('libdir')))
conf_data.set('includedir', join_paths(get_option('prefix'), get_option('includedir')))
conf_data.set('argon2_lib', ', libargon2')
conf_data.set('simdutf_lib', ', simdutf')
conf_data.set('opendht_public_cflags', '')
conf_data.set('opendht_c_public_cflags', '')
if get_option('default_library') != 'static'
conf_data.set('opendht_public_cflags', ' -Dopendht_EXPORTS')
conf_data.set('opendht_c_public_cflags', ' -Dopendht_c_EXPORTS')
endif
configure_file(
input: 'opendht.pc.in',
output: 'opendht.pc',
configuration: conf_data,
install: true,
install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'pkgconfig'),
)
readline = meson.get_compiler('c').find_library('readline', required: get_option('tools'))
if get_option('c').enabled()
opendht_c = library(
'opendht-c',
['c/opendht.cpp', 'c/opendht_c.h'],
dependencies: [opendht_dep, msgpack, jsoncpp, fmt],
cpp_args: ['-DOPENDHT_C_BUILD', '-Dopendht_c_EXPORTS'],
install: true,
)
install_headers('c/opendht_c.h', subdir: 'opendht')
configure_file(
input: 'opendht-c.pc.in',
output: 'opendht-c.pc',
configuration: conf_data,
install: true,
install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'pkgconfig'),
)
if get_option('tools').enabled()
dhtcnode = executable(
'dhtcnode',
'tools/dhtcnode.c',
include_directories: ['c', opendht_interface_inc],
link_with: opendht_c,
dependencies: [readline],
install: true,
)
endif
endif
if get_option('python').require(
get_option('indexation').enabled(),
error_message: 'python requires indexation',
).allowed()
py = import('python').find_installation()
dep_py = py.dependency()
py.extension_module(
'opendht',
'python/opendht.pyx',
override_options: ['cython_language=cpp'],
dependencies: [opendht_dep, msgpack, jsoncpp, fmt, dep_py],
install: true,
)
endif
if get_option('tools').enabled()
dhtnode = executable(
'dhtnode',
'tools/dhtnode.cpp',
dependencies: [opendht_dep, readline, jsoncpp, msgpack, fmt, openssl],
install: true,
)
dhtchat = executable(
'dhtchat',
'tools/dhtchat.cpp',
dependencies: [opendht_dep, readline, jsoncpp, msgpack, fmt, openssl],
install: true,
)
dhtscanner = executable(
'dhtscanner',
'tools/dhtscanner.cpp',
dependencies: [opendht_dep, readline, jsoncpp, msgpack, fmt, openssl],
install: true,
)
if llhttp.found()
durl_deps = [msgpack, openssl]
if io_uring.found()
durl_deps += io_uring
endif
durl = executable(
'durl',
'tools/durl.cpp',
dependencies: [opendht_dep] + durl_deps,
)
endif
endif
# Unit tests
if get_option('tests').enabled()
cppunit = dependency('cppunit')
test_infohash = executable(
'test_infohash',
'tests/test_infohash.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('Infohash', test_infohash)
test_value = executable(
'test_value',
'tests/test_value.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('Value', test_value)
test_parsedmessage = executable(
'test_parsedmessage',
'tests/test_parsedmessage.cpp',
'tests/tests_runner.cpp',
include_directories: opendht_inc,
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('ParsedMessage', test_parsedmessage)
test_networkengine = executable(
'test_networkengine',
'tests/test_networkengine.cpp',
'tests/tests_runner.cpp',
include_directories: opendht_inc,
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('NetworkEngine', test_networkengine)
test_crypto = executable(
'test_crypto',
'tests/test_crypto.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack, gnutls],
)
test('Crypto', test_crypto, timeout: 60)
test_dhtrunner = executable(
'test_dhtrunner',
'tests/test_dhtrunner.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('DhtRunner', test_dhtrunner, timeout: 60)
test_threadpool = executable(
'test_threadpool',
'tests/test_threadpool.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('ThreadPool', test_threadpool)
if get_option('proxy_client').enabled() or get_option('proxy_server').enabled()
test_http = executable(
'test_http',
'tests/test_http.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('Http', test_http)
endif
if get_option('peer_discovery').enabled()
test_peerdiscovery = executable(
'test_peerdiscovery',
'tests/test_peerdiscovery.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('PeerDiscovery', test_peerdiscovery)
endif
if get_option('proxy_server').enabled()
test_proxy = executable(
'test_dhtproxy',
'tests/test_dhtproxy.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('DhtProxy', test_proxy)
if get_option('long_tests').enabled()
test_proxystress = executable(
'test_dhtproxystress',
'tests/dhtproxy_stress_tester.cpp',
'tests/tests_runner.cpp',
dependencies: [opendht_dep, cppunit, jsoncpp, fmt, openssl, msgpack],
)
test('DhtProxy Stress', test_proxystress)
endif
endif
endif
+10
View File
@@ -0,0 +1,10 @@
option('proxy_client', type : 'feature', value : 'disabled')
option('proxy_server', type : 'feature', value : 'disabled')
option('push_notifications', type : 'feature', value : 'disabled')
option('peer_discovery', type : 'feature', value : 'enabled')
option('tools', type : 'feature', value : 'enabled')
option('c', type : 'feature', value : 'enabled')
option('indexation', type : 'feature', value : 'enabled')
option('python', type : 'feature', value : 'enabled')
option('tests', type : 'feature', value : 'enabled')
option('long_tests', type : 'feature', value : 'disabled')
+10
View File
@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenDHT (C Wrapper)
Description: Distributed Hash Table library (C Wrapper)
Version: @VERSION@
Libs: -L${libdir} -lopendht-c
Requires.private: opendht gnutls >= 3.1 @argon2_lib@
Cflags: -I${includedir}@opendht_c_public_cflags@
+6 -5
View File
@@ -3,9 +3,10 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenDHT
Description: C++ Distributed Hash Table library
Description: C++17 Distributed Hash Table library
Version: @VERSION@
Libs: -L${libdir} -lopendht
Libs.private: -lpthread
Requires.private: gnutls >= 3.1
Cflags: -I${includedir}
Libs: -L${libdir} -lopendht -lfmt
Libs.private: @http_lib@ -pthread
Requires: gnutls >= 3.3@jsoncpp_lib@@openssl_lib@
Requires.private: nettle >= 2.4@argon2_lib@@llhttp_lib@@iouring_lib@@simdutf_lib@
Cflags: -I${includedir}@opendht_public_cflags@
+43 -5
View File
@@ -1,11 +1,49 @@
set(CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(setup.py.in setup.py)
configure_file(pyproject.toml pyproject.toml COPYONLY)
configure_file(README.md README.md COPYONLY)
add_custom_target(python ALL
COMMAND python3 setup.py build
DEPENDS opendht opendht_cpp.pxd opendht.pyx)
find_package(Python3 REQUIRED COMPONENTS Interpreter)
install(CODE "execute_process(COMMAND python3 setup.py install --root=\$ENV{DESTDIR}/ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})")
add_custom_target(python
COMMAND ${Python3_EXECUTABLE} -m build "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS opendht opendht_cpp.pxd opendht.pyx pyproject.toml
${CURRENT_SOURCE_DIR}/opendht/__init__.py
${CURRENT_SOURCE_DIR}/opendht/aio.py)
install(CODE [[
if(NOT Python3_EXECUTABLE)
find_package(Python3 COMPONENTS Interpreter)
endif()
if(NOT Python3_EXECUTABLE)
message(WARNING "Skipping Python package install: Python interpreter not found.")
else()
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip --version
OUTPUT_QUIET
ERROR_QUIET
RESULT_VARIABLE _pip_check)
if(NOT _pip_check EQUAL 0)
message(WARNING "Skipping Python package install: pip not available for ${Python3_EXECUTABLE}.")
else()
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install --no-deps --break-system-packages .
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/python
OUTPUT_VARIABLE _pip_output
ERROR_VARIABLE _pip_error
RESULT_VARIABLE _pip_result)
if(_pip_result EQUAL 0)
message(STATUS "Successfully installed Python package")
message(STATUS "Output: ${_pip_output}")
else()
message(WARNING "pip install failed (code: ${_pip_result})\nOutput: ${_pip_output}\nError: ${_pip_error}")
endif()
endif()
endif()
]])
if (OPENDHT_TOOLS)
install(PROGRAMS tools/dhtcluster.py DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME dhtcluster)
endif()
-25
View File
@@ -1,25 +0,0 @@
if USE_CYTHON
PYTHON_INSTALL_RECORD = $(builddir)/install_record.txt
pybuild.stamp:
LDFLAGS="-L$(top_srcdir)/src/.libs" $(PYTHON) setup.py build_ext --inplace
echo stamp > pybuild.stamp
CLEANFILES = pybuild.stamp
all-local: pybuild.stamp
clean-local:
rm -rf $(builddir)/build $(builddir)/*.so $(PYTHON_INSTALL_RECORD)
install-exec-local:
$(PYTHON) setup.py install --root=$(DESTDIR)/ --record $(PYTHON_INSTALL_RECORD)
rm -rf $(builddir)/build
if HAVE_PIP
uninstall-local:
/usr/bin/yes | $(PIP) uninstall $(PACKAGE)
endif
endif
+89
View File
@@ -0,0 +1,89 @@
# OpenDHT
OpenDHT is a lightweight Distributed Hash Table implementation providing an easy to use distributed in-memory data store.
## Key Features
* Lightweight and scalable, designed for large networks and small devices
* High resilience to network disruption
* Public key cryptography layer providing optional data signature and encryption
* IPv4 and IPv6 support
* Python 3 bindings
* REST API with optional HTTP client+server with push notification support
Every node in the network can read and write values to the store. Values are distributed over the network with redundancy.
## Installation
Install on Linux, macOS and Windows with:
```sh
pip install opendht
```
## Quick Example
Using the simple, blocking API:
```python
import opendht as dht
node = dht.DhtRunner()
node.run()
# Join the DHT network through any running node,
# here using a known bootstrap node.
node.bootstrap("bootstrap.jami.net", "4222")
# blocking call (provide callback arguments to make the call non-blocking)
node.put(dht.InfoHash.get("unique_key"), dht.Value(b'some binary data'))
results = node.get(dht.InfoHash.get("unique_key"))
for value in results:
print(value)
```
Or using asyncio:
```python
import asyncio
import opendht.aio as dht
async def dht_async_demo(key_str: str):
# Start a new node using an async context manager.
# It is also possible to call run()/await shutdown() manually.
async with dht.DhtRunner(
bootstrap=(("bootstrap.jami.net", "4222"),)
) as node:
# compute key hash
key = dht.InfoHash.get(key_str)
# put data, waiting for completion
await node.put(key, dht.Value(b'tata data'))
# get all values at key
results = await node.getAll(key)
for value in results:
print(value)
# same operation, but stream values as they come from the network
with node.get(key) as results:
async for value in results:
print(value)
# listen for change of values at key
with node.listen(key) as values:
async for value, expired in values:
print(value)
if value.data == b'tata data':
break
asyncio.run(dht_async_demo("unique_key"))
```
## Documentation
For more information, examples and documentation, or to repport issues, visit: https://opendht.net
## License
Copyright (c) 2014-2026 Savoir-faire Linux Inc.
OpenDHT is released under the MIT License. See [LICENSE](LICENSE) for details.
+680 -124
View File
@@ -1,58 +1,77 @@
# distutils: language = c++
# distutils: extra_compile_args = -std=c++11
# distutils: extra_compile_args = -std=c++17
# distutils: include_dirs = ../../include
# distutils: library_dirs = ../../src
# distutils: libraries = opendht gnutls
# cython: language_level=3
#
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Author(s): Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
# Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
# This wrapper is written for Cython 0.22
#
# This file is part of OpenDHT Python Wrapper.
#
# OpenDHT Python Wrapper is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenDHT Python Wrapper is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenDHT Python Wrapper. If not, see <http://www.gnu.org/licenses/>.
# Copyright (c) 2014-2026 Savoir-faire Linux Inc.
# SPDX-License-Identifier: MIT
from libcpp.map cimport map as map
from libcpp cimport bool
from libcpp.utility cimport pair
from libcpp.string cimport string
from libcpp.memory cimport shared_ptr
from cython.parallel import parallel, prange
from cython.operator cimport dereference as deref, preincrement as inc, predecrement as dec
from cpython cimport ref
from datetime import timedelta
cimport opendht_cpp as cpp
import threading
cdef inline void shutdown_callback(void* user_data) with gil:
cdef inline void _initialize_gnutls():
cdef int err = cpp.gnutls_global_init()
if err != 0:
print(f"Failed to initialize GnuTLS: {cpp.gnutls_strerror(err).decode()}")
else:
import atexit
atexit.register(_deinitialize_gnutls)
cdef inline _deinitialize_gnutls():
cpp.gnutls_global_deinit()
# Initialize GnuTLS when this module is imported
_initialize_gnutls()
def version() -> str:
return cpp.version().decode()
cdef inline void lookup_callback(cpp.vector[cpp.shared_ptr[cpp.IndexValue]]* values, cpp.Prefix* p, void *user_data) noexcept with gil:
cbs = <object>user_data
if 'lookup' in cbs and cbs['lookup']:
vals = []
for val in deref(values):
v = IndexValue()
v._value = val
vals.append(v)
cbs['lookup'](vals, p.toString())
cdef inline void shutdown_callback(void* user_data) noexcept with gil:
cbs = <object>user_data
if 'shutdown' in cbs and cbs['shutdown']:
cbs['shutdown']()
ref.Py_DECREF(cbs)
cdef inline bool get_callback(cpp.shared_ptr[cpp.Value] value, void *user_data) with gil:
cb = (<object>user_data)['get']
cdef inline bool get_callback(shared_ptr[cpp.Value] value, void *user_data) noexcept with gil:
cbs = <object>user_data
cb = cbs['get']
f = cbs['filter'] if 'filter' in cbs else None
pv = Value()
pv._value = value
return cb(pv)
return cb(pv) if not f or f(pv) else True
cdef inline void done_callback(bool done, cpp.vector[cpp.shared_ptr[cpp.Node]]* nodes, void *user_data) with gil:
cdef inline bool value_callback(shared_ptr[cpp.Value] value, bool expired, void *user_data) noexcept with gil:
cbs = <object>user_data
cb = cbs['valcb']
f = cbs['filter'] if 'filter' in cbs else None
pv = Value()
pv._value = value
return cb(pv, expired) if not f or f(pv) else True
cdef inline void done_callback(bool done, cpp.vector[shared_ptr[cpp.Node]]* nodes, void *user_data) noexcept with gil:
node_ids = []
for n in deref(nodes):
h = NodeEntry()
@@ -64,18 +83,30 @@ cdef inline void done_callback(bool done, cpp.vector[cpp.shared_ptr[cpp.Node]]*
cbs['done'](done, node_ids)
ref.Py_DECREF(cbs)
cdef inline void done_callback_simple(bool done, void *user_data) noexcept with gil:
cbs = <object>user_data
if 'done' in cbs and cbs['done']:
cbs['done'](done)
ref.Py_DECREF(cbs)
cdef class _WithID(object):
def __repr__(self):
return "<%s '%s'>" % (self.__class__.__name__, str(self))
def __str__(self):
return self.getId().toString().decode()
cdef class _WithPk(object):
def __repr__(self):
return "<%s '%s'>" % (self.__class__.__name__, str(self))
def __str__(self):
return self.getLongId().toString().decode()
cdef class InfoHash(_WithID):
cdef cpp.InfoHash _infohash
def __init__(self, bytes str=b''):
self._infohash = cpp.InfoHash(str)
def __cinit__(self, bytes str=b''):
self._infohash = cpp.InfoHash(str) if str else cpp.InfoHash()
def __bool__(InfoHash self):
return not (self._infohash == cpp.InfoHash())
return <bool>self._infohash
def __richcmp__(InfoHash self, InfoHash other, int op):
if op == 0:
return self._infohash < other._infohash
@@ -95,21 +126,91 @@ cdef class InfoHash(_WithID):
def toFloat(InfoHash self):
return self._infohash.toFloat()
@staticmethod
def commonBits(InfoHash a, InfoHash b):
def commonBits(InfoHash a, InfoHash b) -> int:
return cpp.InfoHash.commonBits(a._infohash, b._infohash)
@staticmethod
def get(str key):
def get(str key) -> InfoHash:
h = InfoHash()
h._infohash = cpp.InfoHash.get(key.encode())
return h
@staticmethod
def getRandom():
def getRandom() -> InfoHash:
h = InfoHash()
h._infohash = cpp.InfoHash.getRandom()
return h
cdef class PkId(_WithPk):
cdef cpp.PkId _pkid
def __cinit__(self, bytes str=b''):
self._pkid = cpp.PkId(str) if str else cpp.PkId()
def __bool__(PkId self):
return <bool>self._pkid
def __richcmp__(PkId self, PkId other, int op):
if op == 0:
return self._pkid < other._pkid
if op == 1:
return self._pkid < other._pkid or self._pkid == other._pkid
if op == 2:
return self._pkid == other._pkid
return NotImplemented
def getBit(PkId self, bit):
return self._pkid.getBit(bit)
def setBit(PkId self, bit, b):
self._pkid.setBit(bit, b)
def getLongId(PkId self):
return self
def toString(PkId self):
return self._pkid.toString()
def toFloat(PkId self) -> float:
return self._pkid.toFloat()
@staticmethod
def commonBits(PkId a, PkId b) -> int:
return cpp.PkId.commonBits(a._pkid, b._pkid)
@staticmethod
def get(str key) -> PkId:
h = PkId()
h._pkid = cpp.PkId.get(key.encode())
return h
@staticmethod
def getRandom() -> PkId:
h = PkId()
h._pkid = cpp.PkId.getRandom()
return h
cdef class SockAddr(object):
cdef cpp.SockAddr _addr
def toString(SockAddr self):
return self._addr.toString()
def getPort(SockAddr self):
return self._addr.getPort()
def getFamily(SockAddr self):
return self._addr.getFamily()
def setPort(SockAddr self, cpp.in_port_t port):
return self._addr.setPort(port)
def setFamily(SockAddr self, cpp.sa_family_t af):
return self._addr.setFamily(af)
def isLoopback(SockAddr self):
return self._addr.isLoopback()
def isPrivate(SockAddr self):
return self._addr.isPrivate()
def isUnspecified(SockAddr self):
return self._addr.isUnspecified()
def __str__(self):
return self.toString().decode()
def __repr__(self):
return "<%s '%s'>" % (self.__class__.__name__, str(self))
@staticmethod
def resolve(str host, str service=None):
vals = []
result = cpp.SockAddr.resolve(host.encode(), service.encode() if service else b'')
for val in result:
a = SockAddr()
a._addr = val
vals.append(a)
return vals
cdef class Node(_WithID):
cdef cpp.shared_ptr[cpp.Node] _node
cdef shared_ptr[cpp.Node] _node
def getId(self):
h = InfoHash()
h._infohash = self._node.get().getId()
@@ -120,7 +221,7 @@ cdef class Node(_WithID):
return self._node.get().isExpired()
cdef class NodeEntry(_WithID):
cdef cpp.pair[cpp.InfoHash, cpp.shared_ptr[cpp.Node]] _v
cdef cpp.pair[cpp.InfoHash, shared_ptr[cpp.Node]] _v
def getId(self):
h = InfoHash()
h._infohash = self._v.first
@@ -130,41 +231,113 @@ cdef class NodeEntry(_WithID):
n._node = self._v.second
return n
cdef class Query(object):
cdef cpp.Query _query
def __cinit__(self, str q_str=''):
self._query = cpp.Query(q_str.encode())
def __str__(self):
return self._query.toString().decode()
def buildFrom(self, Select s, Where w):
self._query = cpp.Query(s._select, w._where)
def isSatisfiedBy(self, Query q):
return self._query.isSatisfiedBy(q._query)
cdef class Select(object):
cdef cpp.Select _select
def __cinit__(self, str q_str=None):
if q_str:
self._select = cpp.Select(q_str.encode())
else:
self._select = cpp.Select()
def __str__(self):
return self._select.toString().decode()
def isSatisfiedBy(self, Select os):
return self._select.isSatisfiedBy(os._select)
def field(self, int field):
self._select.field(<cpp.Field> field)
return self
cdef class Where(object):
cdef cpp.Where _where
def __cinit__(self, str q_str=None):
if q_str:
self._where = cpp.Where(q_str.encode())
else:
self._where = cpp.Where()
def __str__(self):
return self._where.toString().decode()
def isSatisfiedBy(self, Where where) -> bool:
return self._where.isSatisfiedBy(where._where)
def id(self, cpp.uint64_t id):
self._where.id(id)
return self
def valueType(self, cpp.uint16_t type):
self._where.valueType(type)
return self
def owner(self, InfoHash owner_pk_hash):
self._where.owner(owner_pk_hash._infohash)
return self
def seq(self, cpp.uint16_t seq_no):
self._where.seq(seq_no)
return self
def userType(self, str user_type):
self._where.userType(user_type.encode())
return self
cdef class Value(object):
cdef cpp.shared_ptr[cpp.Value] _value
def __init__(self, bytes val=b''):
self._value.reset(new cpp.Value(val, len(val)))
cdef shared_ptr[cpp.Value] _value
def __init__(self, bytes val=b'', cpp.uint16_t id=0):
self._value.reset(new cpp.Value(id, val, len(val)))
def __str__(self):
return self._value.get().toString().decode()
property owner:
def __get__(self):
h = InfoHash()
h._infohash = self._value.get().owner.get().getId()
return h
property recipient:
def __get__(self):
h = InfoHash()
h._infohash = self._value.get().recipient
return h
def __set__(self, InfoHash h):
self._value.get().recipient = h._infohash
property data:
def __get__(self):
return string(<char*>self._value.get().data.data(), self._value.get().data.size())
def __set__(self, bytes value):
self._value.get().data = value
property id:
def __get__(self):
return self._value.get().id
def __set__(self, cpp.uint64_t value):
self._value.get().id = value
property size:
def __get__(self):
return self._value.get().size()
@property
def owner(self) -> PublicKey:
h = PublicKey()
h._key = self._value.get().owner
return h
@property
def recipient(self) -> InfoHash:
h = InfoHash()
h._infohash = self._value.get().recipient
return h
@recipient.setter
def recipient(self, InfoHash h):
self._value.get().recipient = h._infohash
@property
def data(self) -> bytes:
cdef char* data_ptr = <char*>self._value.get().data.data()
cdef int data_size = self._value.get().data.size()
return data_ptr[:data_size]
@data.setter
def data(self, bytes value):
self._value.get().data = value
@property
def user_type(self) -> str:
return self._value.get().user_type.decode()
@user_type.setter
def user_type(self, str t):
self._value.get().user_type = t.encode()
@property
def id(self):
return self._value.get().id
@id.setter
def id(self, cpp.uint64_t value):
self._value.get().id = value
@property
def size(self) -> int:
return self._value.get().size()
cdef class ValueType(object):
cdef cpp.ValueType * _value
def __init__(self, cpp.uint16_t id, str name, expiration: timedelta):
if not isinstance(expiration, timedelta):
raise TypeError("expiration argument must be of type timedelta")
cdef cpp.seconds duration = cpp.seconds(int(expiration.total_seconds()))
self._value = new cpp.ValueType(id, name.encode(), duration)
cdef class NodeSetIter(object):
cdef map[cpp.InfoHash, cpp.shared_ptr[cpp.Node]]* _nodes
cdef map[cpp.InfoHash, cpp.shared_ptr[cpp.Node]].iterator _curIter
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]]* _nodes
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]].iterator _curIter
def __init__(self, NodeSet s):
self._nodes = &s._nodes
self._curIter = self._nodes.begin()
@@ -177,11 +350,11 @@ cdef class NodeSetIter(object):
return h
cdef class NodeSet(object):
cdef map[cpp.InfoHash, cpp.shared_ptr[cpp.Node]] _nodes
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]] _nodes
def size(self):
return self._nodes.size()
def insert(self, NodeEntry l):
self._nodes.insert(l._v)
return self._nodes.insert(l._v).second
def extend(self, li):
for n in li:
self.insert(n)
@@ -199,7 +372,7 @@ cdef class NodeSet(object):
return h
def __str__(self):
s = ''
cdef map[cpp.InfoHash, cpp.shared_ptr[cpp.Node]].iterator it = self._nodes.begin()
cdef map[cpp.InfoHash, shared_ptr[cpp.Node]].iterator it = self._nodes.begin()
while it != self._nodes.end():
s += deref(it).first.toString().decode() + ' ' + deref(it).second.get().getAddrStr().decode() + '\n'
inc(it)
@@ -207,19 +380,161 @@ cdef class NodeSet(object):
def __iter__(self):
return NodeSetIter(self)
cdef class PublicKey(_WithID):
cdef cpp.PublicKey _key
def getId(self):
cdef class PrivateKey(_WithPk):
cdef shared_ptr[cpp.PrivateKey] _key
def getId(self) -> InfoHash:
if not self._key:
raise ValueError("PrivateKey is not initialized")
h = InfoHash()
h._infohash = self._key.getId()
h._infohash = self._key.get().getSharedPublicKey().get().getId()
return h
cdef class Certificate(_WithID):
cdef cpp.shared_ptr[cpp.Certificate] _cert
def getId(self):
def getLongId(self) -> PkId:
if not self._key:
raise ValueError("PrivateKey is not initialized")
id = PkId()
id._pkid = self._key.get().getSharedPublicKey().get().getLongId()
return id
def getPublicKey(self) -> PublicKey:
if not self._key:
raise ValueError("PrivateKey is not initialized")
pk = PublicKey()
pk._key = self._key.get().getSharedPublicKey()
return pk
def decrypt(self, bytes dat) -> bytes:
cdef size_t d_len = len(dat)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef cpp.Blob decrypted = self._key.get().decrypt(indat)
cdef char* decrypted_c_str = <char *>decrypted.data()
cdef Py_ssize_t length = decrypted.size()
return decrypted_c_str[:length]
def sign(self, bytes dat) -> bytes:
if not self._key:
raise ValueError("PrivateKey is not initialized")
cdef size_t d_len = len(dat)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef cpp.Blob signature = self._key.get().sign(indat)
cdef char* signature_c_str = <char *>signature.data()
cdef Py_ssize_t length = signature.size()
return signature_c_str[:length]
@staticmethod
def generate() -> PrivateKey:
k = PrivateKey()
k._key = cpp.make_shared[cpp.PrivateKey](cpp.PrivateKey.generate())
return k
@staticmethod
def generateEC() -> PrivateKey:
k = PrivateKey()
k._key = cpp.make_shared[cpp.PrivateKey](cpp.PrivateKey.generateEC())
return k
cdef class PublicKey(_WithPk):
cdef cpp.shared_ptr[cpp.PublicKey] _key
def getId(self) -> InfoHash:
if not self._key:
raise ValueError("PublicKey is not initialized")
h = InfoHash()
h._infohash = self._key.get().getId()
return h
def getLongId(self) -> PkId:
if not self._key:
raise ValueError("PublicKey is not initialized")
id = PkId()
id._pkid = self._key.get().getLongId()
return id
def encrypt(self, bytes dat) -> bytes:
if not self._key:
raise ValueError("PublicKey is not initialized")
cdef size_t d_len = len(dat)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef cpp.Blob encrypted = self._key.get().encrypt(indat)
cdef char* encrypted_c_str = <char *>encrypted.data()
cdef Py_ssize_t length = encrypted.size()
return encrypted_c_str[:length]
def checkSignature(self, bytes dat, bytes signature) -> bool:
if not self._key:
raise ValueError("PublicKey is not initialized")
cdef size_t d_len = len(dat)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>dat
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef size_t s_len = len(signature)
cdef cpp.uint8_t* s_ptr = <cpp.uint8_t*>signature
cdef cpp.Blob sig
sig.assign(s_ptr, <cpp.uint8_t*>(s_ptr + s_len))
return self._key.get().checkSignature(indat, sig)
cdef class Certificate(_WithPk):
cdef shared_ptr[cpp.Certificate] _cert
def __init__(self, bytes dat = None):
if dat:
self._cert = cpp.make_shared[cpp.Certificate](<cpp.string>dat)
def getId(self) -> InfoHash:
if not self._cert:
raise ValueError("Certificate is not initialized")
h = InfoHash()
h._infohash = self._cert.get().getId()
return h
def getLongId(self) -> PkId:
if not self._cert:
raise ValueError("Certificate is not initialized")
id = PkId()
id._pkid = self._cert.get().getLongId()
return id
def toString(self) -> str:
if not self._cert:
return ""
return self._cert.get().toString().decode()
def getName(self) -> str:
return self._cert.get().getName().decode()
def revoke(self, PrivateKey k, Certificate c):
self._cert.get().revoke(deref(k._key.get()), deref(c._cert.get()));
def __bytes__(self):
return self._cert.get().toString().encode() if self._cert else b''
@property
def issuer(self) -> Certificate|None:
if self._cert and self._cert.get().issuer:
c = Certificate()
c._cert = self._cert.get().issuer
return c
return None
@staticmethod
def generate(PrivateKey k, str name, Identity i = Identity(), bool is_ca = False):
c = Certificate()
c._cert = cpp.make_shared[cpp.Certificate](cpp.Certificate.generate(deref(k._key.get()), name.encode(), i._id, is_ca))
return c
cdef class VerifyResult(object):
cdef cpp.TrustListVerifyResult _result
def __bool__(self):
return self._result.isValid()
def __str(self):
return self._result.toString()
cdef class TrustList(object):
cdef cpp.TrustList _trust
def add(self, Certificate cert):
self._trust.add(deref(cert._cert.get()))
def remove(self, Certificate cert):
self._trust.remove(deref(cert._cert.get()))
def verify(self, Certificate cert):
r = VerifyResult()
r._result = self._trust.verify(deref(cert._cert.get()))
return r
cdef class ListenToken(object):
cdef cpp.InfoHash _h
@@ -228,90 +543,196 @@ cdef class ListenToken(object):
cdef class Identity(object):
cdef cpp.Identity _id
def generate(self, str name = "pydht", Identity ca = Identity(), unsigned bits = 4096):
self._id = cpp.generateIdentity(name.encode(), ca._id, bits)
property PublicKey:
def __get__(self):
k = PublicKey()
k._key = self._id.first.get().getPublicKey()
return k
property Certificate:
def __get__(self):
c = Certificate()
c._cert = self._id.second
return c
def __init__(self, PrivateKey k = None, Certificate c = None):
if k:
self._id.first = k._key
if c:
self._id.second = c._cert
@staticmethod
def generate(str name = "pydht", Identity ca = Identity(), unsigned bits = 4096):
i = Identity()
i._id = cpp.generateIdentity(name.encode(), ca._id, bits)
return i
@property
def publickey(self) -> PublicKey|None:
if not self._id.first:
return None
k = PublicKey()
k._key = self._id.first.get().getSharedPublicKey()
return k
@property
def certificate(self) -> Certificate|None:
if not self._id.second:
return None
c = Certificate()
c._cert = self._id.second
return c
@property
def key(self) -> PrivateKey|None:
if not self._id.first:
return None
k = PrivateKey()
k._key = self._id.first
return k
def aesEncrypt(bytes data, str password) -> bytes :
cdef size_t d_len = len(data)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>data
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef cpp.Blob encrypted = cpp.aesEncrypt(indat, password.encode())
cdef char* encrypted_c_str = <char *>encrypted.data()
cdef Py_ssize_t length = encrypted.size()
return encrypted_c_str[:length]
def aesDecrypt(bytes data, str password) -> bytes :
cdef size_t d_len = len(data)
cdef cpp.uint8_t* d_ptr = <cpp.uint8_t*>data
cdef cpp.Blob indat
indat.assign(d_ptr, <cpp.uint8_t*>(d_ptr + d_len))
cdef cpp.Blob decrypted = cpp.aesDecrypt(indat, password.encode())
cdef char* decrypted_c_str = <char *>decrypted.data()
cdef Py_ssize_t length = decrypted.size()
return decrypted_c_str[:length]
cdef class DhtConfig(object):
cdef cpp.DhtRunnerConfig _config
def __init__(self):
self._config = cpp.DhtRunnerConfig()
self._config.threaded = True;
self._config.threaded = True
def setIdentity(self, Identity id):
self._config.dht_config.id = id._id
def setBootstrapMode(self, bool bootstrap):
self._config.dht_config.node_config.is_bootstrap = bootstrap
def setNodeId(self, InfoHash id):
self._config.dht_config.node_config.node_id = id._infohash
def setNetwork(self, unsigned netid):
self._config.dht_config.node_config.network = netid
def setMaintainStorage(self, bool maintain_storage):
self._config.dht_config.node_config.maintain_storage = maintain_storage
def setRateLimit(self, ssize_t max_req_per_sec, ssize_t max_peer_req_per_sec):
self._config.dht_config.node_config.max_req_per_sec = max_req_per_sec
self._config.dht_config.node_config.max_peer_req_per_sec = max_peer_req_per_sec
def setProxyInfo(self, str proxy_server, str push_node_id="", str push_token="", str push_topic="", str push_platform="", str user_agent="", Certificate server_ca = Certificate()):
self._config.proxy_server = proxy_server.encode()
self._config.push_node_id = push_node_id.encode()
self._config.push_token = push_token.encode()
self._config.push_topic = push_topic.encode()
self._config.push_platform = push_platform.encode()
self._config.proxy_user_agent = user_agent.encode()
self._config.server_ca = server_ca._cert
def setPeerDiscovery(self, bool peer_discovery, bool peer_publish):
self._config.peer_discovery = peer_discovery
self._config.peer_publish = peer_publish
def setBound(self, SockAddr bind4, SockAddr bind6):
self._config.bind4 = bind4._addr
self._config.bind6 = bind6._addr
cdef class DhtRunner(_WithID):
cdef cpp.DhtRunner* thisptr
cdef cpp.shared_ptr[cpp.DhtRunner] thisptr
def __cinit__(self):
self.thisptr = new cpp.DhtRunner()
def getId(self):
self.thisptr.reset(new cpp.DhtRunner())
def getId(self) -> InfoHash:
h = InfoHash()
h._infohash = self.thisptr.getId()
if self.thisptr:
h._infohash = self.thisptr.get().getId()
return h
def getNodeId(self):
return self.thisptr.getNodeId().toString()
def bootstrap(self, str host, str port):
self.thisptr.bootstrap(host.encode(), port.encode())
def getPublicKey(self) -> PublicKey:
if not self.thisptr:
raise ValueError("DhtRunner is not initialized")
pk = PublicKey()
pk._key = self.thisptr.get().getPublicKey()
return pk
def getNodeId(self) -> InfoHash:
h = InfoHash()
if self.thisptr:
h._infohash = self.thisptr.get().getNodeId()
return h
def ping(self, SockAddr addr, done_cb=None):
if done_cb:
cb_obj = {'done':done_cb}
ref.Py_INCREF(cb_obj)
self.thisptr.get().bootstrap(addr._addr, cpp.bindDoneCbSimple(done_callback_simple, <void*>cb_obj))
else:
lock = threading.Condition()
pending = 0
ok = False
def tmp_done(ok_ret):
nonlocal pending, ok, lock
with lock:
ok = ok_ret
pending -= 1
lock.notify()
with lock:
pending += 1
self.ping(addr, done_cb=tmp_done)
while pending > 0:
lock.wait()
return ok
def bootstrap(self, str host, str port=None):
host_bytes = host.encode()
port_bytes = port.encode() if port else b'4222'
self.thisptr.get().bootstrap(<cpp.const_char*>host_bytes, <cpp.const_char*>port_bytes)
def run(self, Identity id=None, is_bootstrap=False, cpp.in_port_t port=0, str ipv4="", str ipv6="", DhtConfig config=DhtConfig()):
if id:
config.setIdentity(id)
if ipv4 or ipv6:
bind4 = ipv4.encode() if ipv4 else b''
bind6 = ipv6.encode() if ipv6 else b''
self.thisptr.run(bind4, bind6, str(port).encode(), config._config)
self.thisptr.get().run(bind4, bind6, str(port).encode(), config._config)
else:
self.thisptr.run(port, config._config)
self.thisptr.get().run(port, config._config)
def join(self):
self.thisptr.join()
self.thisptr.get().join()
def shutdown(self, shutdown_cb=None):
cb_obj = {'shutdown':shutdown_cb}
ref.Py_INCREF(cb_obj)
self.thisptr.shutdown(cpp.bindShutdownCb(shutdown_callback, <void*>cb_obj))
self.thisptr.get().shutdown(cpp.bindShutdownCb(shutdown_callback, <void*>cb_obj))
def registerType(self, ValueType type):
self.thisptr.get().registerType(deref(type._value))
def enableLogging(self):
cpp.enableLogging(self.thisptr[0])
cpp.enableLogging(self.thisptr.get()[0])
def disableLogging(self):
cpp.disableLogging(self.thisptr[0])
cpp.disableLogging(self.thisptr.get()[0])
def enableFileLogging(self, str path):
cpp.enableFileLogging(self.thisptr[0], path)
cpp.enableFileLogging(self.thisptr.get()[0], path.encode())
def isRunning(self):
return self.thisptr.isRunning()
return self.thisptr.get().isRunning()
def getBound(self, cpp.sa_family_t af = 0):
s = SockAddr()
s._addr = self.thisptr.get().getBound(af)
return s
def getStorageLog(self):
return self.thisptr.getStorageLog().decode()
return self.thisptr.get().getStorageLog().decode()
def getRoutingTablesLog(self, cpp.sa_family_t af):
return self.thisptr.getRoutingTablesLog(af).decode()
return self.thisptr.get().getRoutingTablesLog(af).decode()
def getSearchesLog(self, cpp.sa_family_t af):
return self.thisptr.getSearchesLog(af).decode()
return self.thisptr.get().getSearchesLog(af).decode()
def getNodeMessageStats(self):
stats = []
cdef cpp.vector[unsigned] res = self.thisptr.getNodeMessageStats(False)
cdef cpp.vector[unsigned] res = self.thisptr.get().getNodeMessageStats(False)
for n in res:
stats.append(n)
return stats
def get(self, InfoHash key, get_cb=None, done_cb=None):
def get(self, InfoHash key, get_cb=None, done_cb=None, filter=None, Where where=None):
"""Retreive values associated with a key on the DHT.
key -- the key for which to search
get_cb -- is set, makes the operation non-blocking. Called when a value is found on the DHT.
done_cb -- optional callback used when get_cb is set. Called when the operation is completed.
key -- the key for which to search
get_cb -- is set, makes the operation non-blocking. Called when a value
is found on the DHT.
done_cb -- optional callback used when get_cb is set. Called when the
operation is completed.
"""
if get_cb:
cb_obj = {'get':get_cb, 'done':done_cb}
cb_obj = {'get':get_cb, 'done':done_cb, 'filter':filter}
ref.Py_INCREF(cb_obj)
self.thisptr.get(key._infohash, cpp.bindGetCb(get_callback, <void*>cb_obj), cpp.bindDoneCb(done_callback, <void*>cb_obj))
if where is None:
where = Where()
self.thisptr.get().get(key._infohash, cpp.bindGetCb(get_callback, <void*>cb_obj),
cpp.bindDoneCb(done_callback, <void*>cb_obj),
cpp.nullptr, #filter implemented in the get_callback
where._where)
else:
lock = threading.Condition()
pending = 0
@@ -327,21 +748,22 @@ cdef class DhtRunner(_WithID):
lock.notify()
with lock:
pending += 1
self.get(key, get_cb=tmp_get, done_cb=tmp_done)
self.get(key, get_cb=tmp_get, done_cb=tmp_done, filter=filter, where=where)
while pending > 0:
lock.wait()
return res
def put(self, InfoHash key, Value val, done_cb=None):
def put(self, InfoHash key, Value val, done_cb=None, permanent=False):
"""Publish a new value on the DHT at key.
key -- the DHT key where to put the value
val -- the value to put on the DHT
key -- the DHT key where to put the value
val -- the value to put on the DHT
done_cb -- optional callback called when the operation is completed.
"""
if done_cb:
cb_obj = {'done':done_cb}
ref.Py_INCREF(cb_obj)
self.thisptr.put(key._infohash, val._value, cpp.bindDoneCb(done_callback, <void*>cb_obj))
self.thisptr.get().put(key._infohash, val._value, cpp.bindDoneCb(done_callback, <void*>cb_obj), cpp.time_point.max(), permanent)
else:
lock = threading.Condition()
pending = 0
@@ -358,16 +780,150 @@ cdef class DhtRunner(_WithID):
while pending > 0:
lock.wait()
return ok
def listen(self, InfoHash key, get_cb):
def putSigned(self, InfoHash key, Value val, done_cb=None, permanent=False):
if done_cb:
cb_obj = {'done':done_cb}
ref.Py_INCREF(cb_obj)
self.thisptr.get().putSigned(key._infohash, val._value, cpp.bindDoneCb(done_callback, <void*>cb_obj), permanent)
else:
lock = threading.Condition()
pending = 0
ok = False
def tmp_done(ok_ret, nodes):
nonlocal pending, ok, lock
with lock:
ok = ok_ret
pending -= 1
lock.notify()
with lock:
pending += 1
self.putSigned(key, val, done_cb=tmp_done)
while pending > 0:
lock.wait()
return ok
def putEncrypted(self, InfoHash key, Value val, to, done_cb=None, bool permanent=False):
if to is None:
raise ValueError("'to' must be provided")
if done_cb:
cb_obj = {'done':done_cb}
ref.Py_INCREF(cb_obj)
try:
if isinstance(to, PublicKey):
self.thisptr.get().putEncrypted(
key._infohash, (<PublicKey>to)._key, val._value,
cpp.bindDoneCb(done_callback, <void*>cb_obj), permanent
)
elif isinstance(to, PkId):
self.thisptr.get().putEncrypted(
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")
except:
ref.Py_DECREF(cb_obj)
raise
else:
lock = threading.Condition()
pending = 0
ok = False
def tmp_done(ok_ret, nodes):
nonlocal pending, ok, lock
with lock:
ok = ok_ret
pending -= 1
lock.notify()
with lock:
pending += 1
self.putEncrypted(key, val, to=to, done_cb=tmp_done, permanent=permanent)
while pending > 0:
lock.wait()
return ok
def cancelPut(self, InfoHash key, Value val):
self.thisptr.get().cancelPut(key._infohash, val._value)
def listen(self, InfoHash key, value_cb):
t = ListenToken()
t._h = key._infohash
cb_obj = {'get':get_cb}
cb_obj = {'valcb':value_cb}
t._cb['cb'] = cb_obj
# avoid the callback being destructed if the token is destroyed
ref.Py_INCREF(cb_obj)
t._t = self.thisptr.listen(t._h, cpp.bindGetCb(get_callback, <void*>cb_obj)).share()
t._t = self.thisptr.get().listen(t._h, cpp.bindValueCb(value_callback, <void*>cb_obj)).share()
return t
def cancelListen(self, ListenToken token):
self.thisptr.cancelListen(token._h, token._t)
self.thisptr.get().cancelListen(token._h, token._t)
ref.Py_DECREF(<object>token._cb['cb'])
# fixme: not thread safe
cdef class IndexValue(object):
cdef cpp.shared_ptr[cpp.IndexValue] _value
def __init__(self, InfoHash h=None, cpp.uint64_t vid=0):
cdef cpp.InfoHash hh = h._infohash
self._value.reset(new cpp.IndexValue(hh, vid))
def __str__(self):
return "(" + self.getKey().toString().decode() +", "+ str(self.getValueId()) +")"
def getKey(self):
h = InfoHash()
h._infohash = self._value.get().first
return h
def getValueId(self):
return self._value.get().second
cdef class Pht(object):
cdef cpp.Pht* thisptr
def __cinit__(self, bytes name, key_spec, DhtRunner dht):
cdef cpp.IndexKeySpec cpp_key_spec
for kk, size in key_spec.items():
cpp_key_spec[bytes(kk, 'utf-8')] = size
self.thisptr = new cpp.Pht(name, cpp_key_spec, dht.thisptr)
@property
def MAX_NODE_ENTRY_COUNT(self):
return cpp.PHT_MAX_NODE_ENTRY_COUNT
def lookup(self, key, lookup_cb=None, done_cb=None):
"""Query the Index with a specified key.
key -- the key for to the entry in the index.
lookup_cb -- function called when the operation is completed. This
function takes a list of IndexValue objects and a string
representation of the prefix where the value was indexed in
the PHT.
"""
cb_obj = {'lookup':lookup_cb, 'done':done_cb} # TODO: donecallback is to be removed
ref.Py_INCREF(cb_obj)
cdef cpp.IndexKey cppk
for kk, v in key.items():
cppk[bytes(kk, 'utf-8')] = bytes(v)
self.thisptr.lookup(
cppk,
cpp.Pht.bindLookupCb(lookup_callback, <void*>cb_obj),
cpp.bindDoneCbSimple(done_callback_simple, <void*>cb_obj)
)
def insert(self, key, IndexValue value, done_cb=None):
"""Add an index entry to the Index.
key -- the key for to the entry in the index.
value -- an IndexValue object describing the indexed value.
done_cb -- Called when the operation is completed.
"""
cb_obj = {'done':done_cb}
ref.Py_INCREF(cb_obj)
cdef cpp.IndexKey cppk
for kk, v in key.items():
cppk[bytes(kk, 'utf-8')] = bytes(v)
cdef cpp.IndexValue val
val.first = (<InfoHash>value.getKey())._infohash
val.second = value.getValueId()
self.thisptr.insert(
cppk,
val,
cpp.bindDoneCbSimple(done_callback_simple, <void*>cb_obj)
)
+12
View File
@@ -0,0 +1,12 @@
"""
Python package facade for OpenDHT.
This package re-exports the Cython-built core bindings from ``opendht._core``
to preserve the public API (e.g., ``opendht.DhtRunner``), and also exposes a
pure-Python asyncio-friendly wrapper under ``opendht.aio``.
"""
from ._core import * # re-export core Cython bindings
__version__ = version()
__all__ = [name for name in dir() if not name.startswith("_")]
+281
View File
@@ -0,0 +1,281 @@
# Copyright (c) 2014-2026 Savoir-faire Linux Inc.
# SPDX-License-Identifier: MIT
from __future__ import annotations
import asyncio
from typing import Any, Callable, Iterable, List, Optional, Tuple
from . import _core as _dht
# Re-export core types for convenience
from ._core import InfoHash, Value, ValueType, Where, SockAddr, PublicKey, PkId, DhtConfig, Identity
class _Listener:
"""Async iterator around DHT listen callback.
Yields tuples (Value, expired: bool).
"""
__slots__ = ("_runner", "_token", "_loop", "_queue", "_closed")
def __init__(self, runner: DhtRunner, key: InfoHash) -> None:
self._runner = runner
self._loop = runner._loop
self._queue: asyncio.Queue[Tuple[Value, bool]] = asyncio.Queue()
self._closed = False
def _on_value(v: Value, expired: bool) -> bool:
if self._closed:
return False
self._loop.call_soon_threadsafe(self._queue.put_nowait, (v, expired))
return True # continue listening
self._token = self._runner._dht.listen(key, _on_value)
def __enter__(self) -> _Listener:
return self
def __exit__(self, exc_type, exc, tb) -> None:
self.cancel()
def __aiter__(self) -> _Listener:
return self
async def __anext__(self) -> Tuple[Value, bool]:
if self._closed:
raise StopAsyncIteration
item = await self._queue.get()
if item is None:
self._closed = True
raise StopAsyncIteration
return item
def cancel(self) -> None:
if self._closed:
return
self._closed = True
try:
self._runner._dht.cancelListen(self._token)
finally:
# Unblock any pending __anext__
self._queue.put_nowait(None)
class _GetStream:
"""Async iterator around DHT get callback.
Yields Value instances as they are found, then ends.
Raises on failure.
"""
__slots__ = ("_runner", "_loop", "_queue", "_closed", "_error")
def __init__(
self,
runner: DhtRunner,
key: InfoHash,
where: Optional[Where],
filter: Optional[Callable[[Value], bool]],
) -> None:
self._runner = runner
self._loop = runner._loop
self._queue: asyncio.Queue[Optional[Value]] = asyncio.Queue()
self._closed = False
self._error: Optional[BaseException] = None
def _on_value(v: Value) -> bool:
# Called on DHT thread
if self._closed:
return False
self._loop.call_soon_threadsafe(self._queue.put_nowait, v)
return True
def _on_done(ok: bool, _nodes: Iterable[Any]) -> None:
# Called on DHT thread
if self._closed:
return
if not ok:
self._error = RuntimeError("DHT get failed")
self._loop.call_soon_threadsafe(self._queue.put_nowait, None)
self._runner._dht.get(key, _on_value, _on_done, filter, where)
def __enter__(self) -> _GetStream:
return self
def __exit__(self, exc_type, exc, tb) -> None:
self.cancel()
def __aiter__(self) -> _GetStream:
return self
async def __anext__(self) -> Value:
if self._closed:
raise StopAsyncIteration
item = await self._queue.get()
if item is None:
self._closed = True
if self._error is not None:
raise self._error
raise StopAsyncIteration
return item
def cancel(self) -> None:
if self._closed:
return
self._closed = True
# Unblock any pending __anext__
self._queue.put_nowait(None)
class DhtRunner:
"""Async wrapper around opendht.DhtRunner.
"""
__slots__ = ("_dht", "_loop", "_config", "_bootstrap")
def __init__(
self,
*,
loop: Optional[asyncio.AbstractEventLoop] = None,
core: Optional[_dht.DhtRunner] = None,
config: Optional[DhtConfig] = None,
bootstrap: Optional[Iterable[Tuple[str, Optional[str]]]] = None,
) -> None:
try:
self._loop = loop or asyncio.get_running_loop()
except RuntimeError:
self._loop = asyncio.get_event_loop()
self._dht = core or _dht.DhtRunner()
self._config = config
self._bootstrap = list(bootstrap) if bootstrap is not None else None
def run(
self,
id: Optional[Identity] = None,
is_bootstrap: bool = False,
port: int = 0,
ipv4: str = "",
ipv6: str = "",
config: Optional[DhtConfig] = None,
) -> None:
cfg = config or self._config or DhtConfig()
self._dht.run(id, is_bootstrap, port, ipv4, ipv6, cfg)
if self._bootstrap:
for host, port_str in self._bootstrap:
self._dht.bootstrap(host, port_str)
def bootstrap(self, host: str, port: Optional[str] = None) -> None:
self._dht.bootstrap(host, port)
async def ping(self, addr: SockAddr) -> bool:
fut: asyncio.Future[bool] = self._loop.create_future()
self._dht.ping(addr, lambda ok: self._loop.call_soon_threadsafe(fut.set_result, bool(ok)))
return await fut
def get(
self,
key: InfoHash,
*,
where: Optional[Where] = None,
filter: Optional[Callable[[Value], bool]] = None,
):
# Return a streaming iterator of values; it ends on completion and raises on failure.
return _GetStream(self, key, where, filter)
async def getAll(
self,
key: InfoHash,
*,
where: Optional[Where] = None,
filter: Optional[Callable[[Value], bool]] = None,
) -> List[Value]:
"""Collect all values for a key and return them as a list."""
results: List[Value] = []
async for v in self.get(key, where=where, filter=filter):
results.append(v)
return results
async def getFirst(
self,
key: InfoHash,
*,
where: Optional[Where] = None,
predicate: Optional[Callable[[Value], Any]] = None,
filter: Optional[Callable[[Value], bool]] = None,
) -> Optional[Value]:
"""Return the first value matching an (optionally async) predicate, or None."""
with self.get(key, where=where, filter=filter) as stream:
async for value in stream:
if predicate is None:
return value
result = predicate(value)
if asyncio.iscoroutine(result):
result = await result
if result:
return value
return None
async def put(self, key: InfoHash, val: Value, *, permanent: bool = False) -> bool:
fut: asyncio.Future[bool] = self._loop.create_future()
def _done(ok: bool, _nodes: Iterable[Any]) -> None:
self._loop.call_soon_threadsafe(fut.set_result, bool(ok))
self._dht.put(key, val, _done, permanent)
return await fut
async def putSigned(self, key: InfoHash, val: Value, *, permanent: bool = False) -> bool:
fut: asyncio.Future[bool] = self._loop.create_future()
def _done(ok: bool, _nodes: Iterable[Any]) -> None:
self._loop.call_soon_threadsafe(fut.set_result, bool(ok))
self._dht.putSigned(key, val, _done, permanent)
return await fut
async def putEncrypted(
self,
key: InfoHash,
to: InfoHash | PublicKey | PkId,
val: Value,
*,
permanent: bool = False,
) -> bool:
fut: asyncio.Future[bool] = self._loop.create_future()
def _done(ok: bool, _nodes: Iterable[Any]) -> None:
self._loop.call_soon_threadsafe(fut.set_result, bool(ok))
self._dht.putEncrypted(key, val, to, _done, permanent)
return await fut
def listen(self, key: InfoHash) -> _Listener:
return _Listener(self, key)
async def cancelListen(self, listener: _Listener) -> None:
await listener.cancel()
async def shutdown(self) -> None:
fut: asyncio.Future[None] = self._loop.create_future()
self._dht.shutdown(lambda: self._loop.call_soon_threadsafe(fut.set_result, None))
await fut
async def join(self) -> None:
await asyncio.to_thread(self._dht.join)
async def __aenter__(self):
if not self.isRunning():
self.run()
return self
async def __aexit__(self, exc_type, exc, tb):
if self.isRunning():
try:
await self.shutdown()
finally:
await self.join()
return False
def __getattr__(self, name: str) -> Any:
return getattr(self._dht, name)
+200 -36
View File
@@ -1,35 +1,25 @@
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; If not, see <http://www.gnu.org/licenses/>.
# Copyright (c) 2014-2026 Savoir-faire Linux Inc.
# SPDX-License-Identifier: MIT
from libc.stdint cimport *
from libcpp cimport bool
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
from libcpp cimport bool, nullptr_t, nullptr
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp.utility cimport pair
from libcpp.map cimport map
from libcpp.memory cimport shared_ptr, make_shared
from libc.string cimport const_char
ctypedef uint16_t in_port_t
ctypedef unsigned short int sa_family_t;
ctypedef unsigned short int sa_family_t
cdef extern from "<memory>" namespace "std" nogil:
cdef cppclass shared_ptr[T]:
shared_ptr() except +
T* get()
T operator*()
void reset(T*)
cdef extern from "<chrono>" namespace "std::chrono" nogil:
cdef cppclass duration[ulong]:
duration() except +
cdef cppclass seconds:
duration seconds(uint64_t) except +
duration seconds()
cdef extern from "<functional>" namespace "std" nogil:
cdef cppclass hash[T]:
@@ -46,6 +36,14 @@ cdef extern from "<future>" namespace "std" nogil:
bool valid() const
shared_future[T] share()
cdef extern from "opendht/utils.h" namespace "dht":
const char* version()
cdef cppclass time_point:
@staticmethod
time_point min() const
@staticmethod
time_point max() const
cdef extern from "opendht/infohash.h" namespace "dht":
cdef cppclass InfoHash:
InfoHash() except +
@@ -60,30 +58,109 @@ cdef extern from "opendht/infohash.h" namespace "dht":
InfoHash get(string s)
@staticmethod
InfoHash getRandom()
bool operator==(InfoHash)
bool operator<(InfoHash)
bool operator==(InfoHash) const
bool operator<(InfoHash) const
bool operator bool() const
cdef cppclass PkId:
PkId() except +
PkId(string s) except +
string toString() const
bool getBit(unsigned bit) const
void setBit(unsigned bit, bool b)
double toFloat() const
@staticmethod
unsigned commonBits(PkId a, PkId b)
@staticmethod
PkId get(string s)
@staticmethod
PkId getRandom()
bool operator==(PkId) const
bool operator<(PkId) const
bool operator bool() const
cdef extern from "opendht/sockaddr.h" namespace "dht":
cdef cppclass SockAddr:
SockAddr() except +
string toString() const
in_port_t getPort() const
void setPort(in_port_t p)
sa_family_t getFamily() const
void setFamily(sa_family_t f)
bool isLoopback() const
bool isPrivate() const
bool isUnspecified() const
@staticmethod
vector[SockAddr] resolve(string host, string service) except +
ctypedef vector[uint8_t] Blob
cdef extern from "opendht/crypto.h" namespace "dht::crypto":
ctypedef pair[shared_ptr[PrivateKey], shared_ptr[Certificate]] Identity
cdef Identity generateIdentity(string name, Identity ca, unsigned bits)
cdef Blob aesEncrypt(Blob data, string password) except +
cdef Blob aesDecrypt(Blob encrypted, string password) except +
cdef cppclass PrivateKey:
PrivateKey()
PublicKey getPublicKey() const
shared_ptr[PublicKey] getSharedPublicKey() const
Blob decrypt(Blob data) const
Blob sign(Blob data) const
@staticmethod
PrivateKey generate()
@staticmethod
PrivateKey generateEC()
cdef cppclass PublicKey:
PublicKey()
InfoHash getId() const
PkId getLongId() const
Blob encrypt(Blob data) const
bool checkSignature(Blob data, Blob signature) const
bool operator==(PublicKey) const
cdef cppclass Certificate:
Certificate()
Certificate(string pem)
InfoHash getId() const
PkId getLongId() const
string toString() const
string getName() const
void revoke(PrivateKey key, Certificate cert)
@staticmethod
Certificate generate(PrivateKey key, string name, Identity ca, bool is_ca)
shared_ptr[Certificate] issuer
cdef cppclass TrustList:
cppclass VerifyResult:
bool operator bool() const
bool isValid() const
string toString() const
TrustList()
void add(Certificate)
void remove(Certificate)
VerifyResult verify(Certificate);
ctypedef TrustList.VerifyResult TrustListVerifyResult
cdef extern from "opendht/value.h" namespace "dht::Value":
cdef cppclass Field:
pass
cdef extern from "opendht/value.h" namespace "dht::Value::Field":
cdef Field None
cdef Field Id
cdef Field OwnerPk
cdef Field SeqNum
cdef Field UserType
cdef Field COUNT
cdef extern from "opendht/value.h" namespace "dht":
cdef cppclass Value:
Value() except +
Value(vector[uint8_t]) except +
Value(const uint8_t* dat_ptr, size_t dat_len) except +
Value(const uint16_t t, const uint8_t* dat_ptr, size_t dat_len) except +
string toString() const
size_t size() const
uint64_t id
@@ -92,6 +169,37 @@ cdef extern from "opendht/value.h" namespace "dht":
vector[uint8_t] data
string user_type
cdef cppclass ValueType:
ValueType(uint16_t id, string name, seconds expiration) except +
uint16_t id
string name
seconds expiration
cdef cppclass Query:
Query() except +
Query(Select s, Where w) except +
Query(string q_str) except +
bool isSatisfiedBy(const Query& q) const
string toString() const
cdef cppclass Select:
Select() except +
Select(const string& q_str) except +
bool isSatisfiedBy(const Select& os) const
Select& field(Field field)
string toString() const
cdef cppclass Where:
Where() except +
Where(const string& q_str)
bool isSatisfiedBy(const Where& where) const
Where& id(uint64_t id)
Where& valueType(uint16_t type)
Where& owner(InfoHash owner_pk_hash)
Where& seq(uint16_t seq_no)
Where& userType(string user_type)
string toString() const
cdef extern from "opendht/node.h" namespace "dht":
cdef cppclass Node:
Node() except +
@@ -102,24 +210,35 @@ cdef extern from "opendht/node.h" namespace "dht":
cdef extern from "opendht/callbacks.h" namespace "dht":
ctypedef void (*ShutdownCallbackRaw)(void *user_data)
ctypedef bool (*GetCallbackRaw)(shared_ptr[Value] values, void *user_data)
ctypedef bool (*ValueCallbackRaw)(shared_ptr[Value] values, bool expired, void *user_data)
ctypedef void (*DoneCallbackRaw)(bool done, vector[shared_ptr[Node]]* nodes, void *user_data)
ctypedef void (*DoneCallbackSimpleRaw)(bool done, void *user_data)
cppclass ShutdownCallback:
ShutdownCallback() except +
cppclass GetCallback:
GetCallback() except +
#GetCallback(GetCallbackRaw cb, void *user_data) except +
cppclass ValueCallback:
ValueCallback() except +
cppclass DoneCallback:
DoneCallback() except +
#DoneCallback(DoneCallbackRaw, void *user_data) except +
cppclass DoneCallbackSimple:
DoneCallbackSimple() except +
cdef ShutdownCallback bindShutdownCb(ShutdownCallbackRaw cb, void *user_data)
cdef GetCallback bindGetCb(GetCallbackRaw cb, void *user_data)
cdef ValueCallback bindValueCb(ValueCallbackRaw cb, void *user_data)
cdef DoneCallback bindDoneCb(DoneCallbackRaw cb, void *user_data)
cdef DoneCallbackSimple bindDoneCbSimple(DoneCallbackSimpleRaw cb, void *user_data)
cppclass Config:
InfoHash node_id
uint32_t network
bool is_bootstrap
bool maintain_storage
string persist_path
size_t max_req_per_sec
size_t max_peer_req_per_sec
cppclass SecureDhtConfig:
Config node_config
Identity id
@@ -132,20 +251,42 @@ cdef extern from "opendht/dhtrunner.h" namespace "dht":
cppclass Config:
SecureDhtConfig dht_config
bool threaded
string proxy_server
string push_node_id
string push_token
string push_topic
string push_platform
string proxy_user_agent
bool peer_discovery
bool peer_publish
shared_ptr[Certificate] server_ca
Identity client_identity
SockAddr bind4
SockAddr bind6
InfoHash getId() const
shared_ptr[PublicKey] getPublicKey() const
InfoHash getNodeId() const
void bootstrap(const char*, const char*)
void bootstrap(const_char*, const_char*)
void bootstrap(const SockAddr&, DoneCallbackSimple done_cb)
void run(in_port_t, Config config)
void run(const char*, const char*, const char*, Config config)
void run(const_char*, const_char*, const_char*, Config config)
void join()
void shutdown(ShutdownCallback)
void registerType(ValueType& value);
bool isRunning()
SockAddr getBound(sa_family_t af) const
string getStorageLog() const
string getRoutingTablesLog(sa_family_t af) const
string getSearchesLog(sa_family_t af) const
void get(InfoHash key, GetCallback get_cb, DoneCallback done_cb)
void put(InfoHash key, shared_ptr[Value] val, DoneCallback done_cb)
ListenToken listen(InfoHash key, GetCallback get_cb)
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)
ListenToken listen(InfoHash key, ValueCallback get_cb)
void cancelListen(InfoHash key, SharedListenToken token)
vector[unsigned] getNodeMessageStats(bool i)
@@ -156,3 +297,26 @@ cdef extern from "opendht/log.h" namespace "dht::log":
void disableLogging(DhtRunner& dht)
void enableFileLogging(DhtRunner& dht, const string& path)
cdef extern from "opendht/indexation/pht.h" namespace "dht::indexation":
size_t PHT_MAX_NODE_ENTRY_COUNT "dht::indexation::Pht::MAX_NODE_ENTRY_COUNT"
cdef cppclass Prefix:
Prefix() except +
Prefix(vector[uint8_t]) except +
string toString() const
ctypedef pair[InfoHash, uint64_t] IndexValue "dht::indexation::Value"
ctypedef map[string, vector[uint8_t]] IndexKey "dht::indexation::Pht::Key"
ctypedef map[string, uint32_t] IndexKeySpec "dht::indexation::Pht::KeySpec"
ctypedef void (*LookupCallbackRaw)(vector[shared_ptr[IndexValue]]* values, Prefix* p, void* user_data);
cdef cppclass Pht:
cppclass LookupCallback:
LookupCallback() except +
Pht(string, IndexKeySpec, shared_ptr[DhtRunner]) except +
void lookup(IndexKey k, LookupCallback cb, DoneCallbackSimple doneCb);
void insert(IndexKey k, IndexValue v, DoneCallbackSimple cb)
@staticmethod
LookupCallback bindLookupCb(LookupCallbackRaw cb, void *user_data)
cdef extern from "gnutls/gnutls.h" nogil:
int gnutls_global_init()
void gnutls_global_deinit()
const char* gnutls_strerror(int error)
Loaded 100 of 235 files, more files were not shown because too many files have changed in this diff. Show more