Compare commits

...

168 commits

Author SHA1 Message Date
orignal
2afdd5b723 cleanup NSR keys
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-19 12:33:09 -04:00
R4SAS
9b967059ad
[gha] Update docker containers build
Some checks are pending
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-18 21:52:44 +03:00
orignal
58818514e7 correct NSR size
Some checks failed
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build on Windows / CMake i686 (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
2025-04-17 22:34:39 -04:00
orignal
bbfe81cb79 handle any incoming post quantum crypto type 2025-04-17 22:15:17 -04:00
orignal
67fe6faf2d get preferred crypto key type from ratchets session
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-16 22:08:16 -04:00
orignal
1c162f9fd5 get preferred crypto key type from ratchets session 2025-04-16 21:59:10 -04:00
orignal
e69b56c4e3 publish preferred key first 2025-04-16 16:44:01 -04:00
orignal
f6c93f7345 common LocalEncryptionKey to pass to loacl LeaseSet
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
2025-04-16 15:40:09 -04:00
orignal
9c46ff2449 Initial Noise states and encryptors/decryptors for ML-KEM-768 and ML-KEM-1024
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-15 13:26:19 -04:00
orignal
1a04b59585 common InitNoiseIKState for all ML-KEM crypto
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-14 21:45:53 -04:00
orignal
828cd9d07b common MLKEMKeys for all types 2025-04-14 19:38:43 -04:00
orignal
4c5d0116f8 moved ML-KEM code to PostQuntum.h/.cpp 2025-04-14 18:21:07 -04:00
orignal
459be02d18 correct sequence of MixKey for ML-KEM NSR
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-14 13:31:37 -04:00
orignal
a83cd99f58 all ML-KEM crypto types 2025-04-14 13:29:53 -04:00
orignal
9ab1a67f0b common ML-KEM names and key lengths
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-13 18:18:44 -04:00
orignal
f6abbe5908 Use noise state Encrypt/Decrypt operations
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-04-08 14:39:46 -04:00
orignal
711f5bcc62 store ML-KEM section for possible next NSR
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-07 20:33:19 -04:00
orignal
6b38085f27 Noise state Encrypt/Decrypt operations
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-07 18:47:53 -04:00
orignal
3afe6455b2 reset nonce to 0 before payload encrypt/decrypt for ML-KEM-512
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
2025-04-06 15:34:01 -04:00
orignal
2f2ecc32d2 correct key type and message size for ML-KEM-512
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-05 18:12:38 -04:00
orignal
bce0ccf161 all ratchets types are eligible for ECIESx25519
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-04 19:52:32 -04:00
Alexey Chernov
8ca74a3e1d
[systemd] Wait for network-online target when starting service (#2169)
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
2025-04-04 22:35:56 +03:00
orignal
3be4c7217f move buffer when insert to buffer queue. clean entire queue in one call
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-04-03 18:42:34 -04:00
orignal
78d97179b8 handle ML-KEM section for new session and create for new session reply
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-04-01 20:46:41 -04:00
orignal
2280338900 datetime, address, ack blocks in path response packet
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-31 15:50:16 -04:00
orignal
ad3b999732 send path challenge of 8 bytes. add Ack block
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-31 10:29:16 -04:00
orignal
00920a049d use g++-x86 for 32-bits platform
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-30 13:28:45 -04:00
orignal
567183647e non-copyable RouterInfo 2025-03-30 12:37:40 -04:00
orignal
c2f68d7021 send datetime and address blocks with path challenge
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-29 21:34:16 -04:00
orignal
7404ce7fd2 update session's remote enpoint after receiving path response
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-28 19:34:36 -04:00
orignal
871fc14ba6 ML-KEM section for NS and NSR outgoing sessions
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-27 16:24:02 -04:00
orignal
81ba19e1ae use find_directory to detect data dir in Haiku 2025-03-25 21:31:16 -04:00
orignal
ecf19278e8 skip post-quantum keys if not supported 2025-03-25 18:55:28 -04:00
orignal
a40fa57ed4
Merge pull request #2165 from asciimoth/openssl
Update dates range in licence
2025-03-25 06:48:27 -04:00
AsciiMoth
d3cfbbd6b0
Update dates range in licence 2025-03-25 09:35:00 +04:00
orignal
22d854a6be ML-KEM-512 encaps/decaps 2025-03-24 15:45:06 -04:00
orignal
75d5c6036e use EVP interface for DSA sign/verify with OpenSSL 3 2025-03-23 18:53:32 -04:00
orignal
a193186935 MLKEM512 keygen added 2025-03-22 22:25:06 -04:00
orignal
41197264c6 fixed warning
Some checks failed
Build Debian packages / bookworm (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-03-22 15:42:22 -04:00
orignal
029e279b48 fixed typo 2025-03-22 12:30:51 -04:00
orignal
af5d2a415c c++20 2025-03-22 12:01:47 -04:00
orignal
7b98dd84d8 pass type with static key
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-21 19:40:02 -04:00
orignal
9fdbb14075 calculate preferred crypto based i2cp.leaseSetEncType
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-20 18:56:10 -04:00
orignal
935c055a35 encryptor/decryptor/keygen for ECIES_MLKEM512_X25519_AEAD
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-19 22:00:08 -04:00
orignal
9769ab0a46 changed ML-DSA-44 code 2025-03-19 21:56:59 -04:00
orignal
9684c86a69 select key with max key type if no preferred. Changed default preferred type to 4 2025-03-19 20:49:52 -04:00
orignal
b2fd30d042 map of encryption keys
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-19 15:22:09 -04:00
orignal
9ce515ff79 MLKEM512_X25519 crypto key added
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
2025-03-19 08:40:10 -04:00
orignal
46f530bfcd persist temporary keys of actual size
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-18 21:15:37 -04:00
orignal
bd2b96627c calculate crypto key length from key type 2025-03-18 19:23:13 -04:00
orignal
609cd401bb don't calculate key's base64 if not used
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-17 20:08:39 -04:00
orignal
bbf5c1655a ByteStreamToBase64 always returns std::string 2025-03-17 19:05:10 -04:00
orignal
8e6b9370d0 use ToBase64 for incoming stream accept 2025-03-17 19:00:48 -04:00
orignal
9cc625b19e fixed warning
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
2025-03-17 10:16:05 -04:00
orignal
93cc810f29 use string/string_view for base64
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-17 09:06:11 -04:00
orignal
e0a21cf702 use string/string_view for base32
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-16 20:40:36 -04:00
orignal
c2f6731296 don't use fixed size buffer for local destination's keys 2025-03-16 18:06:12 -04:00
orignal
706b9c51b1 make Base64EncodingBufferSize constexpr
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-16 17:21:22 -04:00
orignal
c0b5f2d2ef pass n by value 2025-03-16 15:17:08 -04:00
orignal
d93a80cd2b Support v1 datagram sessions without port 2025-03-16 11:07:17 -04:00
orignal
960a85e415 replace more strings to string_view
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-15 16:43:08 -04:00
orignal
67ab4fef6d implement strsplit using string_view instead stringstream 2025-03-15 13:19:53 -04:00
orignal
2def747564 use array instead vector for reserved ranges
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-14 19:28:22 -04:00
orignal
6a65680619 use array/string_view for HTTP methods and versions 2025-03-14 18:45:27 -04:00
orignal
ede8244e54 store translation as string_view
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-14 14:46:24 -04:00
orignal
c3d4d1bdf4 use array/string_view for exluded HTTP headers in server tunnel 2025-03-14 13:07:45 -04:00
orignal
ad7ca428ae enable encoding of ML-DSA-44 messages 2025-03-14 11:40:54 -04:00
orignal
cd9427d5d5 correct ML-DSA-44 signature verification params
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-13 20:39:51 -04:00
orignal
e3227ee5ee MLDSA44 signer and keygen
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-13 15:43:22 -04:00
orignal
dd58b2f867 Post-Quantum. MLDSA44 verifier
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-12 15:41:12 -04:00
orignal
972c6854bc don't delete trusted routers from netdb
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-03-10 13:43:21 -04:00
orignal
4ddfe9c94c don't grow window too fast
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-09 21:47:57 -04:00
orignal
4e8b8465fa don't create profile for every single router when save to disk
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-09 11:17:19 -04:00
orignal
4d9b5e685d use ends_with to recognize .i2p addresses
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-08 16:03:36 -05:00
orignal
b500374f74 recognize keys=shareddest
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-07 13:33:17 -05:00
orignal
fe3e7b1f6e reduced profile persist interval
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-06 16:29:14 -05:00
orignal
66a52a17c6 load profile for SSU2 priority only 2025-03-06 16:26:02 -05:00
orignal
c113241ccd support local sockets for I2PControl
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
2025-03-05 14:14:34 -05:00
orignal
9c97909e04 removed test crypto/signature types
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-05 10:51:21 -05:00
orignal
c816d3e4cc Ed25519ph 2025-03-05 10:38:23 -05:00
orignal
4f82fe24da replace boost::lexical_cast by std::to_string. std::unique_ptr for thread
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-03-04 18:11:58 -05:00
orignal
a1794ccd22 Solaris build added
Some checks failed
Build on Windows / i686 (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-03-02 15:00:09 -05:00
orignal
5f762845f0 move BOB incoming connection logic from I2PTunnelConnection to BOB
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-28 22:20:50 -05:00
orignal
539e7e988e reduce I2PTunnelConnection buffer size
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-27 21:35:14 -05:00
orignal
2a4403f1e0 lazy creation of TunnelEnpoint for transit tunnel 2025-02-27 18:00:24 -05:00
orignal
dcd15cc244 use common constants for babdwidth limits
Some checks failed
Build on Windows / clang-x86_64 (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-25 14:12:10 -05:00
orignal
9432202fad check PeerTest buffer size
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-24 13:58:10 -05:00
orignal
bf050ac465 fixed typo
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-22 19:01:20 -05:00
orignal
81dae1997d replace boost::lexical_cast by std::from_chars and std::to_string
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-21 20:34:53 -05:00
orignal
7e3d9649de use plain buffer instead stream for SignedData
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-20 22:04:58 -05:00
orignal
9ba016259d use plain buffer instead stream for SignedData 2025-02-20 21:59:24 -05:00
orignal
7791b3952e check RelayRequest, RelayIntro, RelayResponse buffer size. Use assign instead memcpy
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-20 16:53:49 -05:00
orignal
b97f09cc95 const ExtractString and ExtractMapping
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-19 18:51:54 -05:00
orignal
aedf59d11a fixed typo 2025-02-19 13:38:47 -05:00
orignal
d09367d686 always pass RouterInfo param values as string_view
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for linux/amd64 (push) Waiting to run
2025-02-19 11:08:47 -05:00
orignal
70f99ccc21 update router caps
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-18 21:49:07 -05:00
orignal
ef72ba3f34 parse RouterInfo from buffer 2025-02-18 21:11:59 -05:00
orignal
251605e2b8 Fix the calculation of the window drop size 2025-02-18 20:22:18 -05:00
orignal
fa2178ca3e set max padding size to 32 bytes
Some checks failed
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-17 15:08:22 -05:00
orignal
3d19fa12f6 create new tunnel immediately if last one failed
Some checks failed
Build Debian packages / bookworm (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-15 15:27:14 -05:00
orignal
48aaecacce check outbound tunnels only for LeaseSet request
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-14 21:53:38 -05:00
orignal
4bb86b6a86 don't request LeaseSet until destination if ready 2025-02-14 18:18:28 -05:00
orignal
0588116489 make token always non-zero
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-14 13:08:22 -05:00
orignal
78a37cc00f changed some log levels
Some checks failed
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-12 15:56:22 -05:00
r4sas
fb90b01f6c
2.56.0
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Signed-off-by: r4sas <r4sas@i2pmail.org>
2025-02-11 22:15:11 +03:00
orignal
ea55215668
Merge pull request #2154 from rex4539/uninitvar
Some checks failed
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake i686 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
fix uninitialized variable block.tunnelID
2025-02-11 08:30:28 -05:00
r4sas
58a86fa2dc
[build] OpenSSL linking reorder (#2156)
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Signed-off-by: r4sas <r4sas@i2pmail.org>
2025-02-10 22:10:06 +00:00
Dimitris Apostolou
8a7c4040b6 fix typo
Some checks failed
Build on Windows / CMake i686 (push) Has been cancelled
Build containers / Building container for linux/386 (push) Has been cancelled
Build Debian packages / bookworm (push) Has been cancelled
Build Debian packages / bullseye (push) Has been cancelled
Build Debian packages / buster (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=no (push) Has been cancelled
Build on OSX / With USE_UPNP=yes (push) Has been cancelled
Build on Windows / clang-x86_64 (push) Has been cancelled
Build on Windows / i686 (push) Has been cancelled
Build on Windows / ucrt-x86_64 (push) Has been cancelled
Build on Windows / x86_64 (push) Has been cancelled
Build on Windows / CMake clang-x86_64 (push) Has been cancelled
Build on Windows / CMake ucrt-x86_64 (push) Has been cancelled
Build on Windows / CMake x86_64 (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=no (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=yes (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Has been cancelled
Build containers / Building container for linux/amd64 (push) Has been cancelled
Build containers / Building container for linux/arm64 (push) Has been cancelled
Build containers / Building container for linux/arm/v7 (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-09 14:20:56 +03:00
orignal
ea279ef45a Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=no (push) Waiting to run
Build on OSX / With USE_UPNP=yes (push) Waiting to run
Build on Windows / x86_64 (push) Waiting to run
Build on Windows / CMake clang-x86_64 (push) Waiting to run
Build on Windows / CMake i686 (push) Waiting to run
Build on Windows / CMake ucrt-x86_64 (push) Waiting to run
Build on Windows / CMake x86_64 (push) Waiting to run
Build on Windows / clang-x86_64 (push) Waiting to run
Build on Windows / i686 (push) Waiting to run
Build on Windows / ucrt-x86_64 (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=no (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=yes (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=OFF (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=ON (push) Waiting to run
Build containers / Building container for linux/amd64 (push) Waiting to run
Build containers / Building container for linux/arm64 (push) Waiting to run
Build containers / Building container for linux/arm/v7 (push) Waiting to run
Build containers / Building container for linux/386 (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-08 15:51:58 -05:00
orignal
8aa18add4b 2.56.0 2025-02-08 15:51:13 -05:00
orignal
5ff52e6c93
Removed rus.i2p from subscriptions
Some checks are pending
Build Debian packages / bookworm (push) Waiting to run
Build Debian packages / bullseye (push) Waiting to run
Build Debian packages / buster (push) Waiting to run
2025-02-08 07:45:04 -05:00
orignal
ef19a85fc0 use correct OBEP inbound tunnel build
Some checks failed
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-03 20:41:51 -05:00
orignal
2ce3145195
Build IRC tunnel through low bandwidth routers
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-02-02 18:05:46 -05:00
orignal
b8d74dab47 recreate tunnels in random order 2025-02-02 16:49:37 -05:00
orignal
e8f5efd156 peers cleanup time variance
Some checks failed
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-02-01 09:42:44 -05:00
orignal
57aa8b3de8 fixed typo
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-31 12:55:09 -05:00
orignal
972b66f9a5 decline transit tunnel to duplicated router
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-31 11:20:39 -05:00
orignal
eadeea76e7 check congestion and random reject short tunnel build requests
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-30 15:35:04 -05:00
orignal
da7d3c55b0 replaced banana.incognet.io reseed by coconut.incognet.io
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-30 08:21:01 -05:00
Dimitris Apostolou
ff0b6a6a6a
fix uninitialized variable block.tunnelID 2025-01-30 13:36:53 +02:00
orignal
60d3e4d963 set ack requested flag after second resend attempt
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-29 19:15:12 -05:00
orignal
adc230acde use m_IsSaving flag for saving RouterInfo
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-29 16:02:31 -05:00
orignal
e4ba07a540 persist local RouterInfo in separate thread using seperate buffer 2025-01-29 13:22:15 -05:00
orignal
93ec5ac5c4 rollback
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-28 21:45:26 -05:00
orignal
774c606b09 don't wait for completion explicitly 2025-01-28 21:30:48 -05:00
orignal
1bff42042d check if saving if complete 2025-01-28 21:22:36 -05:00
orignal
daeb177579 save updated local RouterInfo in separate thread 2025-01-28 20:49:36 -05:00
orignal
5d7a062f1b std::mt19937 for random. Congestion update timer variance
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-28 14:47:22 -05:00
orignal
35f7bd5127 don't delete actively use profile. Last persist time 2025-01-28 14:09:25 -05:00
orignal
d411da451a
Merge pull request #2152 from rex4539/typo
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
fix typo
2025-01-27 22:48:40 -05:00
orignal
45bab06f37 cleanup cached addresses 2025-01-27 18:30:22 -05:00
Dimitris Apostolou
588855c6a7
fix typo 2025-01-27 23:04:23 +02:00
orignal
c3fa0ae8cc cache full addresses in memory when requested or received
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-27 13:24:37 -05:00
orignal
bf85a69a2f min peer test version 0.9.62
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-26 17:49:24 -05:00
orignal
72ff0b9fbb shorter ack request interval
Some checks failed
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-25 09:02:18 -05:00
orignal
b9c9988ff4 smaller request timeout if sent directly
Some checks failed
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-24 13:56:33 -05:00
orignal
1bb5ad22af use std::mt19937 for random. Peer test interval variance
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-23 19:20:20 -05:00
orignal
4fa5cec0dc fixed termination deadlock if SAM session is active
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-23 14:12:52 -05:00
orignal
1e7254dfaa don't delete router's buffer if an update received or connecting
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-22 13:25:11 -05:00
orignal
ca0818af7e drop buffer upon peer disconnect 2025-01-22 12:00:37 -05:00
orignal
b3d09513b8 fixed race condition
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
2025-01-21 19:38:07 -05:00
orignal
2857a163e9 check last endpoint only if profile is in memory. postpone profile update when connected
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-21 15:03:25 -05:00
orignal
cba7e5350d drop router's buffer after a while without updates
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
2025-01-20 18:17:41 -05:00
orignal
29a5effabb use std::mt19937 for random numbers in netdb
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
2025-01-20 13:27:40 -05:00
orignal
39e07ac265 don't load router profile in NTCP2 or SSU2 thread when check for duplicates 2025-01-20 11:58:33 -05:00
orignal
57986bd348 postpone updating router profile after tunnel build. Check profiles only in memory
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-19 19:16:34 -05:00
orignal
5e301937f2 use pointer to whole struct instead publicKey for buffer 2025-01-19 15:22:46 -05:00
orignal
4edde333ad don't drop router buffer if connected or being updated
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-19 11:47:32 -05:00
orignal
c600b834e3 postpone reading from file and updating router profile
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-18 18:26:16 -05:00
orignal
b6319d78bf don't delete buffer of connected routers
Some checks failed
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-16 19:06:33 -05:00
orignal
e4fc2789fe
Merge pull request #2149 from rex4539/var
Fix uninitialized variables
2025-01-16 14:21:18 -05:00
Dimitris Apostolou
4c5a1e064d
Fix uninitialized variables 2025-01-16 17:54:38 +02:00
orignal
4bb82110ab don't create EVP_CIPHER_CTX for each ChaCha20
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-15 21:13:50 -05:00
orignal
8c555fe592 copy fragment faster
Some checks failed
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-14 13:30:47 -05:00
orignal
5f1c599f81 fixed warning
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-13 21:37:40 -05:00
orignal
f2b5606583 store fragments inside m_OutOfSequenceFragments 2025-01-13 20:36:27 -05:00
orignal
08a680b53d use std::string_view instead const std::string&
Some checks failed
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-12 18:36:35 -05:00
orignal
634ceceb1c use std::string_view instead const std::string& 2025-01-12 12:23:26 -05:00
orignal
efd8e6e65b use string_view in ExtractString and PutString
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-11 22:34:18 -05:00
orignal
915429bb49 don't drop routing path if no data received
Some checks failed
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-10 11:16:07 -05:00
orignal
3e3e0e0a62 shorter ack request interval for datagrams
Some checks failed
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-08 20:52:38 -05:00
orignal
c023051fe4
Merge pull request #2147 from Vort/xp_fix2
Some checks are pending
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
fix Windows XP build
2025-01-07 16:42:02 -05:00
Vort
0b788de627 fix Windows XP build 2025-01-07 22:15:08 +02:00
orignal
fce4fab071 configurable shared local destination
Some checks failed
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-07 13:58:19 -05:00
orignal
3236de0d5a reduce publishing confimation intervals
Some checks are pending
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Waiting to run
Build Debian packages / ${{ matrix.dist }} (buster) (push) Waiting to run
Build on FreeBSD / with UPnP (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Waiting to run
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Waiting to run
Build on Windows / XP (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Waiting to run
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Waiting to run
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Waiting to run
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Waiting to run
Build containers / Pushing merged manifest (push) Blocked by required conditions
2025-01-06 19:36:15 -05:00
orignal
18707dd844 don't recalculate and process ranges for every Ack block
Some checks failed
Build on Windows / ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bookworm) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (bullseye) (push) Has been cancelled
Build Debian packages / ${{ matrix.dist }} (buster) (push) Has been cancelled
Build on FreeBSD / with UPnP (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on OSX / With USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (clang-x86_64, x64-clang, clang, CLANG64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (i686, x86, gcc, MINGW32) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (ucrt-x86_64, x64-ucrt, gcc, UCRT64) (push) Has been cancelled
Build on Windows / CMake ${{ matrix.arch }} (x86_64, x64, gcc, MINGW64) (push) Has been cancelled
Build on Windows / XP (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (no) (push) Has been cancelled
Build on Ubuntu / Make with USE_UPNP=${{ matrix.with_upnp }} (yes) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (OFF) (push) Has been cancelled
Build on Ubuntu / CMake with -DWITH_UPNP=${{ matrix.with_upnp }} (ON) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (amd64, linux/amd64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (arm64, linux/arm64) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (armv7, linux/arm/v7) (push) Has been cancelled
Build containers / Building container for ${{ matrix.platform }} (i386, linux/386) (push) Has been cancelled
Build containers / Pushing merged manifest (push) Has been cancelled
2025-01-03 22:04:09 -05:00
orignal
fc16a70f7b use AEADChaCha20Poly1305Encryptor and AEADChaCha20Poly1305Decryptor for test 2025-01-02 18:30:16 -05:00
orignal
619ec5d9c1 fixed AEAD/Chacha20/Poly1305 test 2025-01-02 09:04:57 -05:00
117 changed files with 3375 additions and 1615 deletions

View file

@ -133,6 +133,8 @@ jobs:
git clone https://github.com/msys2/MINGW-packages git clone https://github.com/msys2/MINGW-packages
cd MINGW-packages cd MINGW-packages
git checkout 4cbb366edf2f268ac3146174b40ce38604646fc5 mingw-w64-boost git checkout 4cbb366edf2f268ac3146174b40ce38604646fc5 mingw-w64-boost
cd mingw-w64-boost
sed -i 's/boostorg.jfrog.io\/artifactory\/main/archives.boost.io/' PKGBUILD
# headers # headers
- name: Get headers package version - name: Get headers package version

View file

@ -108,7 +108,7 @@ jobs:
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: purplei2p/i2pd:latest inputs: purplei2p/i2pd:latest
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 tags: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true push: true
- name: Create and push latest manifest image to GHCR - name: Create and push latest manifest image to GHCR
@ -116,7 +116,7 @@ jobs:
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: ghcr.io/purplei2p/i2pd:latest inputs: ghcr.io/purplei2p/i2pd:latest
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 tags: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true push: true
- name: Store release version to env - name: Store release version to env
@ -128,7 +128,7 @@ jobs:
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 tags: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true push: true
- name: Create and push release manifest to GHCR - name: Create and push release manifest to GHCR
@ -136,5 +136,5 @@ jobs:
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7 tags: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true push: true

View file

@ -1,6 +1,29 @@
# for this file format description, # for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog # see https://github.com/olivierlacan/keep-a-changelog
## [2.56.0] - 2025-02-11
### Added
- Config params for shared local destination
- AddressBook full addresses cache
- Decline transit tunnel to duplicated router
- Recreate tunnels in random order
### Changed
- Exclude disk operations from SSU2 and NTCP2 threads
- Set minimal version for peer test to 0.9.62
- Send ack requested flag after second SSU2 resend attempt
- Shorter ECIESx25519 ack request interval for datagram and I2CP sessions
- Don't change datagram routing path too often if unidirectional data stream
- Reduce LeaseSet and local RouterInfo publishing confirmation intervals
- Don't delete buffer of connected routers or if an update received
- Smaller RouterInfo request timeout if sent directly
- Persist local RouterInfo in separate thread
- Don't recalculate and process ranges for every SSU2 Ack block
- Reseeds list
### Fixed
- Termination deadlock if SAM session is active
- Race condition at tunnel endpoint
- Inbound tunnel build encryption
## [2.55.0] - 2024-12-30 ## [2.55.0] - 2024-12-30
### Added ### Added
- Support boost 1.87 - Support boost 1.87

View file

@ -1,4 +1,4 @@
Copyright (c) 2013-2023, The PurpleI2P Project Copyright (c) 2013-2025, The PurpleI2P Project
All rights reserved. All rights reserved.

View file

@ -69,6 +69,9 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
else ifneq (, $(findstring haiku, $(SYS))) else ifneq (, $(findstring haiku, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.haiku include Makefile.haiku
else ifneq (, $(findstring solaris, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.solaris
else # not supported else # not supported
$(error Not supported platform) $(error Not supported platform)
endif endif

View file

@ -3,7 +3,7 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1 DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
INCFLAGS = -I/usr/include/ -I/usr/local/include/ INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDLIBS = -lcrypto -lssl -lz -lpthread -lboost_system -lboost_program_options LDLIBS = -lssl -lcrypto -lz -lpthread -lboost_system -lboost_program_options
## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time ## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time
## **without** overwriting the CXXFLAGS which we need in order to build. ## **without** overwriting the CXXFLAGS which we need in order to build.

View file

@ -1,8 +1,12 @@
ifeq ($(shell $(CXX) -dumpmachine | cut -c 1-4), i586)
CXX = g++-x86
else
CXX = g++ CXX = g++
CXXFLAGS := -Wall -std=c++17 endif
CXXFLAGS := -Wall -std=c++20
INCFLAGS = -I/system/develop/headers INCFLAGS = -I/system/develop/headers
DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE
LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_program_options -lpthread LDLIBS = -lbe -lbsd -lnetwork -lz -lssl -lcrypto -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP DEFINES += -DUSE_UPNP

View file

@ -18,7 +18,7 @@ endif
LDLIBS += -lpthread -ldl LDLIBS += -lpthread -ldl
else else
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
LDFLAGS += -L${UPNPROOT}/lib LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc LDLIBS += -lminiupnpc

View file

@ -40,7 +40,7 @@ ifeq ($(USE_UPNP),yes)
endif endif
LDLIBS += -lpthread -ldl LDLIBS += -lpthread -ldl
else else
LDLIBS += -lcrypto -lssl -lz -lboost_program_options -lpthread -latomic LDLIBS += -lssl -lcrypto -lz -lboost_program_options -lpthread -latomic
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
LDLIBS += -lminiupnpc LDLIBS += -lminiupnpc
endif endif

View file

@ -7,9 +7,9 @@ LDFLAGS += -Wl,-dead_strip
LDFLAGS += -Wl,-dead_strip_dylibs LDFLAGS += -Wl,-dead_strip_dylibs
ifeq ($(USE_STATIC),yes) ifeq ($(USE_STATIC),yes)
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread LDLIBS = -lz /usr/local/lib/libssl.a /usr/local/lib/libcrypto.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
else else
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_filesystem -lboost_program_options -lpthread LDLIBS = -lz -lssl -lcrypto -lboost_system -lboost_filesystem -lboost_program_options -lpthread
endif endif
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)

9
Makefile.solaris Normal file
View file

@ -0,0 +1,9 @@
CXX = g++
INCFLAGS = -I/usr/openssl/3/include
CXXFLAGS := -Wall -std=c++20
LDLIBS = -L/usr/openssl/3/lib/64 -lssl -lcrypto -lboost_program_options -lz -lpthread -lsocket
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP
LDLIBS += -lminiupnpc
endif

View file

@ -59,7 +59,7 @@ get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
# function returns an empty string via _git_dir_var. # function returns an empty string via _git_dir_var.
# #
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and # Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
# neither foo nor bar contain a file/directory .git. This wil return # neither foo nor bar contain a file/directory .git. This will return
# C:/bla/.git # C:/bla/.git
# #
function(_git_find_closest_git_dir _start_dir _git_dir_var) function(_git_find_closest_git_dir _start_dir _git_dir_var)

View file

@ -243,7 +243,7 @@ verify = true
## Default: reg.i2p at "mainline" I2P Network ## Default: reg.i2p at "mainline" I2P Network
# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt # defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt
## Optional subscriptions URLs, separated by comma ## Optional subscriptions URLs, separated by comma
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt # subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt
[limits] [limits]
## Maximum active transit sessions (default: 5000) ## Maximum active transit sessions (default: 5000)

View file

@ -1,7 +1,8 @@
[Unit] [Unit]
Description=I2P Router written in C++ Description=I2P Router written in C++
Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/ Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/
After=network.target Wants=network.target
After=network.target network-online.target
[Service] [Service]
User=i2pd User=i2pd

View file

@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7) %define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git Name: i2pd-git
Version: 2.55.0 Version: 2.56.0
Release: git%{git_hash}%{?dist} Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd Conflicts: i2pd
@ -148,6 +148,9 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Tue Feb 11 2025 orignal <orignal@i2pmail.org> - 2.56.0
- update to 2.56.0
* Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0 * Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0
- update to 2.55.0 - update to 2.55.0

View file

@ -1,5 +1,5 @@
Name: i2pd Name: i2pd
Version: 2.55.0 Version: 2.56.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd-git Conflicts: i2pd-git
@ -146,6 +146,9 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Tue Feb 11 2025 orignal <orignal@i2pmail.org> - 2.56.0
- update to 2.56.0
* Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0 * Mon Dec 30 2024 orignal <orignal@i2pmail.org> - 2.55.0
- update to 2.55.0 - update to 2.55.0

View file

@ -5,6 +5,7 @@ port = 6668
destination = irc.ilita.i2p destination = irc.ilita.i2p
destinationport = 6667 destinationport = 6667
keys = irc-keys.dat keys = irc-keys.dat
i2p.streaming.profile=2
#[IRC-IRC2P] #[IRC-IRC2P]
#type = client #type = client

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -132,7 +132,8 @@ namespace http {
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
{ {
std::string state, stateText; std::string state;
std::string_view stateText;
switch (eState) switch (eState)
{ {
case i2p::tunnel::eTunnelStateBuildReplyReceived : case i2p::tunnel::eTunnelStateBuildReplyReceived :
@ -146,7 +147,7 @@ namespace http {
} }
if (stateText.empty ()) stateText = tr(state); if (stateText.empty ()) stateText = tr(state);
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, "; s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + std::string(tr("exploratory")) + ")" : "") << "</span>, "; // TODO:
ShowTraffic(s, bytes); ShowTraffic(s, bytes);
s << "\r\n"; s << "\r\n";
} }
@ -213,7 +214,7 @@ namespace http {
"</html>\r\n"; "</html>\r\n";
} }
static void ShowError(std::stringstream& s, const std::string& string) static void ShowError(std::stringstream& s, std::string_view string)
{ {
s << "<b>" << tr("ERROR") << ":</b>&nbsp;" << string << "<br>\r\n"; s << "<b>" << tr("ERROR") << ":</b>&nbsp;" << string << "<br>\r\n";
} }
@ -1262,7 +1263,7 @@ namespace http {
ShowLeasesSets(s); ShowLeasesSets(s);
else { else {
res.code = 400; res.code = 400;
ShowError(s, tr("Unknown page") + ": " + page); ShowError(s, std::string (tr("Unknown page")) + ": " + page); // TODO
return; return;
} }
} }
@ -1418,13 +1419,11 @@ namespace http {
{ {
auto signatureLen = dest->GetIdentity ()->GetSignatureLen (); auto signatureLen = dest->GetIdentity ()->GetSignatureLen ();
uint8_t * signature = new uint8_t[signatureLen]; uint8_t * signature = new uint8_t[signatureLen];
char * sig = new char[signatureLen*2];
std::stringstream out; std::stringstream out;
out << name << "=" << dest->GetIdentity ()->ToBase64 (); out << name << "=" << dest->GetIdentity ()->ToBase64 ();
dest->Sign ((uint8_t *)out.str ().c_str (), out.str ().length (), signature); dest->Sign ((uint8_t *)out.str ().c_str (), out.str ().length (), signature);
auto len = i2p::data::ByteStreamToBase64 (signature, signatureLen, sig, signatureLen*2); auto sig = i2p::data::ByteStreamToBase64 (signature, signatureLen);
sig[len] = 0;
out << "#!sig=" << sig; out << "#!sig=" << sig;
s << "<b>" << tr("SUCCESS") << "</b>:<br>\r\n<form action=\"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/add\" method=\"post\" rel=\"noreferrer\" target=\"_blank\">\r\n" s << "<b>" << tr("SUCCESS") << "</b>:<br>\r\n<form action=\"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/add\" method=\"post\" rel=\"noreferrer\" target=\"_blank\">\r\n"
"<textarea readonly name=\"record\" cols=\"80\" rows=\"10\">" << out.str () << "</textarea>\r\n<br>\r\n<br>\r\n" "<textarea readonly name=\"record\" cols=\"80\" rows=\"10\">" << out.str () << "</textarea>\r\n<br>\r\n<br>\r\n"
@ -1433,7 +1432,6 @@ namespace http {
"<input type=\"submit\" value=\"" << tr("Submit") << "\">\r\n" "<input type=\"submit\" value=\"" << tr("Submit") << "\">\r\n"
"</form>\r\n<br>\r\n"; "</form>\r\n<br>\r\n";
delete[] signature; delete[] signature;
delete[] sig;
} }
else else
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Domain can't end with .b32.i2p") << "\r\n<br>\r\n<br>\r\n"; s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Domain can't end with .b32.i2p") << "\r\n<br>\r\n<br>\r\n";
@ -1462,7 +1460,7 @@ namespace http {
else else
{ {
res.code = 400; res.code = 400;
ShowError(s, tr("Unknown command") + ": " + cmd); ShowError(s, std::string (tr("Unknown command")) + ": " + cmd); // TODO
return; return;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -15,7 +15,6 @@
// Use global placeholders from boost introduced when local_time.hpp is loaded // Use global placeholders from boost introduced when local_time.hpp is loaded
#define BOOST_BIND_GLOBAL_PLACEHOLDERS #define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <boost/lexical_cast.hpp>
#include "FS.h" #include "FS.h"
#include "Log.h" #include "Log.h"
@ -30,11 +29,24 @@ namespace i2p
namespace client namespace client
{ {
I2PControlService::I2PControlService (const std::string& address, int port): I2PControlService::I2PControlService (const std::string& address, int port):
m_IsRunning (false), m_Thread (nullptr), m_IsRunning (false),
m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(address), port)),
m_SSLContext (boost::asio::ssl::context::sslv23), m_SSLContext (boost::asio::ssl::context::sslv23),
m_ShutdownTimer (m_Service) m_ShutdownTimer (m_Service)
{ {
if (port)
m_Acceptor = std::make_unique<boost::asio::ip::tcp::acceptor>(m_Service,
boost::asio::ip::tcp::endpoint(boost::asio::ip::make_address(address), port));
else
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
{
std::remove (address.c_str ()); // just in case
m_LocalAcceptor = std::make_unique<boost::asio::local::stream_protocol::acceptor>(m_Service,
boost::asio::local::stream_protocol::endpoint(address));
}
#else
LogPrint(eLogError, "I2PControl: Local sockets are not supported");
#endif
i2p::config::GetOption("i2pcontrol.password", m_Password); i2p::config::GetOption("i2pcontrol.password", m_Password);
// certificate / keys // certificate / keys
@ -98,7 +110,7 @@ namespace client
{ {
Accept (); Accept ();
m_IsRunning = true; m_IsRunning = true;
m_Thread = new std::thread (std::bind (&I2PControlService::Run, this)); m_Thread = std::make_unique<std::thread>(std::bind (&I2PControlService::Run, this));
} }
} }
@ -107,12 +119,19 @@ namespace client
if (m_IsRunning) if (m_IsRunning)
{ {
m_IsRunning = false; m_IsRunning = false;
m_Acceptor.cancel (); if (m_Acceptor) m_Acceptor->cancel ();
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
if (m_LocalAcceptor)
{
auto path = m_LocalAcceptor->local_endpoint().path();
m_LocalAcceptor->cancel ();
std::remove (path.c_str ());
}
#endif
m_Service.stop (); m_Service.stop ();
if (m_Thread) if (m_Thread)
{ {
m_Thread->join (); m_Thread->join ();
delete m_Thread;
m_Thread = nullptr; m_Thread = nullptr;
} }
} }
@ -134,40 +153,60 @@ namespace client
void I2PControlService::Accept () void I2PControlService::Accept ()
{ {
auto newSocket = std::make_shared<ssl_socket> (m_Service, m_SSLContext); if (m_Acceptor)
m_Acceptor.async_accept (newSocket->lowest_layer(), std::bind (&I2PControlService::HandleAccept, this, {
std::placeholders::_1, newSocket)); auto newSocket = std::make_shared<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> > (m_Service, m_SSLContext);
m_Acceptor->async_accept (newSocket->lowest_layer(),
[this, newSocket](const boost::system::error_code& ecode)
{
HandleAccepted (ecode, newSocket);
});
}
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
else if (m_LocalAcceptor)
{
auto newSocket = std::make_shared<boost::asio::ssl::stream<boost::asio::local::stream_protocol::socket> > (m_Service, m_SSLContext);
m_LocalAcceptor->async_accept (newSocket->lowest_layer(),
[this, newSocket](const boost::system::error_code& ecode)
{
HandleAccepted (ecode, newSocket);
});
}
#endif
} }
void I2PControlService::HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket) template<typename ssl_socket>
void I2PControlService::HandleAccepted (const boost::system::error_code& ecode,
std::shared_ptr<ssl_socket> newSocket)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
Accept (); Accept ();
if (ecode) { if (ecode)
{
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ()); LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
return; return;
} }
LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ()); LogPrint (eLogDebug, "I2PControl: New request from ", newSocket->lowest_layer ().remote_endpoint ());
Handshake (socket); Handshake (newSocket);
} }
template<typename ssl_socket>
void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket) void I2PControlService::Handshake (std::shared_ptr<ssl_socket> socket)
{ {
socket->async_handshake(boost::asio::ssl::stream_base::server, socket->async_handshake(boost::asio::ssl::stream_base::server,
std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket)); [this, socket](const boost::system::error_code& ecode)
} {
if (ecode)
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket) {
{ LogPrint (eLogError, "I2PControl: Handshake error: ", ecode.message ());
if (ecode) { return;
LogPrint (eLogError, "I2PControl: Handshake error: ", ecode.message ()); }
return; ReadRequest (socket);
} });
//std::this_thread::sleep_for (std::chrono::milliseconds(5));
ReadRequest (socket);
} }
template<typename ssl_socket>
void I2PControlService::ReadRequest (std::shared_ptr<ssl_socket> socket) void I2PControlService::ReadRequest (std::shared_ptr<ssl_socket> socket)
{ {
auto request = std::make_shared<I2PControlBuffer>(); auto request = std::make_shared<I2PControlBuffer>();
@ -177,10 +216,13 @@ namespace client
#else #else
boost::asio::buffer (request->data (), request->size ()), boost::asio::buffer (request->data (), request->size ()),
#endif #endif
std::bind(&I2PControlService::HandleRequestReceived, this, [this, socket, request](const boost::system::error_code& ecode, size_t bytes_transferred)
std::placeholders::_1, std::placeholders::_2, socket, request)); {
HandleRequestReceived (ecode, bytes_transferred, socket, request);
});
} }
template<typename ssl_socket>
void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode, void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode,
size_t bytes_transferred, std::shared_ptr<ssl_socket> socket, size_t bytes_transferred, std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf) std::shared_ptr<I2PControlBuffer> buf)
@ -258,6 +300,7 @@ namespace client
} }
} }
template<typename ssl_socket>
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket, void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml) std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
{ {
@ -267,7 +310,7 @@ namespace client
std::ostringstream header; std::ostringstream header;
header << "HTTP/1.1 200 OK\r\n"; header << "HTTP/1.1 200 OK\r\n";
header << "Connection: close\r\n"; header << "Connection: close\r\n";
header << "Content-Length: " << boost::lexical_cast<std::string>(len) << "\r\n"; header << "Content-Length: " << std::to_string(len) << "\r\n";
header << "Content-Type: application/json\r\n"; header << "Content-Type: application/json\r\n";
header << "Date: "; header << "Date: ";
std::time_t t = std::time (nullptr); std::time_t t = std::time (nullptr);
@ -280,16 +323,11 @@ namespace client
memcpy (buf->data () + offset, response.str ().c_str (), len); memcpy (buf->data () + offset, response.str ().c_str (), len);
boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len), boost::asio::async_write (*socket, boost::asio::buffer (buf->data (), offset + len),
boost::asio::transfer_all (), boost::asio::transfer_all (),
std::bind(&I2PControlService::HandleResponseSent, this, [socket, buf](const boost::system::error_code& ecode, std::size_t bytes_transferred)
std::placeholders::_1, std::placeholders::_2, socket, buf)); {
} if (ecode)
LogPrint (eLogError, "I2PControl: Write error: ", ecode.message ());
void I2PControlService::HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, });
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
{
if (ecode) {
LogPrint (eLogError, "I2PControl: Write error: ", ecode.message ());
}
} }
// handlers // handlers

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -35,8 +35,6 @@ namespace client
class I2PControlService: public I2PControlHandlers class I2PControlService: public I2PControlHandlers
{ {
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
public: public:
I2PControlService (const std::string& address, int port); I2PControlService (const std::string& address, int port);
@ -49,16 +47,18 @@ namespace client
void Run (); void Run ();
void Accept (); void Accept ();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket); template<typename ssl_socket>
void HandleAccepted (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> newSocket);
template<typename ssl_socket>
void Handshake (std::shared_ptr<ssl_socket> socket); void Handshake (std::shared_ptr<ssl_socket> socket);
void HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket); template<typename ssl_socket>
void ReadRequest (std::shared_ptr<ssl_socket> socket); void ReadRequest (std::shared_ptr<ssl_socket> socket);
template<typename ssl_socket>
void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred, void HandleRequestReceived (const boost::system::error_code& ecode, size_t bytes_transferred,
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf); std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
template<typename ssl_socket>
void SendResponse (std::shared_ptr<ssl_socket> socket, void SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml); std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml);
void HandleResponseSent (const boost::system::error_code& ecode, std::size_t bytes_transferred,
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf);
void CreateCertificate (const char *crt_path, const char *key_path); void CreateCertificate (const char *crt_path, const char *key_path);
@ -86,10 +86,13 @@ namespace client
std::string m_Password; std::string m_Password;
bool m_IsRunning; bool m_IsRunning;
std::thread * m_Thread; std::unique_ptr<std::thread> m_Thread;
boost::asio::io_context m_Service; boost::asio::io_context m_Service;
boost::asio::ip::tcp::acceptor m_Acceptor; std::unique_ptr<boost::asio::ip::tcp::acceptor> m_Acceptor;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
std::unique_ptr<boost::asio::local::stream_protocol::acceptor> m_LocalAcceptor;
#endif
boost::asio::ssl::context m_SSLContext; boost::asio::ssl::context m_SSLContext;
boost::asio::deadline_timer m_ShutdownTimer; boost::asio::deadline_timer m_ShutdownTimer;
std::set<std::string> m_Tokens; std::set<std::string> m_Tokens;

6
debian/changelog vendored
View file

@ -1,3 +1,9 @@
i2pd (2.56.0-1) unstable; urgency=medium
* updated to version 2.56.0/0.9.65
-- orignal <orignal@i2pmail.org> Tue, 11 Feb 2025 16:00:00 +0000
i2pd (2.55.0-1) unstable; urgency=medium i2pd (2.55.0-1) unstable; urgency=medium
* updated to version 2.55.0 * updated to version 2.55.0

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace afrikaans // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"failed", "Het misluk"}, {"failed", "Het misluk"},
{"unknown", "onbekend"}, {"unknown", "onbekend"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace armenian // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f ԿիԲ"}, {"%.2f KiB", "%.2f ԿիԲ"},
{"%.2f MiB", "%.2f ՄիԲ"}, {"%.2f MiB", "%.2f ՄիԲ"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace chinese // language namespace
return 0; return 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace czech // language namespace
return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2; return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -30,7 +30,7 @@ namespace english // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"", ""}, {"", ""},
}; };

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace french // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f Kio"}, {"%.2f KiB", "%.2f Kio"},
{"%.2f MiB", "%.2f Mio"}, {"%.2f MiB", "%.2f Mio"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace german // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -30,12 +30,12 @@ namespace i18n
} }
} }
std::string translate (const std::string& arg) std::string_view translate (std::string_view arg)
{ {
return i2p::client::context.GetLanguage ()->GetString (arg); return i2p::client::context.GetLanguage ()->GetString (arg);
} }
std::string translate (const std::string& arg, const std::string& arg2, const int& n) std::string translate (const std::string& arg, const std::string& arg2, const int n)
{ {
return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n); return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -10,6 +10,7 @@
#define __I18N_H__ #define __I18N_H__
#include <string> #include <string>
#include <string_view>
#include <map> #include <map>
#include <utility> #include <utility>
#include <functional> #include <functional>
@ -18,12 +19,13 @@ namespace i2p
{ {
namespace i18n namespace i18n
{ {
typedef std::map<std::string_view, std::string_view> LocaleStrings;
class Locale class Locale
{ {
public: public:
Locale ( Locale (
const std::string& language, const std::string& language,
const std::map<std::string, std::string>& strings, const LocaleStrings& strings,
const std::map<std::string, std::vector<std::string>>& plurals, const std::map<std::string, std::vector<std::string>>& plurals,
std::function<int(int)> formula std::function<int(int)> formula
): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { }; ): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { };
@ -34,7 +36,7 @@ namespace i18n
return m_Language; return m_Language;
} }
std::string GetString (const std::string& arg) const std::string_view GetString (std::string_view arg) const
{ {
const auto it = m_Strings.find(arg); const auto it = m_Strings.find(arg);
if (it == m_Strings.end()) if (it == m_Strings.end())
@ -47,7 +49,7 @@ namespace i18n
} }
} }
std::string GetPlural (const std::string& arg, const std::string& arg2, const int& n) const std::string GetPlural (const std::string& arg, const std::string& arg2, int n) const
{ {
const auto it = m_Plurals.find(arg2); const auto it = m_Plurals.find(arg2);
if (it == m_Plurals.end()) // not found, fallback to english if (it == m_Plurals.end()) // not found, fallback to english
@ -63,14 +65,14 @@ namespace i18n
private: private:
const std::string m_Language; const std::string m_Language;
const std::map<std::string, std::string> m_Strings; const LocaleStrings m_Strings;
const std::map<std::string, std::vector<std::string>> m_Plurals; const std::map<std::string, std::vector<std::string>> m_Plurals;
std::function<int(int)> m_Formula; std::function<int(int)> m_Formula;
}; };
void SetLanguage(const std::string &lang); void SetLanguage(const std::string &lang);
std::string translate (const std::string& arg); std::string_view translate (std::string_view arg);
std::string translate (const std::string& arg, const std::string& arg2, const int& n); std::string translate (const std::string& arg, const std::string& arg2, int n);
} // i18n } // i18n
} // i2p } // i2p
@ -79,7 +81,7 @@ namespace i18n
* @param arg String with message * @param arg String with message
*/ */
template<typename TValue> template<typename TValue>
std::string tr (TValue&& arg) std::string_view tr (TValue&& arg)
{ {
return i2p::i18n::translate(std::forward<TValue>(arg)); return i2p::i18n::translate(std::forward<TValue>(arg));
} }
@ -92,7 +94,7 @@ std::string tr (TValue&& arg)
template<typename TValue, typename... TArgs> template<typename TValue, typename... TArgs>
std::string tr (TValue&& arg, TArgs&&... args) std::string tr (TValue&& arg, TArgs&&... args)
{ {
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg)); std::string tr_str = std::string (i2p::i18n::translate(std::forward<TValue>(arg))); // TODO:
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...); size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
std::string str(size, 0); std::string str(size, 0);
@ -108,7 +110,7 @@ std::string tr (TValue&& arg, TArgs&&... args)
* @param n Integer, used for selection of form * @param n Integer, used for selection of form
*/ */
template<typename TValue, typename TValue2> template<typename TValue, typename TValue2>
std::string ntr (TValue&& arg, TValue2&& arg2, int& n) std::string ntr (TValue&& arg, TValue2&& arg2, int n)
{ {
return i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n)); return i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
} }
@ -121,7 +123,7 @@ std::string ntr (TValue&& arg, TValue2&& arg2, int& n)
* @param args Array of arguments for string formatting * @param args Array of arguments for string formatting
*/ */
template<typename TValue, typename TValue2, typename... TArgs> template<typename TValue, typename TValue2, typename... TArgs>
std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args) std::string ntr (TValue&& arg, TValue2&& arg2, int n, TArgs&&... args)
{ {
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n)); std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace italian // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023-2024, The PurpleI2P Project * Copyright (c) 2023-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace polish // language namespace
return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2); return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023-2024, The PurpleI2P Project * Copyright (c) 2023-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace portuguese // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace russian // language namespace
return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2; return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f КиБ"}, {"%.2f KiB", "%.2f КиБ"},
{"%.2f MiB", "%.2f МиБ"}, {"%.2f MiB", "%.2f МиБ"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace spanish // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023, The PurpleI2P Project * Copyright (c) 2023-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace swedish // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023, The PurpleI2P Project * Copyright (c) 2023-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace turkish // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace turkmen // language namespace
return n != 1 ? 1 : 0; return n != 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace ukrainian // language namespace
return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2; return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f КіБ"}, {"%.2f KiB", "%.2f КіБ"},
{"%.2f MiB", "%.2f МіБ"}, {"%.2f MiB", "%.2f МіБ"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -29,7 +29,7 @@ namespace uzbek // language namespace
return n > 1 ? 1 : 0; return n > 1 ? 1 : 0;
} }
static std::map<std::string, std::string> strings static const LocaleStrings strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"}, {"%.2f MiB", "%.2f MiB"},

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -15,7 +15,7 @@ namespace i2p
{ {
namespace data namespace data
{ {
static const char T32[32] = static constexpr char T32[32] =
{ {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
@ -28,11 +28,6 @@ namespace data
return T32; return T32;
} }
bool IsBase32 (char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
}
static void iT64Build(void); static void iT64Build(void);
/* /*
@ -43,7 +38,7 @@ namespace data
* Direct Substitution Table * Direct Substitution Table
*/ */
static const char T64[64] = static constexpr char T64[64] =
{ {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
@ -60,23 +55,16 @@ namespace data
return T64; return T64;
} }
bool IsBase64 (char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~';
}
/* /*
* Reverse Substitution Table (built in run time) * Reverse Substitution Table (built in run time)
*/ */
static char iT64[256]; static char iT64[256];
static int isFirstTime = 1; static int isFirstTime = 1;
/* /*
* Padding * Padding
*/ */
static constexpr char P64 = '=';
static char P64 = '=';
/* /*
* *
@ -86,78 +74,69 @@ namespace data
* Converts binary encoded data to BASE64 format. * Converts binary encoded data to BASE64 format.
* *
*/ */
std::string ByteStreamToBase64 (// base64 encoded string
size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */ const uint8_t * InBuffer, // Input buffer, binary data
const uint8_t * InBuffer, /* Input buffer, binary data */ size_t InCount // Number of bytes in the input buffer
size_t InCount, /* Number of bytes in the input buffer */
char * OutBuffer, /* output buffer */
size_t len /* length of output buffer */
) )
{ {
unsigned char * ps; unsigned char * ps;
unsigned char * pd;
unsigned char acc_1; unsigned char acc_1;
unsigned char acc_2; unsigned char acc_2;
int i; int i;
int n; int n;
int m; int m;
size_t outCount;
ps = (unsigned char *)InBuffer; ps = (unsigned char *)InBuffer;
n = InCount / 3; n = InCount / 3;
m = InCount % 3; m = InCount % 3;
if (!m) size_t outCount = m ? (4 * (n + 1)) : (4 * n);
outCount = 4 * n;
else
outCount = 4 * (n + 1);
if (outCount > len) return 0; std::string out;
out.reserve (outCount);
pd = (unsigned char *)OutBuffer;
for ( i = 0; i < n; i++ ) for ( i = 0; i < n; i++ )
{ {
acc_1 = *ps++; acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x30; acc_2 = (acc_1 << 4) & 0x30;
acc_1 >>= 2; /* base64 digit #1 */ acc_1 >>= 2; // base64 digit #1
*pd++ = T64[acc_1]; out.push_back (T64[acc_1]);
acc_1 = *ps++; acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */ acc_2 |= acc_1 >> 4; // base64 digit #2
*pd++ = T64[acc_2]; out.push_back (T64[acc_2]);
acc_1 &= 0x0f; acc_1 &= 0x0f;
acc_1 <<= 2; acc_1 <<= 2;
acc_2 = *ps++; acc_2 = *ps++;
acc_1 |= acc_2 >> 6; /* base64 digit #3 */ acc_1 |= acc_2 >> 6; // base64 digit #3
*pd++ = T64[acc_1]; out.push_back (T64[acc_1]);
acc_2 &= 0x3f; /* base64 digit #4 */ acc_2 &= 0x3f; // base64 digit #4
*pd++ = T64[acc_2]; out.push_back (T64[acc_2]);
} }
if ( m == 1 ) if ( m == 1 )
{ {
acc_1 = *ps++; acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */ acc_2 = (acc_1 << 4) & 0x3f; // base64 digit #2
acc_1 >>= 2; /* base64 digit #1 */ acc_1 >>= 2; // base64 digit #1
*pd++ = T64[acc_1]; out.push_back (T64[acc_1]);
*pd++ = T64[acc_2]; out.push_back (T64[acc_2]);
*pd++ = P64; out.push_back (P64);
*pd++ = P64; out.push_back (P64);
} }
else if ( m == 2 ) else if ( m == 2 )
{ {
acc_1 = *ps++; acc_1 = *ps++;
acc_2 = (acc_1 << 4) & 0x3f; acc_2 = (acc_1 << 4) & 0x3f;
acc_1 >>= 2; /* base64 digit #1 */ acc_1 >>= 2; // base64 digit #1
*pd++ = T64[acc_1]; out.push_back (T64[acc_1]);
acc_1 = *ps++; acc_1 = *ps++;
acc_2 |= acc_1 >> 4; /* base64 digit #2 */ acc_2 |= acc_1 >> 4; // base64 digit #2
*pd++ = T64[acc_2]; out.push_back (T64[acc_2]);
acc_1 &= 0x0f; acc_1 &= 0x0f;
acc_1 <<= 2; /* base64 digit #3 */ acc_1 <<= 2; // base64 digit #3
*pd++ = T64[acc_1]; out.push_back (T64[acc_1]);
*pd++ = P64; out.push_back (P64);
} }
return outCount; return out;
} }
/* /*
@ -165,55 +144,42 @@ namespace data
* Base64ToByteStream * Base64ToByteStream
* ------------------ * ------------------
* *
* Converts BASE64 encoded data to binary format. If input buffer is * Converts BASE64 encoded string to binary format. If input buffer is
* not properly padded, buffer of negative length is returned * not properly padded, buffer of negative length is returned
* *
*/ */
size_t Base64ToByteStream ( // Number of output bytes
size_t Base64ToByteStream ( /* Number of output bytes */ std::string_view base64Str, // BASE64 encoded string
const char * InBuffer, /* BASE64 encoded buffer */ uint8_t * OutBuffer, // output buffer length
size_t InCount, /* Number of input bytes */ size_t len // length of output buffer
uint8_t * OutBuffer, /* output buffer length */
size_t len /* length of output buffer */
) )
{ {
unsigned char * ps;
unsigned char * pd; unsigned char * pd;
unsigned char acc_1; unsigned char acc_1;
unsigned char acc_2; unsigned char acc_2;
int i;
int n;
int m;
size_t outCount; size_t outCount;
if (isFirstTime) if (base64Str.empty () || base64Str[0] == P64) return 0;
iT64Build(); auto d = std::div (base64Str.length (), 4);
if (!d.rem)
n = InCount / 4; outCount = 3 * d.quot;
m = InCount % 4;
if (InCount && !m)
outCount = 3 * n;
else else
return 0; return 0;
if(*InBuffer == P64) if (isFirstTime) iT64Build();
return 0;
ps = (unsigned char *)(InBuffer + InCount - 1); auto pos = base64Str.find_last_not_of (P64);
while ( *ps-- == P64 ) if (pos == base64Str.npos) return 0;
outCount--; outCount -= (base64Str.length () - pos - 1);
ps = (unsigned char *)InBuffer; if (outCount > len) return 0;
if (outCount > len)
return 0;
auto ps = base64Str.begin ();
pd = OutBuffer; pd = OutBuffer;
auto endOfOutBuffer = OutBuffer + outCount; auto endOfOutBuffer = OutBuffer + outCount;
for ( i = 0; i < n; i++ ) for (int i = 0; i < d.quot; i++)
{ {
acc_1 = iT64[*ps++]; acc_1 = iT64[int(*ps++)];
acc_2 = iT64[*ps++]; acc_2 = iT64[int(*ps++)];
acc_1 <<= 2; acc_1 <<= 2;
acc_1 |= acc_2 >> 4; acc_1 |= acc_2 >> 4;
*pd++ = acc_1; *pd++ = acc_1;
@ -221,13 +187,13 @@ namespace data
break; break;
acc_2 <<= 4; acc_2 <<= 4;
acc_1 = iT64[*ps++]; acc_1 = iT64[int(*ps++)];
acc_2 |= acc_1 >> 2; acc_2 |= acc_1 >> 2;
*pd++ = acc_2; *pd++ = acc_2;
if (pd >= endOfOutBuffer) if (pd >= endOfOutBuffer)
break; break;
acc_2 = iT64[*ps++]; acc_2 = iT64[int(*ps++)];
acc_2 |= acc_1 << 6; acc_2 |= acc_1 << 6;
*pd++ = acc_2; *pd++ = acc_2;
} }
@ -235,31 +201,16 @@ namespace data
return outCount; return outCount;
} }
size_t Base64EncodingBufferSize (const size_t input_size) std::string ToBase64Standard (std::string_view in)
{ {
auto d = div (input_size, 3); auto str = ByteStreamToBase64 ((const uint8_t *)in.data (), in.length ());
if (d.rem)
d.quot++;
return 4 * d.quot;
}
std::string ToBase64Standard (const std::string& in)
{
auto len = Base64EncodingBufferSize (in.length ());
char * str = new char[len + 1];
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
str[l] = 0;
// replace '-' by '+' and '~' by '/' // replace '-' by '+' and '~' by '/'
for (size_t i = 0; i < l; i++) for (auto& ch: str)
if (str[i] == '-') if (ch == '-')
str[i] = '+'; ch = '+';
else if (str[i] == '~') else if (ch == '~')
str[i] = '/'; ch = '/';
return str;
std::string s(str);
delete[] str;
return s;
} }
/* /*
@ -280,13 +231,12 @@ namespace data
iT64[(int)P64] = 0; iT64[(int)P64] = 0;
} }
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) size_t Base32ToByteStream (std::string_view base32Str, uint8_t * outBuf, size_t outLen)
{ {
unsigned int tmp = 0, bits = 0; unsigned int tmp = 0, bits = 0;
size_t ret = 0; size_t ret = 0;
for (size_t i = 0; i < len; i++) for (auto ch: base32Str)
{ {
char ch = inBuf[i];
if (ch >= '2' && ch <= '7') // digit if (ch >= '2' && ch <= '7') // digit
ch = (ch - '2') + 26; // 26 means a-z ch = (ch - '2') + 26; // 26 means a-z
else if (ch >= 'a' && ch <= 'z') else if (ch >= 'a' && ch <= 'z')
@ -308,11 +258,13 @@ namespace data
return ret; return ret;
} }
size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen) std::string ByteStreamToBase32 (const uint8_t * inBuf, size_t len)
{ {
size_t ret = 0, pos = 1; std::string out;
out.reserve ((len * 8 + 4) / 5);
size_t pos = 1;
unsigned int bits = 8, tmp = inBuf[0]; unsigned int bits = 8, tmp = inBuf[0];
while (ret < outLen && (bits > 0 || pos < len)) while (bits > 0 || pos < len)
{ {
if (bits < 5) if (bits < 5)
{ {
@ -332,10 +284,9 @@ namespace data
bits -= 5; bits -= 5;
int ind = (tmp >> bits) & 0x1F; int ind = (tmp >> bits) & 0x1F;
outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2'); out.push_back ((ind < 26) ? (ind + 'a') : ((ind - 26) + '2'));
ret++;
} }
return ret; return out;
} }
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,26 +11,41 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <iostream> #include <string_view>
#include <cstdlib>
namespace i2p
{
namespace data
{
std::string ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount);
size_t Base64ToByteStream (std::string_view base64Str, uint8_t * OutBuffer, size_t len);
namespace i2p {
namespace data {
size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len);
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
const char * GetBase32SubstitutionTable (); const char * GetBase32SubstitutionTable ();
const char * GetBase64SubstitutionTable (); const char * GetBase64SubstitutionTable ();
bool IsBase64 (char ch); constexpr bool IsBase64 (char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~';
}
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t Base32ToByteStream (std::string_view base32Str, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); std::string ByteStreamToBase32 (const uint8_t * inBuf, size_t len);
bool IsBase32 (char ch); constexpr bool IsBase32 (char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
}
/** /**
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes * Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/ */
size_t Base64EncodingBufferSize(const size_t input_size); inline size_t Base64EncodingBufferSize(size_t input_size)
{
auto d = std::div (input_size, 3);
if (d.rem) d.quot++;
return 4 * d.quot;
}
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization std::string ToBase64Standard (std::string_view in); // using standard table, for Proxy-Authorization
} // data } // data
} // i2p } // i2p

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -152,11 +152,11 @@ namespace data
m_BlindedSigType = m_SigType; m_BlindedSigType = m_SigType;
} }
BlindedPublicKey::BlindedPublicKey (const std::string& b33): BlindedPublicKey::BlindedPublicKey (std::string_view b33):
m_SigType (0) // 0 means invalid, we can't blind DSA, set it later m_SigType (0) // 0 means invalid, we can't blind DSA, set it later
{ {
uint8_t addr[40]; // TODO: define length from b33 uint8_t addr[40]; // TODO: define length from b33
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40); size_t l = i2p::data::Base32ToByteStream (b33, addr, 40);
if (l < 32) if (l < 32)
{ {
LogPrint (eLogError, "Blinding: Malformed b33 ", b33); LogPrint (eLogError, "Blinding: Malformed b33 ", b33);
@ -198,7 +198,7 @@ namespace data
std::string BlindedPublicKey::ToB33 () const std::string BlindedPublicKey::ToB33 () const
{ {
if (m_PublicKey.size () > 32) return ""; // assume 25519 if (m_PublicKey.size () > 32) return ""; // assume 25519
uint8_t addr[35]; char str[60]; // TODO: define actual length uint8_t addr[35];
uint8_t flags = 0; uint8_t flags = 0;
if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG; if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
addr[0] = flags; // flags addr[0] = flags; // flags
@ -208,8 +208,7 @@ namespace data
uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ()); uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ());
// checksum is Little Endian // checksum is Little Endian
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
auto l = ByteStreamToBase32 (addr, m_PublicKey.size () + 3, str, 60); return ByteStreamToBase32 (addr, m_PublicKey.size () + 3);
return std::string (str, str + l);
} }
void BlindedPublicKey::GetCredential (uint8_t * credential) const void BlindedPublicKey::GetCredential (uint8_t * credential) const

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
#include "Identity.h" #include "Identity.h"
@ -23,7 +24,7 @@ namespace data
public: public:
BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false); BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p BlindedPublicKey (std::string_view b33); // from b33 without .b32.i2p
std::string ToB33 () const; std::string ToB33 () const;
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); }; const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -154,6 +154,17 @@ namespace config {
("socksproxy.i2p.streaming.profile", value<std::string>()->default_value("1"), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)") ("socksproxy.i2p.streaming.profile", value<std::string>()->default_value("1"), "SOCKS Proxy bandwidth usage profile. 1 - bulk(high), 2- interactive(low)")
; ;
options_description shareddest("Shared local destination options");
shareddest.add_options()
("shareddest.inbound.length", value<std::string>()->default_value("3"), "Shared local destination inbound tunnel length")
("shareddest.outbound.length", value<std::string>()->default_value("3"), "Shared local destination outbound tunnel length")
("shareddest.inbound.quantity", value<std::string>()->default_value("3"), "Shared local destination inbound tunnels quantity")
("shareddest.outbound.quantity", value<std::string>()->default_value("3"), "Shared local destination outbound tunnels quantity")
("shareddest.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Shared local destination's LeaseSet type")
("shareddest.i2cp.leaseSetEncType", value<std::string>()->default_value("0,4"), "Shared local destination's LeaseSet encryption type")
("shareddest.i2p.streaming.profile", value<std::string>()->default_value("2"), "Shared local destination bandwidth usage profile. 1 - bulk(high), 2- interactive(low)")
;
options_description sam("SAM bridge options"); options_description sam("SAM bridge options");
sam.add_options() sam.add_options()
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge") ("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
@ -227,7 +238,7 @@ namespace config {
"https://reseed.onion.im/," "https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/," "https://i2pseed.creativecowpat.net:8443/,"
"https://reseed.i2pgit.org/," "https://reseed.i2pgit.org/,"
"https://banana.incognet.io/," "https://coconut.incognet.io/,"
"https://reseed-pl.i2pd.xyz/," "https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/," "https://www2.mk16.de/,"
"https://i2p.ghativega.in/," "https://i2p.ghativega.in/,"
@ -341,6 +352,7 @@ namespace config {
.add(httpserver) .add(httpserver)
.add(httpproxy) .add(httpproxy)
.add(socksproxy) .add(socksproxy)
.add(shareddest)
.add(sam) .add(sam)
.add(bob) .add(bob)
.add(i2cp) .add(i2cp)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -19,6 +19,10 @@
#if OPENSSL_HKDF #if OPENSSL_HKDF
#include <openssl/kdf.h> #include <openssl/kdf.h>
#endif #endif
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
#include <openssl/param_build.h>
#include <openssl/core_names.h>
#endif
#include "CPU.h" #include "CPU.h"
#include "Crypto.h" #include "Crypto.h"
#include "Ed25519.h" #include "Ed25519.h"
@ -29,7 +33,7 @@ namespace i2p
{ {
namespace crypto namespace crypto
{ {
const uint8_t elgp_[256]= constexpr uint8_t elgp_[256]=
{ {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
@ -49,9 +53,9 @@ namespace crypto
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
}; };
const int elgg_ = 2; constexpr int elgg_ = 2;
const uint8_t dsap_[128]= constexpr uint8_t dsap_[128]=
{ {
0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c, 0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c,
0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15, 0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15,
@ -63,13 +67,13 @@ namespace crypto
0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93 0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93
}; };
const uint8_t dsaq_[20]= constexpr uint8_t dsaq_[20]=
{ {
0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d, 0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d,
0x68, 0x40, 0x46, 0xb7 0x68, 0x40, 0x46, 0xb7
}; };
const uint8_t dsag_[128]= constexpr uint8_t dsag_[128]=
{ {
0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0, 0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0,
0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81, 0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81,
@ -81,7 +85,7 @@ namespace crypto
0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82 0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82
}; };
const int rsae_ = 65537; constexpr int rsae_ = 65537;
struct CryptoConstants struct CryptoConstants
{ {
@ -146,6 +150,37 @@ namespace crypto
#define dsap GetCryptoConstants ().dsap #define dsap GetCryptoConstants ().dsap
#define dsaq GetCryptoConstants ().dsaq #define dsaq GetCryptoConstants ().dsaq
#define dsag GetCryptoConstants ().dsag #define dsag GetCryptoConstants ().dsag
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
EVP_PKEY * CreateDSA (BIGNUM * pubKey, BIGNUM * privKey)
{
EVP_PKEY * pkey = nullptr;
int selection = EVP_PKEY_KEY_PARAMETERS;
auto bld = OSSL_PARAM_BLD_new();
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, dsap);
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, dsaq);
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, dsag);
if (pubKey)
{
OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PUB_KEY, pubKey);
selection = EVP_PKEY_PUBLIC_KEY;
}
if (privKey)
{
OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PRIV_KEY, privKey);
selection = EVP_PKEY_KEYPAIR;
}
auto params = OSSL_PARAM_BLD_to_param(bld);
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "DSA", NULL);
EVP_PKEY_fromdata_init(ctx);
EVP_PKEY_fromdata(ctx, &pkey, selection, params);
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
return pkey;
}
#else
DSA * CreateDSA () DSA * CreateDSA ()
{ {
DSA * dsa = DSA_new (); DSA * dsa = DSA_new ();
@ -153,6 +188,7 @@ namespace crypto
DSA_set0_key (dsa, NULL, NULL); DSA_set0_key (dsa, NULL, NULL);
return dsa; return dsa;
} }
#endif
// DH/ElGamal // DH/ElGamal
@ -711,18 +747,40 @@ namespace crypto
return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false); return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false);
} }
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out) static void ChaCha20 (EVP_CIPHER_CTX *ctx, const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
{ {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
uint32_t iv[4]; uint32_t iv[4];
iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv); EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
int outlen = 0; int outlen = 0;
EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen); EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
EVP_EncryptFinal_ex(ctx, NULL, &outlen); EVP_EncryptFinal_ex(ctx, NULL, &outlen);
}
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
{
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
ChaCha20 (ctx, msg, msgLen, key, nonce, out);
EVP_CIPHER_CTX_free (ctx); EVP_CIPHER_CTX_free (ctx);
} }
ChaCha20Context::ChaCha20Context ()
{
m_Ctx = EVP_CIPHER_CTX_new ();
}
ChaCha20Context::~ChaCha20Context ()
{
if (m_Ctx)
EVP_CIPHER_CTX_free (m_Ctx);
}
void ChaCha20Context::operator ()(const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
{
ChaCha20 (m_Ctx, msg, msgLen, key, nonce, out);
}
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
uint8_t * out, size_t outLen) uint8_t * out, size_t outLen)
{ {
@ -763,6 +821,18 @@ namespace crypto
// Noise // Noise
void NoiseSymmetricState::Init (const uint8_t * ck, const uint8_t * hh, const uint8_t * pub)
{
// pub is Bob's public static key, hh = SHA256(h)
memcpy (m_CK, ck, 32);
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
m_N = 0;
}
void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len) void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
{ {
SHA256_CTX ctx; SHA256_CTX ctx;
@ -786,74 +856,93 @@ namespace crypto
{ {
HKDF (m_CK, sharedSecret, 32, "", m_CK); HKDF (m_CK, sharedSecret, 32, "", m_CK);
// new ck is m_CK[0:31], key is m_CK[32:63] // new ck is m_CK[0:31], key is m_CK[32:63]
m_N = 0;
} }
static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck, bool NoiseSymmetricState::Encrypt (const uint8_t * in, uint8_t * out, size_t len)
const uint8_t * hh, const uint8_t * pub)
{ {
// pub is Bob's public static key, hh = SHA256(h) uint8_t nonce[12];
memcpy (state.m_CK, ck, 32); if (m_N)
SHA256_CTX ctx; {
SHA256_Init (&ctx); memset (nonce, 0, 4);
SHA256_Update (&ctx, hh, 32); htole64buf (nonce + 4, m_N);
SHA256_Update (&ctx, pub, 32); }
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub) else
memset (nonce, 0, 12);
auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len + 16, true);
if (ret) m_N++;
return ret;
}
bool NoiseSymmetricState::Decrypt (const uint8_t * in, uint8_t * out, size_t len)
{
uint8_t nonce[12];
if (m_N)
{
memset (nonce, 0, 4);
htole64buf (nonce + 4, m_N);
}
else
memset (nonce, 0, 12);
auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len, false);
if (ret) m_N++;
return ret;
} }
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub) void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
{ {
static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars static constexpr char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
static const uint8_t hh[32] = static constexpr uint8_t hh[32] =
{ {
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1, 0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54 0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
}; // hh = SHA256(protocol_name || 0) }; // hh = SHA256(protocol_name || 0)
InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0 state.Init ((const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
} }
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub) void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
{ {
static const uint8_t protocolNameHash[32] = static constexpr uint8_t protocolNameHash[32] =
{ {
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed, 0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71 0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
}; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256") }; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256")
static const uint8_t hh[32] = static constexpr uint8_t hh[32] =
{ {
0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5, 0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e 0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
}; // SHA256 (protocolNameHash) }; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub); state.Init (protocolNameHash, hh, pub);
} }
void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub) void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub)
{ {
static const uint8_t protocolNameHash[32] = static constexpr uint8_t protocolNameHash[32] =
{ {
0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4, 0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4,
0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32 0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32
}; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256") }; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256")
static const uint8_t hh[32] = static constexpr uint8_t hh[32] =
{ {
0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53, 0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53,
0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33 0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33
}; // SHA256 (protocolNameHash) }; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub); state.Init (protocolNameHash, hh, pub);
} }
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub) void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
{ {
static const uint8_t protocolNameHash[32] = static constexpr uint8_t protocolNameHash[32] =
{ {
0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba, 0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c 0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes }; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
static const uint8_t hh[32] = static constexpr uint8_t hh[32] =
{ {
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32, 0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c 0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
}; // SHA256 (protocolNameHash) }; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub); state.Init (protocolNameHash, hh, pub);
} }
// init and terminate // init and terminate

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -33,6 +33,9 @@
# if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL # if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL
# define OPENSSL_SIPHASH 1 # define OPENSSL_SIPHASH 1
# endif # endif
# if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0
# define OPENSSL_PQ 1
# endif
#endif #endif
namespace i2p namespace i2p
@ -42,7 +45,11 @@ namespace crypto
bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len);
// DSA // DSA
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
EVP_PKEY * CreateDSA (BIGNUM * pubKey = nullptr, BIGNUM * privKey = nullptr);
#else
DSA * CreateDSA (); DSA * CreateDSA ();
#endif
// RSA // RSA
const BIGNUM * GetRSAE (); const BIGNUM * GetRSAE ();
@ -226,6 +233,19 @@ namespace crypto
// ChaCha20 // ChaCha20
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out); void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
class ChaCha20Context
{
public:
ChaCha20Context ();
~ChaCha20Context ();
void operator ()(const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
private:
EVP_CIPHER_CTX * m_Ctx;
};
// HKDF // HKDF
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32 void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
@ -235,10 +255,16 @@ namespace crypto
struct NoiseSymmetricState struct NoiseSymmetricState
{ {
uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/; uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/;
uint64_t m_N;
void Init (const uint8_t * ck, const uint8_t * hh, const uint8_t * pub);
void MixHash (const uint8_t * buf, size_t len); void MixHash (const uint8_t * buf, size_t len);
void MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs); void MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs);
void MixKey (const uint8_t * sharedSecret); void MixKey (const uint8_t * sharedSecret);
bool Encrypt (const uint8_t * in, uint8_t * out, size_t len); // out length = len + 16
bool Decrypt (const uint8_t * in, uint8_t * out, size_t len); // len without 16 bytes tag
}; };
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router) void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2021, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -181,5 +181,21 @@ namespace crypto
k.GetPrivateKey (priv); k.GetPrivateKey (priv);
memcpy (pub, k.GetPublicKey (), 32); memcpy (pub, k.GetPublicKey (), 32);
} }
LocalEncryptionKey::LocalEncryptionKey (i2p::data::CryptoKeyType t): keyType(t)
{
pub.resize (GetCryptoPublicKeyLen (keyType));
priv.resize (GetCryptoPrivateKeyLen (keyType));
}
void LocalEncryptionKey::GenerateKeys ()
{
i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv.data (), pub.data ());
}
void LocalEncryptionKey::CreateDecryptor ()
{
decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv.data ());
}
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2021, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "Crypto.h" #include "Crypto.h"
#include "Identity.h"
namespace i2p namespace i2p
{ {
@ -157,7 +158,50 @@ namespace crypto
X25519Keys m_StaticKeys; X25519Keys m_StaticKeys;
}; };
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); // including hybrid
constexpr size_t GetCryptoPrivateKeyLen (i2p::data::CryptoKeyType type)
{
switch (type)
{
case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32;
// ML-KEM hybrid
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
return 32;
};
return 0;
}
constexpr size_t GetCryptoPublicKeyLen (i2p::data::CryptoKeyType type)
{
switch (type)
{
case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32;
// ML-KEM hybrid
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
return 32;
};
return 0;
}
struct LocalEncryptionKey
{
std::vector<uint8_t> pub, priv;
i2p::data::CryptoKeyType keyType;
std::shared_ptr<CryptoKeyDecryptor> decryptor;
LocalEncryptionKey (i2p::data::CryptoKeyType t);
void GenerateKeys ();
void CreateDecryptor ();
};
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -104,8 +104,7 @@ namespace datagram
if (verified) if (verified)
{ {
auto h = identity.GetIdentHash(); auto session = ObtainSession (identity.GetIdentHash());
auto session = ObtainSession(h);
session->Ack(); session->Ack();
auto r = FindReceiver(toPort); auto r = FindReceiver(toPort);
if(r) if(r)
@ -381,15 +380,19 @@ namespace datagram
if (!found) if (!found)
{ {
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true); m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
if (!m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ()) if (m_RoutingSession)
m_PendingRoutingSessions.push_back (m_RoutingSession); {
m_RoutingSession->SetAckRequestInterval (DATAGRAM_SESSION_ACK_REQUEST_INTERVAL);
if (!m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ())
m_PendingRoutingSessions.push_back (m_RoutingSession);
}
} }
} }
auto path = m_RoutingSession->GetSharedRoutingPath(); auto path = m_RoutingSession->GetSharedRoutingPath();
if (path && m_RoutingSession->IsRatchets () && (m_RoutingSession->CleanupUnconfirmedTags () || if (path && m_RoutingSession->IsRatchets () && m_RoutingSession->CleanupUnconfirmedTags ())
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT))
{ {
LogPrint (eLogDebug, "Datagram: path reset");
m_RoutingSession->SetSharedRoutingPath (nullptr); m_RoutingSession->SetSharedRoutingPath (nullptr);
path = nullptr; path = nullptr;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -31,8 +31,6 @@ namespace datagram
{ {
// milliseconds for max session idle time // milliseconds for max session idle time
const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000; const uint64_t DATAGRAM_SESSION_MAX_IDLE = 10 * 60 * 1000;
// milliseconds for how long we try sticking to a dead routing path before trying to switch
const uint64_t DATAGRAM_SESSION_PATH_TIMEOUT = 10 * 1000;
// milliseconds interval a routing path is used before switching // milliseconds interval a routing path is used before switching
const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 20 * 60 * 1000; const uint64_t DATAGRAM_SESSION_PATH_SWITCH_INTERVAL = 20 * 60 * 1000;
// milliseconds before lease expire should we try switching leases // milliseconds before lease expire should we try switching leases
@ -44,6 +42,7 @@ namespace datagram
// max 64 messages buffered in send queue for each datagram session // max 64 messages buffered in send queue for each datagram session
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64; const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
const uint64_t DATAGRAM_MAX_FLUSH_INTERVAL = 5; // in milliseconds const uint64_t DATAGRAM_MAX_FLUSH_INTERVAL = 5; // in milliseconds
const int DATAGRAM_SESSION_ACK_REQUEST_INTERVAL = 5500; // in milliseconds
class DatagramSession : public std::enable_shared_from_this<DatagramSession> class DatagramSession : public std::enable_shared_from_this<DatagramSession>
{ {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -13,6 +13,7 @@
#include <vector> #include <vector>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include "Crypto.h" #include "Crypto.h"
#include "ECIESX25519AEADRatchetSession.h"
#include "Log.h" #include "Log.h"
#include "FS.h" #include "FS.h"
#include "Timestamp.h" #include "Timestamp.h"
@ -195,7 +196,7 @@ namespace client
m_IsPublic = itr->second != "true"; m_IsPublic = itr->second != "true";
} }
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency; int inLen = 0, outLen = 0, inQuant = 0, outQuant = 0, numTags = 0, minLatency = 0, maxLatency = 0;
std::map<std::string, int&> intOpts = { std::map<std::string, int&> intOpts = {
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen}, {I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen}, {I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
@ -377,10 +378,12 @@ namespace client
{ {
I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]); I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]);
uint32_t msgID = bufbe32toh (buf + I2NP_HEADER_MSGID_OFFSET); uint32_t msgID = bufbe32toh (buf + I2NP_HEADER_MSGID_OFFSET);
LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE, msgID); LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE,
GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE, msgID, nullptr);
} }
bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from)
{ {
switch (typeID) switch (typeID)
{ {
@ -395,7 +398,7 @@ namespace client
m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET)); m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET));
break; break;
case eI2NPDatabaseStore: case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (payload, len); HandleDatabaseStoreMessage (payload, len, from);
break; break;
case eI2NPDatabaseSearchReply: case eI2NPDatabaseSearchReply:
HandleDatabaseSearchReplyMessage (payload, len); HandleDatabaseSearchReplyMessage (payload, len);
@ -410,7 +413,8 @@ namespace client
return true; return true;
} }
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len,
i2p::garlic::ECIESX25519AEADRatchetSession * from)
{ {
if (len < DATABASE_STORE_HEADER_SIZE) if (len < DATABASE_STORE_HEADER_SIZE)
{ {
@ -465,7 +469,8 @@ namespace client
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET) if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
else else
leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetPreferredCryptoType () ); // LeaseSet2 leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET],
buf + offset, len - offset, true, from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType () ); // LeaseSet2
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ()) if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ())
{ {
if (leaseSet->GetIdentHash () != GetIdentHash ()) if (leaseSet->GetIdentHash () != GetIdentHash ())
@ -494,7 +499,8 @@ namespace client
if (request->requestedBlindedKey) if (request->requestedBlindedKey)
{ {
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ()); request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr,
from ? from->GetRemoteStaticKeyType () : GetPreferredCryptoType ());
if (ls2->IsValid () && !ls2->IsExpired ()) if (ls2->IsValid () && !ls2->IsExpired ())
{ {
leaseSet = ls2; leaseSet = ls2;
@ -597,7 +603,8 @@ namespace client
m_ExcludedFloodfills.clear (); m_ExcludedFloodfills.clear ();
m_PublishReplyToken = 0; m_PublishReplyToken = 0;
// schedule verification // schedule verification
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT +
(m_Pool ? m_Pool->GetRng ()() % PUBLISH_VERIFICATION_TIMEOUT_VARIANCE : 0)));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
} }
@ -676,8 +683,8 @@ namespace client
m_ExcludedFloodfills.clear (); m_ExcludedFloodfills.clear ();
m_PublishReplyToken = 1; // dummy non-zero value m_PublishReplyToken = 1; // dummy non-zero value
// try again after a while // try again after a while
LogPrint (eLogInfo, "Destination: Can't publish LeasetSet because destination is not ready. Try publishing again after ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds"); LogPrint (eLogInfo, "Destination: Can't publish LeasetSet because destination is not ready. Try publishing again after ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds");
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::milliseconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
return; return;
@ -696,7 +703,7 @@ namespace client
s->HandlePublishConfirmationTimer (boost::system::error_code()); s->HandlePublishConfirmationTimer (boost::system::error_code());
}); });
}; };
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::milliseconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg); outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg);
@ -712,15 +719,15 @@ namespace client
m_PublishReplyToken = 0; m_PublishReplyToken = 0;
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{ {
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds or failed. will try again"); LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds or failed. will try again");
Publish (); Publish ();
} }
else else
{ {
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " milliseconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
// Java floodfill never sends confirmation back for unknown crypto type // Java floodfill never sends confirmation back for unknown crypto type
// assume it successive and try to verify // assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT + PUBLISH_VERIFICATION_TIMEOUT_VARIANCE)); // always max
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
@ -993,17 +1000,10 @@ namespace client
} }
} }
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
{
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
}
ClientDestination::ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, ClientDestination::ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params): bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params), LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), m_Keys (keys), m_PreferredCryptoType (0), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED), m_StreamingOutboundSpeed (DEFAULT_MAX_OUTBOUND_SPEED),
m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED), m_StreamingInboundSpeed (DEFAULT_MAX_INBOUND_SPEED),
m_StreamingMaxConcurrentStreams (DEFAULT_MAX_CONCURRENT_STREAMS), m_StreamingMaxConcurrentStreams (DEFAULT_MAX_CONCURRENT_STREAMS),
@ -1028,7 +1028,15 @@ namespace client
{ {
try try
{ {
encryptionKeyTypes.insert (std::stoi(it1)); i2p::data::CryptoKeyType cryptoType = std::stoi(it1);
#if !OPENSSL_PQ
if (cryptoType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported
#endif
{
if (!m_PreferredCryptoType && cryptoType)
m_PreferredCryptoType = cryptoType; // first non-zero in the list
encryptionKeyTypes.insert (cryptoType);
}
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
@ -1045,20 +1053,15 @@ namespace client
for (auto& it: encryptionKeyTypes) for (auto& it: encryptionKeyTypes)
{ {
auto encryptionKey = new EncryptionKey (it); auto encryptionKey = std::make_shared<i2p::crypto::LocalEncryptionKey> (it);
if (IsPublic ()) if (IsPublic ())
PersistTemporaryKeys (encryptionKey); PersistTemporaryKeys (encryptionKey);
else else
encryptionKey->GenerateKeys (); encryptionKey->GenerateKeys ();
encryptionKey->CreateDecryptor (); encryptionKey->CreateDecryptor ();
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) if (it > i2p::data::CRYPTO_KEY_TYPE_ELGAMAL && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
{ SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Only DSA can use LeaseSet1
m_ECIESx25519EncryptionKey.reset (encryptionKey); m_EncryptionKeys.emplace (it, encryptionKey);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2
}
else
m_StandardEncryptionKey.reset (encryptionKey);
} }
if (IsPublic ()) if (IsPublic ())
@ -1408,31 +1411,56 @@ namespace client
return ret; return ret;
} }
void ClientDestination::PersistTemporaryKeys (EncryptionKey * keys) void ClientDestination::PersistTemporaryKeys (std::shared_ptr<i2p::crypto::LocalEncryptionKey> keys)
{ {
if (!keys) return; if (!keys) return;
std::string ident = GetIdentHash().ToBase32(); std::string ident = GetIdentHash().ToBase32();
std::string path = i2p::fs::DataDirPath("destinations", ident + "." + std::to_string (keys->keyType) + ".dat"); std::string path = i2p::fs::DataDirPath("destinations", ident + "." + std::to_string (keys->keyType) + ".dat");
std::ifstream f(path, std::ifstream::binary); std::ifstream f(path, std::ifstream::binary);
if (f)
{
size_t len = 0;
if (keys->keyType == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
len = 512;
else if (keys->keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{
f.seekg (0, std::ios::end);
len = f.tellg();
f.seekg (0, std::ios::beg);
}
if (f) { if (len == 512)
f.read ((char *)keys->pub, 256); {
f.read ((char *)keys->priv, 256); char pub[256], priv[256];
return; f.read (pub, 256);
memcpy (keys->pub.data(), pub, keys->pub.size());
f.read (priv, 256);
memcpy (keys->priv.data (), priv, keys->priv.size ());
}
else
{
f.read ((char *)keys->pub.data(), keys->pub.size());
f.read ((char *)keys->priv.data(), keys->priv.size());
}
if (f)
return;
else
LogPrint(eLogWarning, "Destination: Can't read keys from ", path);
} }
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p"); LogPrint (eLogInfo, "Destination: Creating new temporary keys of type ", keys->keyType, " for address ", ident, ".b32.i2p");
memset (keys->priv, 0, 256); memset (keys->priv.data (), 0, keys->priv.size ());
memset (keys->pub, 0, 256); memset (keys->pub.data (), 0, keys->pub.size ());
keys->GenerateKeys (); keys->GenerateKeys ();
// TODO:: persist crypto key type
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
if (f1) { if (f1)
f1.write ((char *)keys->pub, 256); {
f1.write ((char *)keys->priv, 256); f1.write ((char *)keys->pub.data (), keys->pub.size ());
return; f1.write ((char *)keys->priv.data (), keys->priv.size ());
} }
LogPrint(eLogCritical, "Destinations: Can't save keys to ", path); if (!f1)
LogPrint(eLogError, "Destination: Can't save keys to ", path);
} }
void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
@ -1440,9 +1468,10 @@ namespace client
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet; std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
{ {
if (m_StandardEncryptionKey) auto it = m_EncryptionKeys.find (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
if (it != m_EncryptionKeys.end ())
{ {
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_StandardEncryptionKey->pub, tunnels); leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), it->second->pub.data (), tunnels);
// sign // sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
} }
@ -1452,11 +1481,26 @@ namespace client
else else
{ {
// standard LS2 (type 3) first // standard LS2 (type 3) first
i2p::data::LocalLeaseSet2::KeySections keySections; if (m_EncryptionKeys.empty ())
if (m_ECIESx25519EncryptionKey) {
keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} ); LogPrint (eLogError, "Destinations: No encryption keys");
if (m_StandardEncryptionKey) return;
keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} ); }
i2p::data::LocalLeaseSet2::EncryptionKeys keySections;
std::shared_ptr<const i2p::crypto::LocalEncryptionKey> preferredSection;
if (m_EncryptionKeys.size () == 1)
preferredSection = m_EncryptionKeys.begin ()->second; // only key
else
{
for (const auto& it: m_EncryptionKeys)
if (it.first == m_PreferredCryptoType)
preferredSection = it.second;
else
keySections.push_back (it.second);
}
if (preferredSection)
keySections.push_front (preferredSection); // make preferred first
auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch (); auto publishedTimestamp = i2p::util::GetSecondsSinceEpoch ();
if (publishedTimestamp <= m_LastPublishedTimestamp) if (publishedTimestamp <= m_LastPublishedTimestamp)
@ -1482,11 +1526,22 @@ namespace client
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
{ {
if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) std::shared_ptr<i2p::crypto::LocalEncryptionKey> encryptionKey;
if (m_ECIESx25519EncryptionKey && m_ECIESx25519EncryptionKey->decryptor) if (!m_EncryptionKeys.empty ())
return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data); {
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor) if (m_EncryptionKeys.rbegin ()->first == preferredCrypto)
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data); encryptionKey = m_EncryptionKeys.rbegin ()->second;
else
{
auto it = m_EncryptionKeys.find (preferredCrypto);
if (it != m_EncryptionKeys.end ())
encryptionKey = it->second;
}
if (!encryptionKey)
encryptionKey = m_EncryptionKeys.rbegin ()->second;
}
if (encryptionKey)
return encryptionKey->decryptor->Decrypt (encrypted, data);
else else
LogPrint (eLogError, "Destinations: Decryptor is not set"); LogPrint (eLogError, "Destinations: Decryptor is not set");
return false; return false;
@ -1494,14 +1549,26 @@ namespace client
bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
{ {
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey; #if __cplusplus >= 202002L // C++20
return m_EncryptionKeys.contains (keyType);
#else
return m_EncryptionKeys.count (keyType) > 0;
#endif
}
i2p::data::CryptoKeyType ClientDestination::GetRatchetsHighestCryptoType () const
{
if (m_EncryptionKeys.empty ()) return 0;
auto cryptoType = m_EncryptionKeys.rbegin ()->first;
return cryptoType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? cryptoType : 0;
} }
const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
{ {
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) auto it = m_EncryptionKeys.find (keyType);
return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr; if (it != m_EncryptionKeys.end ())
return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr; return it->second->pub.data ();
return nullptr;
} }
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params) void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -22,6 +22,7 @@
#include "Identity.h" #include "Identity.h"
#include "TunnelPool.h" #include "TunnelPool.h"
#include "Crypto.h" #include "Crypto.h"
#include "CryptoKey.h"
#include "LeaseSet.h" #include "LeaseSet.h"
#include "Garlic.h" #include "Garlic.h"
#include "NetDb.hpp" #include "NetDb.hpp"
@ -36,8 +37,9 @@ namespace client
const uint8_t PROTOCOL_TYPE_STREAMING = 6; const uint8_t PROTOCOL_TYPE_STREAMING = 6;
const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; const uint8_t PROTOCOL_TYPE_DATAGRAM = 17;
const uint8_t PROTOCOL_TYPE_RAW = 18; const uint8_t PROTOCOL_TYPE_RAW = 18;
const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds const int PUBLISH_CONFIRMATION_TIMEOUT = 1800; // in milliseconds
const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successful publish const int PUBLISH_VERIFICATION_TIMEOUT = 5; // in seconds after successful publish
const int PUBLISH_VERIFICATION_TIMEOUT_VARIANCE = 3; // in seconds
const int PUBLISH_MIN_INTERVAL = 20; // in seconds const int PUBLISH_MIN_INTERVAL = 20; // in seconds
const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically
const int LEASESET_REQUEST_TIMEOUT = 1600; // in milliseconds const int LEASESET_REQUEST_TIMEOUT = 1600; // in milliseconds
@ -162,13 +164,15 @@ namespace client
// implements GarlicDestination // implements GarlicDestination
void HandleI2NPMessage (const uint8_t * buf, size_t len) override; void HandleI2NPMessage (const uint8_t * buf, size_t len) override;
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) override; bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) override;
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet); void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
int GetLeaseSetType () const { return m_LeaseSetType; }; int GetLeaseSetType () const { return m_LeaseSetType; };
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
int GetAuthType () const { return m_AuthType; }; int GetAuthType () const { return m_AuthType; };
virtual void CleanupDestination () {}; // additional clean up in derived classes virtual void CleanupDestination () {}; // additional clean up in derived classes
virtual i2p::data::CryptoKeyType GetPreferredCryptoType () const = 0;
// I2CP // I2CP
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0; virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
virtual void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) = 0; virtual void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) = 0;
@ -181,7 +185,7 @@ namespace client
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
void HandlePublishVerificationTimer (const boost::system::error_code& ecode); void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
void HandlePublishDelayTimer (const boost::system::error_code& ecode); void HandlePublishDelayTimer (const boost::system::error_code& ecode);
void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len, i2p::garlic::ECIESX25519AEADRatchetSession * from);
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
void HandleDeliveryStatusMessage (uint32_t msgID); void HandleDeliveryStatusMessage (uint32_t msgID);
@ -191,7 +195,6 @@ namespace client
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode); void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets (); void CleanupRemoteLeaseSets ();
i2p::data::CryptoKeyType GetPreferredCryptoType () const;
private: private:
@ -228,25 +231,14 @@ namespace client
class ClientDestination: public LeaseSetDestination class ClientDestination: public LeaseSetDestination
{ {
struct EncryptionKey
{
uint8_t pub[256], priv[256];
i2p::data::CryptoKeyType keyType;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> decryptor;
EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); };
void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); };
void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); };
};
public: public:
ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys, ClientDestination (boost::asio::io_context& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params = nullptr); bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~ClientDestination (); ~ClientDestination ();
void Start (); void Start () override;
void Stop (); void Stop () override;
const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; };
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
@ -283,24 +275,28 @@ namespace client
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true); i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
// implements LocalDestination // implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const; bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const override;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); }; std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const override { return m_Keys.GetPublic (); };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const; bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const override;
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const; const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const override;
protected: protected:
void CleanupDestination (); // GarlicDestionation
i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override;
// LeaseSetDestination
void CleanupDestination () override;
i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; }
// I2CP // I2CP
void HandleDataMessage (const uint8_t * buf, size_t len); void HandleDataMessage (const uint8_t * buf, size_t len) override;
void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels); void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) override;
private: private:
std::shared_ptr<ClientDestination> GetSharedFromThis () { std::shared_ptr<ClientDestination> GetSharedFromThis () {
return std::static_pointer_cast<ClientDestination>(shared_from_this ()); return std::static_pointer_cast<ClientDestination>(shared_from_this ());
} }
void PersistTemporaryKeys (EncryptionKey * keys); void PersistTemporaryKeys (std::shared_ptr<i2p::crypto::LocalEncryptionKey> keys);
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params); void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
template<typename Dest> template<typename Dest>
@ -309,8 +305,8 @@ namespace client
private: private:
i2p::data::PrivateKeys m_Keys; i2p::data::PrivateKeys m_Keys;
std::unique_ptr<EncryptionKey> m_StandardEncryptionKey; std::map<i2p::data::CryptoKeyType, std::shared_ptr<i2p::crypto::LocalEncryptionKey> > m_EncryptionKeys; // last is most preferable
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey; i2p::data::CryptoKeyType m_PreferredCryptoType;
int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams; int m_StreamingAckDelay,m_StreamingOutboundSpeed, m_StreamingInboundSpeed, m_StreamingMaxConcurrentStreams;
bool m_IsStreamingAnswerPings; bool m_IsStreamingAnswerPings;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,7 @@
#include "Log.h" #include "Log.h"
#include "util.h" #include "util.h"
#include "Crypto.h" #include "Crypto.h"
#include "PostQuantum.h"
#include "Elligator.h" #include "Elligator.h"
#include "Tag.h" #include "Tag.h"
#include "I2PEndian.h" #include "I2PEndian.h"
@ -94,6 +95,17 @@ namespace garlic
m_ItermediateSymmKeys.erase (index); m_ItermediateSymmKeys.erase (index);
} }
ReceiveRatchetTagSet::ReceiveRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session, bool isNS):
m_Session (session), m_IsNS (isNS)
{
}
ReceiveRatchetTagSet::~ReceiveRatchetTagSet ()
{
if (m_IsNS && m_Session)
m_Session->CleanupReceiveNSRKeys ();
}
void ReceiveRatchetTagSet::Expire () void ReceiveRatchetTagSet::Expire ()
{ {
if (!m_ExpirationTimestamp) if (!m_ExpirationTimestamp)
@ -162,12 +174,12 @@ namespace garlic
return false; return false;
} }
if (m_Destination) if (m_Destination)
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size); m_Destination->HandleECIESx25519GarlicClove (buf + offset, size, nullptr);
return true; return true;
} }
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS): ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS):
GarlicRoutingSession (owner, true) GarlicRoutingSession (owner, true), m_RemoteStaticKeyType (0)
{ {
if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate); if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0; RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
@ -252,12 +264,19 @@ namespace garlic
return false; return false;
} }
void ECIESX25519AEADRatchetSession::CleanupReceiveNSRKeys ()
{
m_EphemeralKeys = nullptr;
#if OPENSSL_PQ
m_PQKeys = nullptr;
#endif
}
bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len) bool ECIESX25519AEADRatchetSession::HandleNewIncomingSession (const uint8_t * buf, size_t len)
{ {
if (!GetOwner ()) return false; if (!GetOwner ()) return false;
// we are Bob // we are Bob
// KDF1 // KDF1
i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{ {
@ -265,20 +284,61 @@ namespace garlic
return false; return false;
} }
buf += 32; len -= 32; buf += 32; len -= 32;
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk) bool decrypted = false;
auto cryptoType = GetOwner ()->GetRatchetsHighestCryptoType ();
#if OPENSSL_PQ
if (cryptoType > i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // we support post quantum
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key"); i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), cryptoType, GetOwner ()->GetEncryptionPublicKey (cryptoType)); // bpk
return false; MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, cryptoType)) // x25519(bsk, aepk)
{
MixKey (sharedSecret);
auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (cryptoType);
std::vector<uint8_t> encapsKey(keyLen);
if (Decrypt (buf, encapsKey.data (), keyLen))
{
decrypted = true; // encaps section has right hash
MixHash (buf, keyLen + 16);
buf += keyLen + 16;
len -= keyLen + 16;
m_PQKeys = i2p::crypto::CreateMLKEMKeys (cryptoType);
m_PQKeys->SetPublicKey (encapsKey.data ());
}
}
}
#endif
if (!decrypted)
{
if (cryptoType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
{
cryptoType = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
return false;
}
MixKey (sharedSecret);
}
else
{
LogPrint (eLogWarning, "Garlic: No supported encryption type");
return false;
}
} }
MixKey (sharedSecret);
// decrypt flags/static // decrypt flags/static
uint8_t nonce[12], fs[32]; uint8_t fs[32];
CreateNonce (0, nonce); if (!Decrypt (buf, fs, 32))
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt
{ {
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed "); LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
return false; return false;
@ -291,20 +351,18 @@ namespace garlic
if (isStatic) if (isStatic)
{ {
// static key, fs is apk // static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32); SetRemoteStaticKey (cryptoType, fs);
if (!GetOwner ()->Decrypt (fs, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk) if (!GetOwner ()->Decrypt (fs, sharedSecret, m_RemoteStaticKeyType)) // x25519(bsk, apk)
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
} }
else // all zeros flags
CreateNonce (1, nonce);
// decrypt payload // decrypt payload
std::vector<uint8_t> payload (len - 16); // we must save original ciphertext std::vector<uint8_t> payload (len - 16); // we must save original ciphertext
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt if (!Decrypt (buf, payload.data (), len - 16))
{ {
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false; return false;
@ -340,7 +398,7 @@ namespace garlic
{ {
case eECIESx25519BlkGalicClove: case eECIESx25519BlkGalicClove:
if (GetOwner ()) if (GetOwner ())
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size); GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size, this);
break; break;
case eECIESx25519BlkNextKey: case eECIESx25519BlkNextKey:
LogPrint (eLogDebug, "Garlic: Next key"); LogPrint (eLogDebug, "Garlic: Next key");
@ -492,7 +550,16 @@ namespace garlic
offset += 32; offset += 32;
// KDF1 // KDF1
i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk #if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
{
i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), m_RemoteStaticKeyType, m_RemoteStaticKey); // bpk
m_PQKeys = i2p::crypto::CreateMLKEMKeys (m_RemoteStaticKeyType);
m_PQKeys->GenerateKeys ();
}
else
#endif
i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk) MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk) if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
@ -501,18 +568,32 @@ namespace garlic
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
#if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
{
auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType);
std::vector<uint8_t> encapsKey(keyLen);
m_PQKeys->GetPublicKey (encapsKey.data ());
// encrypt encapsKey
if (!Encrypt (encapsKey.data (), out + offset, keyLen))
{
LogPrint (eLogWarning, "Garlic: ML-KEM encap_key section AEAD encryption failed ");
return false;
}
MixHash (out + offset, keyLen + 16); // h = SHA256(h || ciphertext)
offset += keyLen + 16;
}
#endif
// encrypt flags/static key section // encrypt flags/static key section
uint8_t nonce[12];
CreateNonce (0, nonce);
const uint8_t * fs; const uint8_t * fs;
if (isStatic) if (isStatic)
fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); fs = GetOwner ()->GetEncryptionPublicKey (m_RemoteStaticKeyType);
else else
{ {
memset (out + offset, 0, 32); // all zeros flags section memset (out + offset, 0, 32); // all zeros flags section
fs = out + offset; fs = out + offset;
} }
if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt if (!Encrypt (fs, out + offset, 32))
{ {
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed "); LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed ");
return false; return false;
@ -523,13 +604,11 @@ namespace garlic
// KDF2 // KDF2
if (isStatic) if (isStatic)
{ {
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk) GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bpk)
MixKey (sharedSecret); MixKey (sharedSecret);
} }
else
CreateNonce (1, nonce);
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt if (!Encrypt (payload, out + offset, len))
{ {
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false; return false;
@ -578,16 +657,33 @@ namespace garlic
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
#if OPENSSL_PQ
if (m_PQKeys)
{
size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType);
std::vector<uint8_t> kemCiphertext(cipherTextLen);
m_PQKeys->Encaps (kemCiphertext.data (), sharedSecret);
if (!Encrypt (kemCiphertext.data (), out + offset, cipherTextLen))
{
LogPrint (eLogWarning, "Garlic: NSR ML-KEM ciphertext section AEAD encryption failed");
return false;
}
m_NSREncodedPQKey = std::make_unique<std::vector<uint8_t> > (cipherTextLen + 16);
memcpy (m_NSREncodedPQKey->data (), out + offset, cipherTextLen + 16);
MixHash (out + offset, cipherTextLen + 16);
MixKey (sharedSecret);
offset += cipherTextLen + 16;
}
#endif
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk) if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk)
{ {
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key"); LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
// calculate hash for zero length // calculate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) if (!Encrypt (sharedSecret /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false; return false;
@ -608,6 +704,7 @@ namespace garlic
GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MIN_NUM_GENERATED_TAGS); GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MIN_NUM_GENERATED_TAGS);
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", m_NSRKey, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// encrypt payload // encrypt payload
uint8_t nonce[12]; memset (nonce, 0, 12); // seqn = 0
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset, len + 16, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: NSR payload section AEAD encryption failed");
@ -629,16 +726,34 @@ namespace garlic
memcpy (m_H, m_NSRH, 32); memcpy (m_H, m_NSRH, 32);
MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag) MixHash ((const uint8_t *)&tag, 8); // h = SHA256(h || tag)
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk) MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || bepk)
uint8_t nonce[12]; m_N = 0;
CreateNonce (0, nonce); size_t offset = 40;
if (!i2p::crypto::AEADChaCha20Poly1305 (nonce /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + 40, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad) #if OPENSSL_PQ
if (m_PQKeys)
{
if (m_NSREncodedPQKey)
{
size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType);
memcpy (out + offset, m_NSREncodedPQKey->data (), cipherTextLen + 16);
MixHash (out + offset, cipherTextLen + 16);
offset += cipherTextLen + 16;
}
else
{
LogPrint (eLogWarning, "Garlic: No stored ML-KEM keys");
return false;
}
}
#endif
if (!Encrypt (m_NSRH /* can be anything */, out + offset, 0)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
return false; return false;
} }
MixHash (out + 40, 16); // h = SHA256(h || ciphertext) MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + 56, len + 16, true)) // encrypt uint8_t nonce[12]; memset (nonce, 0, 12);
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_NSRKey, nonce, out + offset + 16, len + 16, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed"); LogPrint (eLogWarning, "Garlic: Next NSR payload section AEAD encryption failed");
return false; return false;
@ -670,13 +785,30 @@ namespace garlic
return false; return false;
} }
MixKey (sharedSecret); MixKey (sharedSecret);
GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk) #if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
{
// decrypt kem_ciphertext section
size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType);
std::vector<uint8_t> kemCiphertext(cipherTextLen);
if (!Decrypt (buf, kemCiphertext.data (), cipherTextLen))
{
LogPrint (eLogWarning, "Garlic: Reply ML-KEM ciphertext section AEAD decryption failed");
return false;
}
MixHash (buf, cipherTextLen + 16);
buf += cipherTextLen + 16;
len -= cipherTextLen + 16;
// decaps
m_PQKeys->Decaps (kemCiphertext.data (), sharedSecret);
MixKey (sharedSecret);
}
#endif
GetOwner ()->Decrypt (bepk, sharedSecret, m_RemoteStaticKeyType); // x25519 (ask, bepk)
MixKey (sharedSecret); MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
// calculate hash for zero length // calculate hash for zero length
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 0, m_H, 32, m_CK + 32, nonce, sharedSecret/* can be anything */, 0, false)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only if (!Decrypt (buf, sharedSecret/* can be anything */, 0)) // decrypt, DECRYPT(k, n, ZEROLEN, ad) verification only
{ {
LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed"); LogPrint (eLogWarning, "Garlic: Reply key section AEAD decryption failed");
return false; return false;
@ -701,6 +833,7 @@ namespace garlic
} }
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32) i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
// decrypt payload // decrypt payload
uint8_t nonce[12]; memset (nonce, 0, 12); // seqn = 0
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keydata, nonce, buf, len - 16, false)) // decrypt
{ {
LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed"); LogPrint (eLogWarning, "Garlic: Payload section AEAD decryption failed");
@ -710,7 +843,8 @@ namespace garlic
if (m_State == eSessionStateNewSessionSent) if (m_State == eSessionStateNewSessionSent)
{ {
m_State = eSessionStateEstablished; m_State = eSessionStateEstablished;
//m_EphemeralKeys = nullptr; // TODO: delete after a while // don't delete m_EpehemralKey and m_PQKeys because delayd NSR's migth come
// done in CleanupReceiveNSRKeys called from NSR tagset destructor
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch (); m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ()); GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
} }
@ -803,6 +937,10 @@ namespace garlic
m_State = eSessionStateEstablished; m_State = eSessionStateEstablished;
m_NSRSendTagset = nullptr; m_NSRSendTagset = nullptr;
m_EphemeralKeys = nullptr; m_EphemeralKeys = nullptr;
#if OPENSSL_PQ
m_PQKeys = nullptr;
m_NSREncodedPQKey = nullptr;
#endif
[[fallthrough]]; [[fallthrough]];
case eSessionStateEstablished: case eSessionStateEstablished:
if (m_SendReverseKey && receiveTagset->GetTagSetID () == m_NextReceiveRatchet->GetReceiveTagSetID ()) if (m_SendReverseKey && receiveTagset->GetTagSetID () == m_NextReceiveRatchet->GetReceiveTagSetID ())
@ -833,7 +971,12 @@ namespace garlic
if (!payload) return nullptr; if (!payload) return nullptr;
size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload); size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload);
if (!len) return nullptr; if (!len) return nullptr;
#if OPENSSL_PQ
auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 :
i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 116));
#else
auto m = NewI2NPMessage (len + 100); // 96 + 4 auto m = NewI2NPMessage (len + 100); // 96 + 4
#endif
m->Align (12); // in order to get buf aligned to 16 (12 + 4) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
@ -848,16 +991,28 @@ namespace garlic
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen)) if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 96; len += 96;
#if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
len += i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 16;
#endif
break; break;
case eSessionStateNewSessionReceived: case eSessionStateNewSessionReceived:
if (!NewSessionReplyMessage (payload, len, buf, m->maxLen)) if (!NewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
#if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
len += i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType) + 16;
#endif
break; break;
case eSessionStateNewSessionReplySent: case eSessionStateNewSessionReplySent:
if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen)) if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr; return nullptr;
len += 72; len += 72;
#if OPENSSL_PQ
if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
len += i2p::crypto::GetMLKEMCipherTextLen (m_RemoteStaticKeyType) + 16;
#endif
break; break;
case eSessionStateOneTime: case eSessionStateOneTime:
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false)) if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false))
@ -913,7 +1068,7 @@ namespace garlic
} }
} }
if (!sendAckRequest && !first && if (!sendAckRequest && !first &&
((!m_AckRequestMsgID && ts > m_LastAckRequestSendTime + ECIESX25519_ACK_REQUEST_INTERVAL) || // regular request ((!m_AckRequestMsgID && ts > m_LastAckRequestSendTime + m_AckRequestInterval) || // regular request
(m_AckRequestMsgID && ts > m_LastAckRequestSendTime + LEASESET_CONFIRMATION_TIMEOUT))) // previous request failed. try again (m_AckRequestMsgID && ts > m_LastAckRequestSendTime + LEASESET_CONFIRMATION_TIMEOUT))) // previous request failed. try again
{ {
// not LeaseSet // not LeaseSet

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -14,10 +14,12 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <array>
#include <list> #include <list>
#include <unordered_map> #include <unordered_map>
#include "Identity.h" #include "Identity.h"
#include "Crypto.h" #include "Crypto.h"
#include "PostQuantum.h"
#include "Garlic.h" #include "Garlic.h"
#include "Tag.h" #include "Tag.h"
@ -33,7 +35,7 @@ namespace garlic
const int ECIESX25519_SESSION_CREATE_TIMEOUT = 3; // in seconds, NSR must be send after NS received const int ECIESX25519_SESSION_CREATE_TIMEOUT = 3; // in seconds, NSR must be send after NS received
const int ECIESX25519_SESSION_ESTABLISH_TIMEOUT = 15; // in seconds const int ECIESX25519_SESSION_ESTABLISH_TIMEOUT = 15; // in seconds
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // in seconds const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // in seconds
const int ECIESX25519_ACK_REQUEST_INTERVAL = 33000; // in milliseconds const int ECIESX25519_DEFAULT_ACK_REQUEST_INTERVAL = 33000; // in milliseconds
const int ECIESX25519_ACK_REQUEST_MAX_NUM_ATTEMPTS = 3; const int ECIESX25519_ACK_REQUEST_MAX_NUM_ATTEMPTS = 3;
const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24; const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
@ -79,8 +81,8 @@ namespace garlic
{ {
public: public:
ReceiveRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session, bool isNS = false): ReceiveRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session, bool isNS = false);
m_Session (session), m_IsNS (isNS) {}; ~ReceiveRatchetTagSet () override;
bool IsNS () const { return m_IsNS; }; bool IsNS () const { return m_IsNS; };
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session; }; std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session; };
@ -164,27 +166,32 @@ namespace garlic
~ECIESX25519AEADRatchetSession (); ~ECIESX25519AEADRatchetSession ();
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0); bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg); std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) override;
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg); std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; } const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); } i2p::data::CryptoKeyType GetRemoteStaticKeyType () const { return m_RemoteStaticKeyType; }
void SetRemoteStaticKey (i2p::data::CryptoKeyType keyType, const uint8_t * key)
{
m_RemoteStaticKeyType = keyType;
memcpy (m_RemoteStaticKey, key, 32);
}
void Terminate () { m_IsTerminated = true; } void Terminate () { m_IsTerminated = true; }
void SetDestination (const i2p::data::IdentHash& dest) void SetDestination (const i2p::data::IdentHash& dest)
{ {
if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest)); if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest));
} }
bool CheckExpired (uint64_t ts); // true is expired bool CheckExpired (uint64_t ts); // true is expired
bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; } bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; }
bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); } bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); }
void CleanupReceiveNSRKeys (); // called from ReceiveRatchetTagSet at Alice's side
bool IsRatchets () const { return true; }; bool IsRatchets () const override { return true; };
bool IsReadyToSend () const { return m_State != eSessionStateNewSessionSent; }; bool IsReadyToSend () const override { return m_State != eSessionStateNewSessionSent; };
bool IsTerminated () const { return m_IsTerminated; } bool IsTerminated () const override { return m_IsTerminated; }
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; }; uint64_t GetLastActivityTimestamp () const override { return m_LastActivityTimestamp; };
bool CleanupUnconfirmedTags (); // return true if unaswered Ack requests, called from I2CP void SetAckRequestInterval (int interval) override { m_AckRequestInterval = interval; };
bool CleanupUnconfirmedTags () override; // return true if unaswered Ack requests, called from I2CP
protected: protected:
@ -192,7 +199,7 @@ namespace garlic
void SetNoiseState (const i2p::crypto::NoiseSymmetricState& state) { GetNoiseState () = state; }; void SetNoiseState (const i2p::crypto::NoiseSymmetricState& state) { GetNoiseState () = state; };
void CreateNonce (uint64_t seqn, uint8_t * nonce); void CreateNonce (uint64_t seqn, uint8_t * nonce);
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index); void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index);
bool MessageConfirmed (uint32_t msgID); bool MessageConfirmed (uint32_t msgID) override;
private: private:
@ -218,10 +225,15 @@ namespace garlic
private: private:
i2p::data::CryptoKeyType m_RemoteStaticKeyType;
uint8_t m_RemoteStaticKey[32]; uint8_t m_RemoteStaticKey[32];
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys; std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
#if OPENSSL_PQ
std::unique_ptr<i2p::crypto::MLKEMKeys> m_PQKeys;
std::unique_ptr<std::vector<uint8_t> > m_NSREncodedPQKey;
#endif
SessionState m_State = eSessionStateNew; SessionState m_State = eSessionStateNew;
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds) uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
m_LastSentTimestamp = 0; // in milliseconds m_LastSentTimestamp = 0; // in milliseconds
@ -235,6 +247,7 @@ namespace garlic
uint64_t m_LastAckRequestSendTime = 0; // milliseconds uint64_t m_LastAckRequestSendTime = 0; // milliseconds
uint32_t m_AckRequestMsgID = 0; uint32_t m_AckRequestMsgID = 0;
int m_AckRequestNumAttempts = 0; int m_AckRequestNumAttempts = 0;
int m_AckRequestInterval = ECIESX25519_DEFAULT_ACK_REQUEST_INTERVAL; // milliseconds
public: public:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -15,6 +15,10 @@
#include <TargetConditionals.h> #include <TargetConditionals.h>
#endif #endif
#if defined(__HAIKU__)
#include <FindDirectory.h>
#endif
#ifdef _WIN32 #ifdef _WIN32
#include <shlobj.h> #include <shlobj.h>
#include <windows.h> #include <windows.h>
@ -169,12 +173,11 @@ namespace fs {
dataDir += "/Library/Application Support/" + appName; dataDir += "/Library/Application Support/" + appName;
return; return;
#elif defined(__HAIKU__) #elif defined(__HAIKU__)
char *home = getenv("HOME"); char home[PATH_MAX]; // /boot/home/config/settings
if (home != NULL && strlen(home) > 0) { if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, home, PATH_MAX) == B_OK)
dataDir = std::string(home) + "/config/settings/" + appName; dataDir = std::string(home) + "/" + appName;
} else { else
dataDir = "/tmp/" + appName; dataDir = "/tmp/" + appName;
}
return; return;
#else /* other unix */ #else /* other unix */
#if defined(ANDROID) #if defined(ANDROID)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -90,10 +90,10 @@ namespace data
} }
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
const char * signature, const char * key) const std::string_view signature, const char * key) const
{ {
uint8_t buf[100], signatureBuf[64]; uint8_t buf[100], signatureBuf[64];
size_t len = family.length (), signatureLen = strlen (signature); size_t len = family.length ();
if (len + 32 > 100) if (len + 32 > 100)
{ {
LogPrint (eLogError, "Family: ", family, " is too long"); LogPrint (eLogError, "Family: ", family, " is too long");
@ -105,7 +105,7 @@ namespace data
memcpy (buf, family.c_str (), len); memcpy (buf, family.c_str (), len);
memcpy (buf + len, (const uint8_t *)ident, 32); memcpy (buf + len, (const uint8_t *)ident, 32);
len += 32; len += 32;
auto signatureBufLen = Base64ToByteStream (signature, signatureLen, signatureBuf, 64); auto signatureBufLen = Base64ToByteStream (signature, signatureBuf, 64);
if (signatureBufLen) if (signatureBufLen)
{ {
EVP_MD_CTX * ctx = EVP_MD_CTX_create (); EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
@ -154,12 +154,7 @@ namespace data
memcpy (buf + len, (const uint8_t *)ident, 32); memcpy (buf + len, (const uint8_t *)ident, 32);
len += 32; len += 32;
signer.Sign (buf, len, signature); signer.Sign (buf, len, signature);
len = Base64EncodingBufferSize (64); sig = ByteStreamToBase64 (signature, 64);
char * b64 = new char[len+1];
len = ByteStreamToBase64 (signature, 64, b64, len);
b64[len] = 0;
sig = b64;
delete[] b64;
} }
else else
LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <string_view>
#include <memory> #include <memory>
#include <openssl/evp.h> #include <openssl/evp.h>
#include "Identity.h" #include "Identity.h"
@ -28,7 +29,7 @@ namespace data
~Families (); ~Families ();
void LoadCertificates (); void LoadCertificates ();
bool VerifyFamily (const std::string& family, const IdentHash& ident, bool VerifyFamily (const std::string& family, const IdentHash& ident,
const char * signature, const char * key = nullptr) const; std::string_view signature, const char * key = nullptr) const;
FamilyID GetFamilyID (const std::string& family) const; FamilyID GetFamilyID (const std::string& family) const;
private: private:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -498,7 +498,8 @@ namespace garlic
buf += 4; // length buf += 4; // length
bool found = false; bool found = false;
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) bool supportsRatchets = SupportsRatchets ();
if (supportsRatchets)
// try ECIESx25519 tag // try ECIESx25519 tag
found = HandleECIESx25519TagMessage (buf, length); found = HandleECIESx25519TagMessage (buf, length);
if (!found) if (!found)
@ -535,7 +536,7 @@ namespace garlic
decryption->Decrypt(buf + 514, length - 514, iv, buf + 514); decryption->Decrypt(buf + 514, length - 514, iv, buf + 514);
HandleAESBlock (buf + 514, length - 514, decryption, msg->from); HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
} }
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) else if (supportsRatchets)
{ {
// otherwise ECIESx25519 // otherwise ECIESx25519
auto ts = i2p::util::GetMillisecondsSinceEpoch (); auto ts = i2p::util::GetMillisecondsSinceEpoch ();
@ -747,31 +748,35 @@ namespace garlic
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet, std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet,
bool requestNewIfNotFound) bool requestNewIfNotFound)
{ {
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD && if (destination->GetEncryptionType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
{ {
ECIESX25519AEADRatchetSessionPtr session; if (SupportsEncryptionType (destination->GetEncryptionType ()))
uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
{ {
session = it->second; ECIESX25519AEADRatchetSessionPtr session;
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ())) uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
{ {
LogPrint (eLogDebug, "Garlic: Session restarted"); session = it->second;
requestNewIfNotFound = true; // it's not a new session if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
session = nullptr; {
LogPrint (eLogDebug, "Garlic: Session restarted");
requestNewIfNotFound = true; // it's not a new session
session = nullptr;
}
} }
if (!session && requestNewIfNotFound)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
session->SetRemoteStaticKey (destination->GetEncryptionType (), staticKey);
}
if (session && destination->IsDestination ())
session->SetDestination (destination->GetIdentHash ()); // NS or NSR
return session;
} }
if (!session && requestNewIfNotFound) else
{ LogPrint (eLogError, "Garlic: Non-supported encryption type ", destination->GetEncryptionType ());
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
session->SetRemoteStaticKey (staticKey);
}
if (session && destination->IsDestination ())
session->SetDestination (destination->GetIdentHash ()); // NS or NSR
return session;
} }
else else
{ {
@ -999,7 +1004,8 @@ namespace garlic
i2p::fs::Remove (it); i2p::fs::Remove (it);
} }
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len) void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len,
ECIESX25519AEADRatchetSession * from)
{ {
const uint8_t * buf1 = buf; const uint8_t * buf1 = buf;
uint8_t flag = buf[0]; buf++; // flag uint8_t flag = buf[0]; buf++; // flag
@ -1019,7 +1025,7 @@ namespace garlic
buf += 4; // expiration buf += 4; // expiration
ptrdiff_t offset = buf - buf1; ptrdiff_t offset = buf - buf1;
if (offset <= (int)len) if (offset <= (int)len)
HandleCloveI2NPMessage (typeID, buf, len - offset, msgID); HandleCloveI2NPMessage (typeID, buf, len - offset, msgID, from);
else else
LogPrint (eLogError, "Garlic: Clove is too long"); LogPrint (eLogError, "Garlic: Clove is too long");
break; break;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -116,6 +116,7 @@ namespace garlic
virtual bool IsReadyToSend () const { return true; }; virtual bool IsReadyToSend () const { return true; };
virtual bool IsTerminated () const { return !GetOwner (); }; virtual bool IsTerminated () const { return !GetOwner (); };
virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only
virtual void SetAckRequestInterval (int interval) {}; // in milliseconds, override in ECIESX25519AEADRatchetSession
void SetLeaseSetUpdated () void SetLeaseSetUpdated ()
{ {
@ -256,7 +257,7 @@ namespace garlic
uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset); uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session); void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
void RemoveECIESx25519Session (const uint8_t * staticKey); void RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len); void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len, ECIESX25519AEADRatchetSession * from);
uint8_t * GetPayloadBuffer (); uint8_t * GetPayloadBuffer ();
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg); virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
@ -265,13 +266,18 @@ namespace garlic
virtual std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () = 0; // TODO virtual std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () = 0; // TODO
virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0; virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0;
virtual i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const
{
return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? GetIdentity ()->GetCryptoKeyType () : 0;
}
protected: protected:
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
bool HandleECIESx25519TagMessage (uint8_t * buf, size_t len); // return true if found bool HandleECIESx25519TagMessage (uint8_t * buf, size_t len); // return true if found
virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only
virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) = 0; virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
size_t len, uint32_t msgID, ECIESX25519AEADRatchetSession * from) = 0;
void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg); void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
void HandleDeliveryStatusMessage (uint32_t msgID); void HandleDeliveryStatusMessage (uint32_t msgID);
@ -280,6 +286,7 @@ namespace garlic
private: private:
bool SupportsRatchets () const { return GetRatchetsHighestCryptoType () > 0; }
void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption, void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from); std::shared_ptr<i2p::tunnel::InboundTunnel> from);
void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -10,6 +10,7 @@
#include <utility> #include <utility>
#include <stdio.h> #include <stdio.h>
#include <ctime> #include <ctime>
#include <charconv>
#include "util.h" #include "util.h"
#include "Base.h" #include "Base.h"
#include "HTTP.h" #include "HTTP.h"
@ -18,54 +19,51 @@ namespace i2p
{ {
namespace http namespace http
{ {
const std::vector<std::string> HTTP_METHODS = { // list of valid HTTP methods
static constexpr std::array<std::string_view, 16> HTTP_METHODS =
{
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323 "COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323
}; };
const std::vector<std::string> HTTP_VERSIONS = {
// list of valid HTTP versions
static constexpr std::array<std::string_view, 2> HTTP_VERSIONS =
{
"HTTP/1.0", "HTTP/1.1" "HTTP/1.0", "HTTP/1.1"
}; };
const std::vector<const char *> weekdays = {
static constexpr std::array<const char *, 7> weekdays =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
}; };
const std::vector<const char *> months = {
static constexpr std::array<const char *, 12> months =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}; };
inline bool is_http_version(const std::string & str) { static inline bool is_http_version(std::string_view str)
{
return std::find(HTTP_VERSIONS.begin(), HTTP_VERSIONS.end(), str) != std::end(HTTP_VERSIONS); return std::find(HTTP_VERSIONS.begin(), HTTP_VERSIONS.end(), str) != std::end(HTTP_VERSIONS);
} }
inline bool is_http_method(const std::string & str) { static inline bool is_http_method(std::string_view str)
{
return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS); return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS);
} }
static void strsplit(std::stringstream& ss, std::vector<std::string> &tokens, char delim, std::size_t limit = 0) static void strsplit(std::string_view line, std::vector<std::string_view> &tokens, char delim, std::size_t limit = 0)
{ {
std::size_t count = 0; size_t count = 0, pos;
std::string token; while ((pos = line.find (delim)) != line.npos)
while (1)
{ {
count++; count++;
if (limit > 0 && count >= limit) if (limit > 0 && count >= limit) delim = '\n'; // reset delimiter
delim = '\n'; /* reset delimiter */ tokens.push_back (line.substr (0, pos));
if (!std::getline(ss, token, delim)) line = line.substr (pos + 1);
break;
tokens.push_back(token);
} }
} if (!line.empty ()) tokens.push_back (line);
static void strsplit(const std::string & line, std::vector<std::string> &tokens, char delim, std::size_t limit = 0)
{
std::stringstream ss{line};
strsplit (ss, tokens, delim, limit);
}
static void strsplit(std::string_view line, std::vector<std::string> &tokens, char delim, std::size_t limit = 0)
{
std::stringstream ss{std::string(line)};
strsplit (ss, tokens, delim, limit);
} }
static std::pair<std::string, std::string> parse_header_line(std::string_view line) static std::pair<std::string, std::string> parse_header_line(std::string_view line)
@ -211,8 +209,9 @@ namespace http
return true; return true;
} }
bool URL::parse_query(std::map<std::string, std::string> & params) { bool URL::parse_query(std::map<std::string, std::string> & params)
std::vector<std::string> tokens; {
std::vector<std::string_view> tokens;
strsplit(query, tokens, '&'); strsplit(query, tokens, '&');
params.clear(); params.clear();
@ -308,8 +307,9 @@ namespace http
if (expect == REQ_LINE) if (expect == REQ_LINE)
{ {
std::string_view line = str.substr(pos, eol - pos); std::string_view line = str.substr(pos, eol - pos);
std::vector<std::string> tokens; std::vector<std::string_view> tokens;
strsplit(line, tokens, ' '); strsplit(line, tokens, ' ');
if (tokens.size() != 3) if (tokens.size() != 3)
return -1; return -1;
if (!is_http_method(tokens[0])) if (!is_http_method(tokens[0]))
@ -333,11 +333,11 @@ namespace http
else else
return -1; return -1;
} }
pos = eol + strlen(CRLF); pos = eol + CRLF.length();
if (pos >= eoh) if (pos >= eoh)
break; break;
} }
return eoh + strlen(HTTP_EOH); return eoh + HTTP_EOH.length();
} }
void HTTPReq::write(std::ostream & o) void HTTPReq::write(std::ostream & o)
@ -381,7 +381,7 @@ namespace http
} }
} }
std::string HTTPReq::GetHeader (const std::string& name) const std::string HTTPReq::GetHeader (std::string_view name) const
{ {
for (auto& it : headers) for (auto& it : headers)
if (it.first == name) if (it.first == name)
@ -389,7 +389,7 @@ namespace http
return ""; return "";
} }
size_t HTTPReq::GetNumHeaders (const std::string& name) const size_t HTTPReq::GetNumHeaders (std::string_view name) const
{ {
size_t num = 0; size_t num = 0;
for (auto& it : headers) for (auto& it : headers)
@ -451,13 +451,15 @@ namespace http
if (expect == RES_LINE) if (expect == RES_LINE)
{ {
std::string_view line = str.substr(pos, eol - pos); std::string_view line = str.substr(pos, eol - pos);
std::vector<std::string> tokens; std::vector<std::string_view> tokens;
strsplit(line, tokens, ' ', 3); strsplit(line, tokens, ' ', 3);
if (tokens.size() != 3) if (tokens.size() != 3)
return -1; return -1;
if (!is_http_version(tokens[0])) if (!is_http_version(tokens[0]))
return -1; return -1;
code = atoi(tokens[1].c_str()); auto res = std::from_chars(tokens[1].data (), tokens[1].data() + tokens[1].size(), code);
if (res.ec != std::errc())
return -1;
if (code < 100 || code >= 600) if (code < 100 || code >= 600)
return -1; return -1;
/* all ok */ /* all ok */
@ -474,11 +476,11 @@ namespace http
else else
return -1; return -1;
} }
pos = eol + strlen(CRLF); pos = eol + CRLF.length();
if (pos >= eoh) if (pos >= eoh)
break; break;
} }
return eoh + strlen(HTTP_EOH); return eoh + HTTP_EOH.length();
} }
std::string HTTPRes::to_string() { std::string HTTPRes::to_string() {
@ -503,9 +505,11 @@ namespace http
return ss.str(); return ss.str();
} }
const char * HTTPCodeToStatus(int code) { std::string_view HTTPCodeToStatus(int code)
const char *ptr; {
switch (code) { std::string_view ptr;
switch (code)
{
case 105: ptr = "Name Not Resolved"; break; case 105: ptr = "Name Not Resolved"; break;
/* success */ /* success */
case 200: ptr = "OK"; break; case 200: ptr = "OK"; break;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -21,10 +21,8 @@ namespace i2p
{ {
namespace http namespace http
{ {
const char CRLF[] = "\r\n"; /**< HTTP line terminator */ constexpr std::string_view CRLF = "\r\n"; /**< HTTP line terminator */
const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */ constexpr std::string_view HTTP_EOH = "\r\n\r\n"; /**< HTTP end-of-headers mark */
extern const std::vector<std::string> HTTP_METHODS; /**< list of valid HTTP methods */
extern const std::vector<std::string> HTTP_VERSIONS; /**< list of valid HTTP versions */
struct URL struct URL
{ {
@ -103,8 +101,8 @@ namespace http
void UpdateHeader (const std::string& name, const std::string& value); void UpdateHeader (const std::string& name, const std::string& value);
void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt
void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); }; void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); };
std::string GetHeader (const std::string& name) const; std::string GetHeader (std::string_view name) const;
size_t GetNumHeaders (const std::string& name) const; size_t GetNumHeaders (std::string_view name) const;
size_t GetNumHeaders () const { return headers.size (); }; size_t GetNumHeaders () const { return headers.size (); };
}; };
@ -154,7 +152,7 @@ namespace http
* @param code HTTP code [100, 599] * @param code HTTP code [100, 599]
* @return Immutable string with status * @return Immutable string with status
*/ */
const char * HTTPCodeToStatus(int code); std::string_view HTTPCodeToStatus(int code);
/** /**
* @brief Replaces %-encoded characters in string with their values * @brief Replaces %-encoded characters in string with their values

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -10,6 +10,7 @@
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Log.h" #include "Log.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "CryptoKey.h"
#include "Identity.h" #include "Identity.h"
namespace i2p namespace i2p
@ -27,18 +28,15 @@ namespace data
size_t Identity::FromBuffer (const uint8_t * buf, size_t len) size_t Identity::FromBuffer (const uint8_t * buf, size_t len)
{ {
if ( len < DEFAULT_IDENTITY_SIZE ) { if (len < DEFAULT_IDENTITY_SIZE) return 0; // buffer too small, don't overflow
// buffer too small, don't overflow memcpy (this, buf, DEFAULT_IDENTITY_SIZE);
return 0;
}
memcpy (publicKey, buf, DEFAULT_IDENTITY_SIZE);
return DEFAULT_IDENTITY_SIZE; return DEFAULT_IDENTITY_SIZE;
} }
IdentHash Identity::Hash () const IdentHash Identity::Hash () const
{ {
IdentHash hash; IdentHash hash;
SHA256(publicKey, DEFAULT_IDENTITY_SIZE, hash); SHA256((const uint8_t *)this, DEFAULT_IDENTITY_SIZE, hash);
return hash; return hash;
} }
@ -122,6 +120,16 @@ namespace data
memcpy (m_StandardIdentity.signingKey, signingKey, i2p::crypto::GOSTR3410_512_PUBLIC_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey, signingKey, i2p::crypto::GOSTR3410_512_PUBLIC_KEY_LENGTH);
break; break;
} }
#if OPENSSL_PQ
case SIGNING_KEY_TYPE_MLDSA44:
{
memcpy (m_StandardIdentity, signingKey, 384);
excessLen = i2p::crypto::MLDSA44_PUBLIC_KEY_LENGTH - 384;
excessBuf = new uint8_t[excessLen];
memcpy (excessBuf, signingKey + 384, excessLen);
break;
}
#endif
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported"); LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported");
} }
@ -262,23 +270,19 @@ namespace data
return fullLen; return fullLen;
} }
size_t IdentityEx::FromBase64(const std::string& s) size_t IdentityEx::FromBase64(std::string_view s)
{ {
const size_t slen = s.length(); std::vector<uint8_t> buf(s.length ()); // binary data can't exceed base64
std::vector<uint8_t> buf(slen); // binary data can't exceed base64 auto len = Base64ToByteStream (s, buf.data(), buf.size ());
const size_t len = Base64ToByteStream (s.c_str(), slen, buf.data(), slen);
return FromBuffer (buf.data(), len); return FromBuffer (buf.data(), len);
} }
std::string IdentityEx::ToBase64 () const std::string IdentityEx::ToBase64 () const
{ {
const size_t bufLen = GetFullLen(); const size_t bufLen = GetFullLen();
const size_t strLen = Base64EncodingBufferSize(bufLen);
std::vector<uint8_t> buf(bufLen); std::vector<uint8_t> buf(bufLen);
std::vector<char> str(strLen);
size_t l = ToBuffer (buf.data(), bufLen); size_t l = ToBuffer (buf.data(), bufLen);
size_t l1 = i2p::data::ByteStreamToBase64 (buf.data(), l, str.data(), strLen); return i2p::data::ByteStreamToBase64 (buf.data(), l);
return std::string (str.data(), l1);
} }
size_t IdentityEx::GetSigningPublicKeyLen () const size_t IdentityEx::GetSigningPublicKeyLen () const
@ -355,6 +359,10 @@ namespace data
return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512); return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512);
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
return new i2p::crypto::RedDSA25519Verifier (); return new i2p::crypto::RedDSA25519Verifier ();
#if OPENSSL_PQ
case SIGNING_KEY_TYPE_MLDSA44:
return new i2p::crypto::MLDSA44Verifier ();
#endif
case SIGNING_KEY_TYPE_RSA_SHA256_2048: case SIGNING_KEY_TYPE_RSA_SHA256_2048:
case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA384_3072:
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
@ -376,6 +384,18 @@ namespace data
auto keyLen = verifier->GetPublicKeyLen (); auto keyLen = verifier->GetPublicKeyLen ();
if (keyLen <= 128) if (keyLen <= 128)
verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen); verifier->SetPublicKey (m_StandardIdentity.signingKey + 128 - keyLen);
#if OPENSSL_PQ
else if (keyLen > 384)
{
// for post-quantum
uint8_t * signingKey = new uint8_t[keyLen];
memcpy (signingKey, m_StandardIdentity.signingKey, 384);
size_t excessLen = keyLen - 384;
memcpy (signingKey + 384, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
verifier->SetPublicKey (signingKey);
delete[] signingKey;
}
#endif
else else
{ {
// for P521 // for P521
@ -399,15 +419,14 @@ namespace data
return std::make_shared<i2p::crypto::ElGamalEncryptor>(key); return std::make_shared<i2p::crypto::ElGamalEncryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetEncryptor>(key); return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetEncryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
return std::make_shared<i2p::crypto::ECIESP256Encryptor>(key); return std::make_shared<i2p::crypto::ECIESP256Encryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
return std::make_shared<i2p::crypto::ECIESGOSTR3410Encryptor>(key);
break;
default: default:
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType); LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType);
}; };
@ -551,26 +570,18 @@ namespace data
return ret; return ret;
} }
size_t PrivateKeys::FromBase64(const std::string& s) size_t PrivateKeys::FromBase64(std::string_view s)
{ {
uint8_t * buf = new uint8_t[s.length ()]; std::vector<uint8_t> buf(s.length ());
size_t l = i2p::data::Base64ToByteStream (s.c_str (), s.length (), buf, s.length ()); size_t l = i2p::data::Base64ToByteStream (s, buf.data (), buf.size ());
size_t ret = FromBuffer (buf, l); return FromBuffer (buf.data (), l);
delete[] buf;
return ret;
} }
std::string PrivateKeys::ToBase64 () const std::string PrivateKeys::ToBase64 () const
{ {
uint8_t * buf = new uint8_t[GetFullLen ()]; std::vector<uint8_t> buf(GetFullLen ());
char * str = new char[GetFullLen ()*2]; size_t l = ToBuffer (buf.data (), buf.size ());
size_t l = ToBuffer (buf, GetFullLen ()); return i2p::data::ByteStreamToBase64 (buf.data (), l);
size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, str, GetFullLen ()*2);
str[l1] = 0;
delete[] buf;
std::string ret(str);
delete[] str;
return ret;
} }
void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const
@ -633,6 +644,11 @@ namespace data
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
return new i2p::crypto::RedDSA25519Signer (priv); return new i2p::crypto::RedDSA25519Signer (priv);
break; break;
#if OPENSSL_PQ
case SIGNING_KEY_TYPE_MLDSA44:
return new i2p::crypto::MLDSA44Signer (priv);
break;
#endif
default: default:
LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported"); LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
} }
@ -646,8 +662,7 @@ namespace data
size_t PrivateKeys::GetPrivateKeyLen () const size_t PrivateKeys::GetPrivateKeyLen () const
{ {
// private key length always 256, but type 4 return i2p::crypto::GetCryptoPrivateKeyLen (m_Public->GetCryptoKeyType ());
return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256;
} }
uint8_t * PrivateKeys::GetPadding() uint8_t * PrivateKeys::GetPadding()
@ -673,15 +688,14 @@ namespace data
return std::make_shared<i2p::crypto::ElGamalDecryptor>(key); return std::make_shared<i2p::crypto::ElGamalDecryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key); return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key); return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
return std::make_shared<i2p::crypto::ECIESGOSTR3410Decryptor>(key);
break;
default: default:
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType); LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType);
}; };
@ -728,9 +742,7 @@ namespace data
case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA384_3072:
case SIGNING_KEY_TYPE_RSA_SHA512_4096: case SIGNING_KEY_TYPE_RSA_SHA512_4096:
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA"); LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]]; [[fallthrough]];
#endif
// no break here // no break here
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub); i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
@ -744,6 +756,11 @@ namespace data
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub); i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub);
break; break;
#if OPENSSL_PQ
case SIGNING_KEY_TYPE_MLDSA44:
i2p::crypto::CreateMLDSA44RandomKeys (priv, pub);
break;
#endif
default: default:
LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1 i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
@ -758,13 +775,12 @@ namespace data
i2p::crypto::GenerateElGamalKeyPair(priv, pub); i2p::crypto::GenerateElGamalKeyPair(priv, pub);
break; break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
i2p::crypto::CreateECIESP256RandomKeys (priv, pub); i2p::crypto::CreateECIESP256RandomKeys (priv, pub);
break; break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub);
break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
case CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub);
break; break;
default: default:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -12,14 +12,19 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <string_view>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "Base.h" #include "Base.h"
#include "Signature.h" #include "Signature.h"
#include "CryptoKey.h"
namespace i2p namespace i2p
{ {
namespace crypto
{
class CryptoKeyEncryptor;
class CryptoKeyDecryptor;
}
namespace data namespace data
{ {
typedef Tag<32> IdentHash; typedef Tag<32> IdentHash;
@ -54,6 +59,8 @@ namespace data
Identity& operator=(const Keys& keys); Identity& operator=(const Keys& keys);
size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (const uint8_t * buf, size_t len);
IdentHash Hash () const; IdentHash Hash () const;
operator uint8_t * () { return reinterpret_cast<uint8_t *>(this); }
operator const uint8_t * () const { return reinterpret_cast<const uint8_t *>(this); }
}; };
Keys CreateRandomKeys (); Keys CreateRandomKeys ();
@ -63,8 +70,9 @@ namespace data
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1;
const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD = 4; const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD = 4;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD = 5;
const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD = 6;
const uint16_t CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD = 7;
const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0;
const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1; const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1;
@ -74,10 +82,11 @@ namespace data
const uint16_t SIGNING_KEY_TYPE_RSA_SHA384_3072 = 5; const uint16_t SIGNING_KEY_TYPE_RSA_SHA384_3072 = 5;
const uint16_t SIGNING_KEY_TYPE_RSA_SHA512_4096 = 6; const uint16_t SIGNING_KEY_TYPE_RSA_SHA512_4096 = 6;
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 = 7; const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 = 7;
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519ph = 8; // not implemented const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519ph = 8; // since openssl 3.0.0
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9; const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9;
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB
const uint16_t SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 = 11; // for LeaseSet2 only const uint16_t SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 = 11; // for LeaseSet2 only
const uint16_t SIGNING_KEY_TYPE_MLDSA44 = 12;
typedef uint16_t SigningKeyType; typedef uint16_t SigningKeyType;
typedef uint16_t CryptoKeyType; typedef uint16_t CryptoKeyType;
@ -99,7 +108,7 @@ namespace data
size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (const uint8_t * buf, size_t len);
size_t ToBuffer (uint8_t * buf, size_t len) const; size_t ToBuffer (uint8_t * buf, size_t len) const;
size_t FromBase64(const std::string& s); size_t FromBase64(std::string_view s);
std::string ToBase64 () const; std::string ToBase64 () const;
const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; const Identity& GetStandardIdentity () const { return m_StandardIdentity; };
@ -133,7 +142,7 @@ namespace data
IdentHash m_IdentHash; IdentHash m_IdentHash;
std::unique_ptr<i2p::crypto::Verifier> m_Verifier; std::unique_ptr<i2p::crypto::Verifier> m_Verifier;
size_t m_ExtendedLen; size_t m_ExtendedLen;
uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; // TODO: support PQ keys
}; };
size_t GetIdentityBufferLen (const uint8_t * buf, size_t len); // return actual identity length in buffer size_t GetIdentityBufferLen (const uint8_t * buf, size_t len); // return actual identity length in buffer
@ -162,7 +171,7 @@ namespace data
size_t FromBuffer (const uint8_t * buf, size_t len); size_t FromBuffer (const uint8_t * buf, size_t len);
size_t ToBuffer (uint8_t * buf, size_t len) const; size_t ToBuffer (uint8_t * buf, size_t len) const;
size_t FromBase64(const std::string& s); size_t FromBase64(std::string_view s);
std::string ToBase64 () const; std::string ToBase64 () const;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (const uint8_t * key) const; std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (const uint8_t * key) const;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -14,6 +14,7 @@
#include "Timestamp.h" #include "Timestamp.h"
#include "NetDb.hpp" #include "NetDb.hpp"
#include "Tunnel.h" #include "Tunnel.h"
#include "CryptoKey.h"
#include "LeaseSet.h" #include "LeaseSet.h"
namespace i2p namespace i2p
@ -399,6 +400,7 @@ namespace data
offset += propertiesLen; // skip for now. TODO: implement properties offset += propertiesLen; // skip for now. TODO: implement properties
// key sections // key sections
CryptoKeyType preferredKeyType = m_EncryptionType; CryptoKeyType preferredKeyType = m_EncryptionType;
m_EncryptionType = 0;
bool preferredKeyFound = false; bool preferredKeyFound = false;
if (offset + 1 > len) return 0; if (offset + 1 > len) return 0;
int numKeySections = buf[offset]; offset++; int numKeySections = buf[offset]; offset++;
@ -410,13 +412,21 @@ namespace data
if (offset + encryptionKeyLen > len) return 0; if (offset + encryptionKeyLen > len) return 0;
if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only
{ {
// we pick first valid key if preferred not found // we pick max key type if preferred not found
auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset); #if !OPENSSL_PQ
if (encryptor && (!m_Encryptor || keyType == preferredKeyType)) if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported
#endif
{ {
m_Encryptor = encryptor; // TODO: atomic if (keyType == preferredKeyType || !m_Encryptor || keyType > m_EncryptionType)
m_EncryptionType = keyType; {
if (keyType == preferredKeyType) preferredKeyFound = true; auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset);
if (encryptor)
{
m_Encryptor = encryptor; // TODO: atomic
m_EncryptionType = keyType;
if (keyType == preferredKeyType) preferredKeyFound = true;
}
}
} }
} }
offset += encryptionKeyLen; offset += encryptionKeyLen;
@ -838,7 +848,7 @@ namespace data
} }
LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
const KeySections& encryptionKeys, const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels, const EncryptionKeys& encryptionKeys, const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels,
bool isPublic, uint64_t publishedTimestamp, bool isPublishedEncrypted): bool isPublic, uint64_t publishedTimestamp, bool isPublishedEncrypted):
LocalLeaseSet (keys.GetPublic (), nullptr, 0) LocalLeaseSet (keys.GetPublic (), nullptr, 0)
{ {
@ -848,7 +858,7 @@ namespace data
if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES;
size_t keySectionsLen = 0; size_t keySectionsLen = 0;
for (const auto& it: encryptionKeys) for (const auto& it: encryptionKeys)
keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/; keySectionsLen += 2/*key type*/ + 2/*key len*/ + it->pub.size()/*key*/;
m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ + m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ +
1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen (); 1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen ();
uint16_t flags = 0; uint16_t flags = 0;
@ -883,9 +893,9 @@ namespace data
m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key
for (const auto& it: encryptionKeys) for (const auto& it: encryptionKeys)
{ {
htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type htobe16buf (m_Buffer + offset, it->keyType); offset += 2; // key type
htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len htobe16buf (m_Buffer + offset, it->pub.size()); offset += 2; // key len
memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key memcpy (m_Buffer + offset, it->pub.data(), it->pub.size()); offset += it->pub.size(); // key
} }
// leases // leases
uint32_t expirationTime = 0; // in seconds uint32_t expirationTime = 0; // in seconds

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -12,12 +12,14 @@
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <vector> #include <vector>
#include <list>
#include <set> #include <set>
#include <memory> #include <memory>
#include "Identity.h" #include "Identity.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "I2PEndian.h" #include "I2PEndian.h"
#include "Blinding.h" #include "Blinding.h"
#include "CryptoKey.h"
namespace i2p namespace i2p
{ {
@ -150,8 +152,8 @@ namespace data
public: public:
LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // store type 5, called from local netdb only
uint8_t GetStoreType () const { return m_StoreType; }; uint8_t GetStoreType () const { return m_StoreType; };
uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; }; uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; };
bool IsPublic () const { return m_IsPublic; }; bool IsPublic () const { return m_IsPublic; };
@ -247,15 +249,10 @@ namespace data
{ {
public: public:
struct KeySection typedef std::list<std::shared_ptr<const i2p::crypto::LocalEncryptionKey> > EncryptionKeys;
{
uint16_t keyType, keyLen;
const uint8_t * encryptionPublicKey;
};
typedef std::vector<KeySection> KeySections;
LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
const KeySections& encryptionKeys, const EncryptionKeys& encryptionKeys,
const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels, const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels,
bool isPublic, uint64_t publishedTimestamp, bool isPublic, uint64_t publishedTimestamp,
bool isPublishedEncrypted = false); bool isPublishedEncrypted = false);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -145,10 +145,12 @@ namespace transport
// 2 bytes reserved // 2 bytes reserved
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsA, rounded to seconds
// 4 bytes reserved // 4 bytes reserved
// sign and encrypt options, use m_H as AD // encrypt options
uint8_t nonce[12]; if (!Encrypt (options, m_SessionRequestBuffer + 32, 16))
memset (nonce, 0, 12); // set nonce to zero {
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt LogPrint (eLogWarning, "NTCP2: SessionRequest failed to encrypt options");
return false;
}
return true; return true;
} }
@ -167,14 +169,16 @@ namespace transport
memset (options, 0, 16); memset (options, 0, 16);
htobe16buf (options + 2, paddingLen); // padLen htobe16buf (options + 2, paddingLen); // padLen
htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds
// sign and encrypt options, use m_H as AD // encrypt options
uint8_t nonce[12]; if (!Encrypt (options, m_SessionCreatedBuffer + 32, 16))
memset (nonce, 0, 12); // set nonce to zero {
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt LogPrint (eLogWarning, "NTCP2: SessionCreated failed to encrypt options");
return false;
}
return true; return true;
} }
void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce) bool NTCP2Establisher::CreateSessionConfirmedMessagePart1 ()
{ {
// update AD // update AD
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
@ -182,19 +186,28 @@ namespace transport
if (paddingLength > 0) if (paddingLength > 0)
MixHash (m_SessionCreatedBuffer + 64, paddingLength); MixHash (m_SessionCreatedBuffer + 64, paddingLength);
// part1 48 bytes // part1 48 bytes, n = 1
i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt if (!Encrypt (i2p::context.GetNTCP2StaticPublicKey (), m_SessionConfirmedBuffer, 32))
{
LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part1");
return false;
}
return true;
} }
bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce) bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 ()
{ {
// part 2 // part 2
// update AD again // update AD again
MixHash (m_SessionConfirmedBuffer, 48); MixHash (m_SessionConfirmedBuffer, 48);
// encrypt m3p2, it must be filled in SessionRequest // encrypt m3p2, it must be filled in SessionRequest
if (!KDF3Alice ()) return false; if (!KDF3Alice ()) return false; // MixKey, n = 0
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt if (!Encrypt (m3p2, m3p2, m3p2Len - 16))
{
LogPrint (eLogWarning, "NTCP2: SessionConfirmed failed to encrypt part2");
return false;
}
// update h again // update h again
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext) MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
return true; return true;
@ -214,10 +227,9 @@ namespace transport
LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed"); LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed");
return false; return false;
} }
// verify MAC and decrypt options block (32 bytes), use m_H as AD // verify MAC and decrypt options block (32 bytes)
uint8_t nonce[12], options[16]; uint8_t options[16];
memset (nonce, 0, 12); // set nonce to zero if (Decrypt (m_SessionRequestBuffer + 32, options, 16))
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, GetH (), 32, GetK (), nonce, options, 16, false)) // decrypt
{ {
// options // options
if (options[0] && options[0] != i2p::context.GetNetID ()) if (options[0] && options[0] != i2p::context.GetNetID ())
@ -274,9 +286,7 @@ namespace transport
} }
// decrypt and verify MAC // decrypt and verify MAC
uint8_t payload[16]; uint8_t payload[16];
uint8_t nonce[12]; if (Decrypt (m_SessionCreatedBuffer + 32, payload, 16))
memset (nonce, 0, 12); // set nonce to zero
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, GetH (), 32, GetK (), nonce, payload, 16, false)) // decrypt
{ {
// options // options
paddingLen = bufbe16toh(payload + 2); paddingLen = bufbe16toh(payload + 2);
@ -297,7 +307,7 @@ namespace transport
return true; return true;
} }
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce) bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 ()
{ {
// update AD // update AD
MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload
@ -305,7 +315,8 @@ namespace transport
if (paddingLength > 0) if (paddingLength > 0)
MixHash (m_SessionCreatedBuffer + 64, paddingLength); MixHash (m_SessionCreatedBuffer + 64, paddingLength);
if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, GetH (), 32, GetK (), nonce, m_RemoteStaticKey, 32, false)) // decrypt S // decrypt S, n = 1
if (!Decrypt (m_SessionConfirmedBuffer, m_RemoteStaticKey, 32))
{ {
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
return false; return false;
@ -313,17 +324,17 @@ namespace transport
return true; return true;
} }
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf)
{ {
// update AD again // update AD again
MixHash (m_SessionConfirmedBuffer, 48); MixHash (m_SessionConfirmedBuffer, 48);
if (!KDF3Bob ()) if (!KDF3Bob ()) // MixKey, n = 0
{ {
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed"); LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed");
return false; return false;
} }
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt if (Decrypt (m_SessionConfirmedBuffer + 48, m3p2Buf, m3p2Len - 16))
// calculate new h again for KDF data // calculate new h again for KDF data
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext) MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
else else
@ -657,11 +668,12 @@ namespace transport
void NTCP2Session::SendSessionConfirmed () void NTCP2Session::SendSessionConfirmed ()
{ {
uint8_t nonce[12]; if (!m_Establisher->CreateSessionConfirmedMessagePart1 ())
CreateNonce (1, nonce); // set nonce to 1 {
m_Establisher->CreateSessionConfirmedMessagePart1 (nonce); boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
memset (nonce, 0, 12); // set nonce back to 0 return;
if (!m_Establisher->CreateSessionConfirmedMessagePart2 (nonce)) }
if (!m_Establisher->CreateSessionConfirmedMessagePart2 ())
{ {
LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed"); LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed");
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ())); boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
@ -740,14 +752,11 @@ namespace transport
// run on establisher thread // run on establisher thread
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
// part 1 // part 1
uint8_t nonce[12]; if (m_Establisher->ProcessSessionConfirmedMessagePart1 ())
CreateNonce (1, nonce);
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
{ {
// part 2 // part 2
auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC
memset (nonce, 0, 12); // set nonce to 0 again if (m_Establisher->ProcessSessionConfirmedMessagePart2 (buf->data ())) // TODO:handle in establisher thread
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf->data ())) // TODO:handle in establisher thread
{ {
// payload // payload
// RI block must be first // RI block must be first
@ -819,15 +828,20 @@ namespace transport
Terminate (); Terminate ();
return; return;
} }
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
bool isOlder = false;
if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ()) if (ri.GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
{ {
// received RouterInfo is older than one in netdb // received RouterInfo is older than one in netdb
profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile isOlder = true;
if (profile && profile->IsDuplicated ()) if (ri1->HasProfile ())
{ {
SendTerminationAndTerminate (eNTCP2Banned); auto profile = i2p::data::GetRouterProfile (ri1->GetIdentHash ()); // retrieve profile
return; if (profile && profile->IsDuplicated ())
{
SendTerminationAndTerminate (eNTCP2Banned);
return;
}
} }
} }
@ -844,8 +858,12 @@ namespace transport
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data () + 1, addr->host.to_v6 ().to_bytes ().data () + 1, 7) : // from the same yggdrasil subnet
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), addr->host.to_v6 ().to_bytes ().data (), 8)))) // temporary address
{ {
if (profile) // older router? if (isOlder) // older router?
profile->Duplicated (); // mark router as duplicated in profile i2p::data::UpdateRouterProfile (ri1->GetIdentHash (),
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Duplicated (); // mark router as duplicated in profile
});
else else
LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ()); LogPrint (eLogInfo, "NTCP2: Host mismatch between published address ", addr->host, " and actual endpoint ", m_RemoteEndpoint.address ());
SendTerminationAndTerminate (eNTCP2Banned); SendTerminationAndTerminate (eNTCP2Banned);

View file

@ -91,7 +91,6 @@ namespace transport
const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob const uint8_t * GetRemotePub () const { return m_RemoteEphemeralPublicKey; }; // Y for Alice and X for Bob
uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set uint8_t * GetRemotePub () { return m_RemoteEphemeralPublicKey; }; // to set
const uint8_t * GetK () const { return m_CK + 32; };
const uint8_t * GetCK () const { return m_CK; }; const uint8_t * GetCK () const { return m_CK; };
const uint8_t * GetH () const { return m_H; }; const uint8_t * GetH () const { return m_H; };
@ -108,13 +107,13 @@ namespace transport
bool CreateSessionRequestMessage (std::mt19937& rng); bool CreateSessionRequestMessage (std::mt19937& rng);
bool CreateSessionCreatedMessage (std::mt19937& rng); bool CreateSessionCreatedMessage (std::mt19937& rng);
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce); bool CreateSessionConfirmedMessagePart1 ();
bool CreateSessionConfirmedMessagePart2 (const uint8_t * nonce); bool CreateSessionConfirmedMessagePart2 ();
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew); bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
bool ProcessSessionCreatedMessage (uint16_t& paddingLen); bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce); bool ProcessSessionConfirmedMessagePart1 ();
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf); bool ProcessSessionConfirmedMessagePart2 (uint8_t * m3p2Buf);
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys; std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
uint8_t m_RemoteEphemeralPublicKey[32]; // x25519 uint8_t m_RemoteEphemeralPublicKey[32]; // x25519

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -10,7 +10,6 @@
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <random>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <stdexcept> #include <stdexcept>
@ -40,7 +39,7 @@ namespace data
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr),
m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true),
m_LastExploratorySelectionUpdateTime (0) m_LastExploratorySelectionUpdateTime (0), m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
{ {
} }
@ -119,8 +118,9 @@ namespace data
i2p::util::SetThreadName("NetDB"); i2p::util::SetThreadName("NetDB");
uint64_t lastManage = 0; uint64_t lastManage = 0;
uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (), lastObsoleteProfilesCleanup = lastProfilesCleanup; uint64_t lastProfilesCleanup = i2p::util::GetMonotonicMilliseconds (),
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0; lastObsoleteProfilesCleanup = lastProfilesCleanup, lastApplyingProfileUpdates = lastProfilesCleanup;
int16_t profilesCleanupVariance = 0, obsoleteProfilesCleanVariance = 0, applyingProfileUpdatesVariance = 0;
std::list<std::shared_ptr<const I2NPMessage> > msgs; std::list<std::shared_ptr<const I2NPMessage> > msgs;
while (m_IsRunning) while (m_IsRunning)
@ -181,7 +181,7 @@ namespace data
LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk"); LogPrint (eLogWarning, "NetDb: Can't persist profiles. Profiles are being saved to disk");
} }
lastProfilesCleanup = mts; lastProfilesCleanup = mts;
profilesCleanupVariance = rand () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE; profilesCleanupVariance = m_Rng () % i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE;
} }
if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000) if (mts >= lastObsoleteProfilesCleanup + (uint64_t)(i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_TIMEOUT + obsoleteProfilesCleanVariance)*1000)
@ -197,7 +197,20 @@ namespace data
else else
LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk"); LogPrint (eLogWarning, "NetDb: Can't delete profiles. Profiles are being deleted from disk");
lastObsoleteProfilesCleanup = mts; lastObsoleteProfilesCleanup = mts;
obsoleteProfilesCleanVariance = rand () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE; obsoleteProfilesCleanVariance = m_Rng () % i2p::data::PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE;
}
if (mts >= lastApplyingProfileUpdates + i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT + applyingProfileUpdatesVariance)
{
bool isApplying = m_ApplyingProfileUpdates.valid ();
if (isApplying && m_ApplyingProfileUpdates.wait_for(std::chrono::seconds(0)) == std::future_status::ready) // still active?
{
m_ApplyingProfileUpdates.get ();
isApplying = false;
}
if (!isApplying)
m_ApplyingProfileUpdates = i2p::data::FlushPostponedRouterProfileUpdates ();
lastApplyingProfileUpdates = mts;
applyingProfileUpdatesVariance = m_Rng () % i2p::data::PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE;
} }
} }
catch (std::exception& ex) catch (std::exception& ex)
@ -281,6 +294,7 @@ namespace data
} }
else else
{ {
r->CancelBufferToDelete (); // since an update received
if (CheckLogLevel (eLogDebug)) if (CheckLogLevel (eLogDebug))
LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64());
updated = false; updated = false;
@ -557,7 +571,7 @@ namespace data
while(n > 0) while(n > 0)
{ {
std::lock_guard<std::mutex> lock(m_RouterInfosMutex); std::lock_guard<std::mutex> lock(m_RouterInfosMutex);
uint32_t idx = rand () % m_RouterInfos.size (); uint32_t idx = m_Rng () % m_RouterInfos.size ();
uint32_t i = 0; uint32_t i = 0;
for (const auto & it : m_RouterInfos) { for (const auto & it : m_RouterInfos) {
if(i >= idx) // are we at the random start point? if(i >= idx) // are we at the random start point?
@ -660,16 +674,21 @@ namespace data
{ {
std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update std::lock_guard<std::mutex> l(m_RouterInfosMutex); // possible collision between DeleteBuffer and Update
buffer = r->CopyBuffer (); buffer = r->CopyBuffer ();
r->ScheduleBufferToDelete ();
} }
if (!i2p::transport::transports.IsConnected (ident))
r->ScheduleBufferToDelete ();
if (buffer) if (buffer)
saveToDisk.push_back(std::make_pair(ident.ToBase64 (), buffer)); saveToDisk.emplace_back(ident.ToBase64 (), buffer);
} }
r->SetUpdated (false); r->SetUpdated (false);
updatedCount++; updatedCount++;
continue; continue;
} }
if (r->GetProfile ()->IsUnreachable ()) else if (r->GetBuffer () && ts > r->GetTimestamp () + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL)
// since update was long time ago we assume that router is not connected anymore
r->ScheduleBufferToDelete ();
if (r->HasProfile () && r->GetProfile ()->IsUnreachable ())
r->SetUnreachable (true); r->SetUnreachable (true);
// make router reachable back if too few routers or floodfills // make router reachable back if too few routers or floodfills
if (r->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate || isOffline || if (r->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS || isLowRate || isOffline ||
@ -696,15 +715,16 @@ namespace data
r->SetUnreachable (true); r->SetUnreachable (true);
} }
} }
// make router reachable back if connected now // make router reachable back if connected now or trusted router
if (r->IsUnreachable () && i2p::transport::transports.IsConnected (ident)) if (r->IsUnreachable () && (i2p::transport::transports.IsConnected (ident) ||
i2p::transport::transports.IsTrustedRouter (ident)))
r->SetUnreachable (false); r->SetUnreachable (false);
if (r->IsUnreachable ()) if (r->IsUnreachable ())
{ {
if (r->IsFloodfill ()) deletedFloodfillsCount++; if (r->IsFloodfill ()) deletedFloodfillsCount++;
// delete RI file // delete RI file
removeFromDisk.push_back (ident.ToBase64()); removeFromDisk.emplace_back (ident.ToBase64());
deletedCount++; deletedCount++;
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
} }
@ -931,14 +951,13 @@ namespace data
LogPrint (eLogError, "NetDb: DatabaseLookup for zero ident. Ignored"); LogPrint (eLogError, "NetDb: DatabaseLookup for zero ident. Ignored");
return; return;
} }
char key[48]; std::string key;
int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48); if (CheckLogLevel (eLogInfo))
key[l] = 0; key = i2p::data::ByteStreamToBase64 (buf, 32);
IdentHash replyIdent(buf + 32); IdentHash replyIdent(buf + 32);
uint8_t flag = buf[64]; uint8_t flag = buf[64];
LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " received flags=", (int)flag); LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " received flags=", (int)flag);
uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK; uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK;
const uint8_t * excluded = buf + 65; const uint8_t * excluded = buf + 65;
@ -1331,7 +1350,7 @@ namespace data
if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE) if (eligible.size () > NETDB_MAX_EXPLORATORY_SELECTION_SIZE)
{ {
std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection), std::sample (eligible.begin(), eligible.end(), std::back_inserter(m_ExploratorySelection),
NETDB_MAX_EXPLORATORY_SELECTION_SIZE, std::mt19937(ts)); NETDB_MAX_EXPLORATORY_SELECTION_SIZE, m_Rng);
} }
else else
std::swap (m_ExploratorySelection, eligible); std::swap (m_ExploratorySelection, eligible);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -16,6 +16,7 @@
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <future> #include <future>
#include <random>
#include "Base.h" #include "Base.h"
#include "Gzip.h" #include "Gzip.h"
@ -52,6 +53,7 @@ namespace data
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 58); // 0.9.58 const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 58); // 0.9.58
const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 59); // 0.9.59 const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 59); // 0.9.59
const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51 const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51
const int NETDB_MIN_PEER_TEST_VERSION = MAKE_VERSION_NUMBER(0, 9, 62); // 0.9.62
const size_t NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES = 16; const size_t NETDB_MAX_NUM_SEARCH_REPLY_PEER_HASHES = 16;
const size_t NETDB_MAX_EXPLORATORY_SELECTION_SIZE = 500; const size_t NETDB_MAX_EXPLORATORY_SELECTION_SIZE = 500;
const int NETDB_EXPLORATORY_SELECTION_UPDATE_INTERVAL = 82; // in seconds. for floodfill const int NETDB_EXPLORATORY_SELECTION_UPDATE_INTERVAL = 82; // in seconds. for floodfill
@ -185,10 +187,11 @@ namespace data
std::shared_ptr<NetDbRequests> m_Requests; std::shared_ptr<NetDbRequests> m_Requests;
bool m_PersistProfiles; bool m_PersistProfiles;
std::future<void> m_SavingProfiles, m_DeletingProfiles, m_PersistingRouters; std::future<void> m_SavingProfiles, m_DeletingProfiles, m_ApplyingProfileUpdates, m_PersistingRouters;
std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection; std::vector<std::shared_ptr<const RouterInfo> > m_ExploratorySelection;
uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds uint64_t m_LastExploratorySelectionUpdateTime; // in monotonic seconds
std::mt19937 m_Rng;
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool; i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool; i2p::util::MemoryPoolMt<RouterInfo::Address> m_RouterInfoAddressesPool;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -20,8 +20,10 @@ namespace i2p
namespace data namespace data
{ {
RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct): RequestedDestination::RequestedDestination (const IdentHash& destination, bool isExploratory, bool direct):
m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct), m_IsActive (true), m_Destination (destination), m_IsExploratory (isExploratory), m_IsDirect (direct),
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()), m_LastRequestTime (0), m_NumAttempts (0) m_IsActive (true), m_IsSentDirectly (false),
m_CreationTime (i2p::util::GetMillisecondsSinceEpoch ()),
m_LastRequestTime (0), m_NumAttempts (0)
{ {
if (i2p::context.IsFloodfill ()) if (i2p::context.IsFloodfill ())
m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill m_ExcludedPeers.insert (i2p::context.GetIdentHash ()); // exclude self if floodfill
@ -46,6 +48,7 @@ namespace data
m_ExcludedPeers.insert (router->GetIdentHash ()); m_ExcludedPeers.insert (router->GetIdentHash ());
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch (); m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
m_NumAttempts++; m_NumAttempts++;
m_IsSentDirectly = false;
return msg; return msg;
} }
@ -56,6 +59,7 @@ namespace data
m_ExcludedPeers.insert (floodfill); m_ExcludedPeers.insert (floodfill);
m_NumAttempts++; m_NumAttempts++;
m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch (); m_LastRequestTime = i2p::util::GetMillisecondsSinceEpoch ();
m_IsSentDirectly = true;
return msg; return msg;
} }
@ -222,7 +226,8 @@ namespace data
bool done = false; bool done = false;
if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME) if (ts < dest->GetCreationTime () + MAX_REQUEST_TIME)
{ {
if (ts > dest->GetLastRequestTime () + MIN_REQUEST_TIME) // try next floodfill if no response after min interval if (ts > dest->GetLastRequestTime () + (dest->IsSentDirectly () ? MIN_DIRECT_REQUEST_TIME : MIN_REQUEST_TIME))
// try next floodfill if no response after min interval
done = !SendNextRequest (dest); done = !SendNextRequest (dest);
} }
else // request is expired else // request is expired
@ -355,11 +360,12 @@ namespace data
void NetDbRequests::HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg) void NetDbRequests::HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg)
{ {
const uint8_t * buf = msg->GetPayload (); const uint8_t * buf = msg->GetPayload ();
char key[48]; std::string key;
int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48);
key[l] = 0;
size_t num = buf[32]; // num size_t num = buf[32]; // num
if (CheckLogLevel (eLogInfo))
key = i2p::data::ByteStreamToBase64 (buf, 32);
LogPrint (eLogDebug, "NetDbReq: DatabaseSearchReply for ", key, " num=", num); LogPrint (eLogDebug, "NetDbReq: DatabaseSearchReply for ", key, " num=", num);
IdentHash ident (buf); IdentHash ident (buf);
bool isExploratory = false; bool isExploratory = false;
auto dest = FindRequest (ident); auto dest = FindRequest (ident);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -28,6 +28,7 @@ namespace data
const uint64_t MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds const uint64_t MANAGE_REQUESTS_INTERVAL_VARIANCE = 300; // in milliseconds
const uint64_t MIN_REQUEST_TIME = 1200; // in milliseconds const uint64_t MIN_REQUEST_TIME = 1200; // in milliseconds
const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS * (MIN_REQUEST_TIME + MANAGE_REQUESTS_INTERVAL + MANAGE_REQUESTS_INTERVAL_VARIANCE); const uint64_t MAX_REQUEST_TIME = MAX_NUM_REQUEST_ATTEMPTS * (MIN_REQUEST_TIME + MANAGE_REQUESTS_INTERVAL + MANAGE_REQUESTS_INTERVAL_VARIANCE);
const uint64_t MIN_DIRECT_REQUEST_TIME = 600; // in milliseconds
const uint64_t EXPLORATORY_REQUEST_INTERVAL = 55; // in seconds const uint64_t EXPLORATORY_REQUEST_INTERVAL = 55; // in seconds
const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds const uint64_t EXPLORATORY_REQUEST_INTERVAL_VARIANCE = 170; // in seconds
const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds const uint64_t DISCOVERED_REQUEST_INTERVAL = 360; // in milliseconds
@ -52,6 +53,7 @@ namespace data
bool IsExploratory () const { return m_IsExploratory; }; bool IsExploratory () const { return m_IsExploratory; };
bool IsDirect () const { return m_IsDirect; }; bool IsDirect () const { return m_IsDirect; };
bool IsActive () const { return m_IsActive; }; bool IsActive () const { return m_IsActive; };
bool IsSentDirectly () const { return m_IsSentDirectly; };
bool IsExcluded (const IdentHash& ident) const; bool IsExcluded (const IdentHash& ident) const;
uint64_t GetCreationTime () const { return m_CreationTime; }; uint64_t GetCreationTime () const { return m_CreationTime; };
uint64_t GetLastRequestTime () const { return m_LastRequestTime; }; uint64_t GetLastRequestTime () const { return m_LastRequestTime; };
@ -70,7 +72,7 @@ namespace data
private: private:
IdentHash m_Destination; IdentHash m_Destination;
bool m_IsExploratory, m_IsDirect, m_IsActive; bool m_IsExploratory, m_IsDirect, m_IsActive, m_IsSentDirectly;
std::unordered_set<IdentHash> m_ExcludedPeers; std::unordered_set<IdentHash> m_ExcludedPeers;
uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds uint64_t m_CreationTime, m_LastRequestTime; // in milliseconds
std::list<RequestComplete> m_RequestComplete; std::list<RequestComplete> m_RequestComplete;

160
libi2pd/PostQuantum.cpp Normal file
View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 2025, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include "Log.h"
#include "PostQuantum.h"
#if OPENSSL_PQ
#include <openssl/param_build.h>
#include <openssl/core_names.h>
namespace i2p
{
namespace crypto
{
MLKEMKeys::MLKEMKeys (MLKEMTypes type):
m_Name (std::get<0>(MLKEMS[type])), m_KeyLen (std::get<1>(MLKEMS[type])),
m_CTLen (std::get<2>(MLKEMS[type])), m_Pkey (nullptr)
{
}
MLKEMKeys::~MLKEMKeys ()
{
if (m_Pkey) EVP_PKEY_free (m_Pkey);
}
void MLKEMKeys::GenerateKeys ()
{
if (m_Pkey) EVP_PKEY_free (m_Pkey);
m_Pkey = EVP_PKEY_Q_keygen(NULL, NULL, m_Name.c_str ());
}
void MLKEMKeys::GetPublicKey (uint8_t * pub) const
{
if (m_Pkey)
{
size_t len = m_KeyLen;
EVP_PKEY_get_octet_string_param (m_Pkey, OSSL_PKEY_PARAM_PUB_KEY, pub, m_KeyLen, &len);
}
}
void MLKEMKeys::SetPublicKey (const uint8_t * pub)
{
if (m_Pkey)
{
EVP_PKEY_free (m_Pkey);
m_Pkey = nullptr;
}
OSSL_PARAM params[] =
{
OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)pub, m_KeyLen),
OSSL_PARAM_END
};
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, m_Name.c_str (), NULL);
if (ctx)
{
EVP_PKEY_fromdata_init (ctx);
EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params);
EVP_PKEY_CTX_free (ctx);
}
else
LogPrint (eLogError, "MLKEM can't create PKEY context");
}
void MLKEMKeys::Encaps (uint8_t * ciphertext, uint8_t * shared)
{
if (!m_Pkey) return;
auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL);
if (ctx)
{
EVP_PKEY_encapsulate_init (ctx, NULL);
size_t len = m_CTLen, sharedLen = 32;
EVP_PKEY_encapsulate (ctx, ciphertext, &len, shared, &sharedLen);
EVP_PKEY_CTX_free (ctx);
}
else
LogPrint (eLogError, "MLKEM can't create PKEY context");
}
void MLKEMKeys::Decaps (const uint8_t * ciphertext, uint8_t * shared)
{
if (!m_Pkey) return;
auto ctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL);
if (ctx)
{
EVP_PKEY_decapsulate_init (ctx, NULL);
size_t sharedLen = 32;
EVP_PKEY_decapsulate (ctx, shared, &sharedLen, ciphertext, m_CTLen);
EVP_PKEY_CTX_free (ctx);
}
else
LogPrint (eLogError, "MLKEM can't create PKEY context");
}
std::unique_ptr<MLKEMKeys> CreateMLKEMKeys (i2p::data::CryptoKeyType type)
{
if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return nullptr;
return std::make_unique<MLKEMKeys>((MLKEMTypes)(type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1));
}
static constexpr std::array<std::pair<std::array<uint8_t, 32>, std::array<uint8_t, 32> >, 3> NoiseIKInitMLKEMKeys =
{
std::make_pair
(
std::array<uint8_t, 32>
{
0xb0, 0x8f, 0xb1, 0x73, 0x92, 0x66, 0xc9, 0x90, 0x45, 0x7f, 0xdd, 0xc6, 0x4e, 0x55, 0x40, 0xd8,
0x0a, 0x37, 0x99, 0x06, 0x92, 0x2a, 0x78, 0xc4, 0xb1, 0xef, 0x86, 0x06, 0xd0, 0x15, 0x9f, 0x4d
}, // SHA256("Noise_IKhfselg2_25519+MLKEM512_ChaChaPoly_SHA256")
std::array<uint8_t, 32>
{
0x95, 0x8d, 0xf6, 0x6c, 0x95, 0xce, 0xa9, 0xf7, 0x42, 0xfc, 0xfa, 0x62, 0x71, 0x36, 0x1e, 0xa7,
0xdc, 0x7a, 0xc0, 0x75, 0x01, 0xcf, 0xf9, 0xfc, 0x9f, 0xdb, 0x4c, 0x68, 0x3a, 0x53, 0x49, 0xeb
} // SHA256 (first)
),
std::make_pair
(
std::array<uint8_t, 32>
{
0x36, 0x03, 0x90, 0x2d, 0xf9, 0xa2, 0x2a, 0x5e, 0xc9, 0x3d, 0xdb, 0x8f, 0xa8, 0x1b, 0xdb, 0x4b,
0xae, 0x9d, 0x93, 0x9c, 0xdf, 0xaf, 0xde, 0x55, 0x49, 0x13, 0xfe, 0x98, 0xf8, 0x4a, 0xd4, 0xbd
}, // SHA256("Noise_IKhfselg2_25519+MLKEM768_ChaChaPoly_SHA256")
std::array<uint8_t, 32>
{
0x15, 0x44, 0x89, 0xbf, 0x30, 0xf0, 0xc9, 0x77, 0x66, 0x10, 0xcb, 0xb1, 0x57, 0x3f, 0xab, 0x68,
0x79, 0x57, 0x39, 0x57, 0x0a, 0xe7, 0xc0, 0x31, 0x8a, 0xa2, 0x96, 0xef, 0xbf, 0xa9, 0x6a, 0xbb
} // SHA256 (first)
),
std::make_pair
(
std::array<uint8_t, 32>
{
0x86, 0xa5, 0x36, 0x44, 0xc6, 0x12, 0xd5, 0x71, 0xa1, 0x2d, 0xd8, 0xb6, 0x0a, 0x00, 0x9f, 0x2c,
0x1a, 0xa8, 0x7d, 0x22, 0xa4, 0xff, 0x2b, 0xcd, 0x61, 0x34, 0x97, 0x6d, 0xa1, 0x49, 0xeb, 0x4a
}, // SHA256("Noise_IKhfselg2_25519+MLKEM1024_ChaChaPoly_SHA256")
std::array<uint8_t, 32>
{
0x42, 0x0d, 0xc2, 0x1c, 0x7b, 0x18, 0x61, 0xb7, 0x4a, 0x04, 0x3d, 0xae, 0x0f, 0xdc, 0xf2, 0x71,
0xb9, 0xba, 0x19, 0xbb, 0xbd, 0x5f, 0xd4, 0x9c, 0x3f, 0x4b, 0x01, 0xed, 0x6d, 0x13, 0x1d, 0xa2
} // SHA256 (first)
)
};
void InitNoiseIKStateMLKEM (NoiseSymmetricState& state, i2p::data::CryptoKeyType type, const uint8_t * pub)
{
if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)NoiseIKInitMLKEMKeys.size ()) return;
auto ind = type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1;
state.Init (NoiseIKInitMLKEMKeys[ind].first.data(), NoiseIKInitMLKEMKeys[ind].second.data(), pub);
}
}
}
#endif

88
libi2pd/PostQuantum.h Normal file
View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2025, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifndef POST_QUANTUM_H__
#define POST_QUANTUM_H__
#include <memory>
#include <string_view>
#include <array>
#include <tuple>
#include "Crypto.h"
#include "Identity.h"
#if OPENSSL_PQ
namespace i2p
{
namespace crypto
{
enum MLKEMTypes
{
eMLKEM512 = 0,
eMLKEM768,
eMLKEM1024
};
constexpr size_t MLKEM512_KEY_LENGTH = 800;
constexpr size_t MLKEM512_CIPHER_TEXT_LENGTH = 768;
constexpr size_t MLKEM768_KEY_LENGTH = 1184;
constexpr size_t MLKEM768_CIPHER_TEXT_LENGTH = 1088;
constexpr size_t MLKEM1024_KEY_LENGTH = 1568;
constexpr size_t MLKEM1024_CIPHER_TEXT_LENGTH = 1568;
constexpr std::array<std::tuple<std::string_view, size_t, size_t>, 3> MLKEMS =
{
std::make_tuple ("ML-KEM-512", MLKEM512_KEY_LENGTH, MLKEM512_CIPHER_TEXT_LENGTH),
std::make_tuple ("ML-KEM-768", MLKEM768_KEY_LENGTH, MLKEM768_CIPHER_TEXT_LENGTH),
std::make_tuple ("ML-KEM-1024", MLKEM1024_KEY_LENGTH, MLKEM1024_CIPHER_TEXT_LENGTH)
};
constexpr size_t GetMLKEMPublicKeyLen (i2p::data::CryptoKeyType type)
{
if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0;
return std::get<1>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]);
}
constexpr size_t GetMLKEMCipherTextLen (i2p::data::CryptoKeyType type)
{
if (type <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD > (int)MLKEMS.size ()) return 0;
return std::get<2>(MLKEMS[type - i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD - 1]);
}
class MLKEMKeys
{
public:
MLKEMKeys (MLKEMTypes type);
~MLKEMKeys ();
void GenerateKeys ();
void GetPublicKey (uint8_t * pub) const;
void SetPublicKey (const uint8_t * pub);
void Encaps (uint8_t * ciphertext, uint8_t * shared);
void Decaps (const uint8_t * ciphertext, uint8_t * shared);
private:
const std::string m_Name;
const size_t m_KeyLen, m_CTLen;
EVP_PKEY * m_Pkey;
};
std::unique_ptr<MLKEMKeys> CreateMLKEMKeys (i2p::data::CryptoKeyType type);
void InitNoiseIKStateMLKEM (NoiseSymmetricState& state, i2p::data::CryptoKeyType type, const uint8_t * pub); // Noise_IK (ratchets) PQ ML-KEM5
}
}
#endif
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -27,13 +27,15 @@ namespace data
static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt"); static i2p::fs::HashedStorage g_ProfilesStorage("peerProfiles", "p", "profile-", "txt");
static std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > g_Profiles; static std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > g_Profiles;
static std::mutex g_ProfilesMutex; static std::mutex g_ProfilesMutex;
static std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > > g_PostponedUpdates;
static std::mutex g_PostponedUpdatesMutex;
RouterProfile::RouterProfile (): RouterProfile::RouterProfile ():
m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0), m_IsUpdated (false), m_LastDeclineTime (0), m_LastUnreachableTime (0),
m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()), m_LastUpdateTime (i2p::util::GetSecondsSinceEpoch ()), m_LastAccessTime (0),
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), m_LastPersistTime (0), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0),
m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false), m_NumTunnelsNonReplied (0),m_NumTimesTaken (0), m_NumTimesRejected (0),
m_IsDuplicated (false) m_HasConnected (false), m_IsDuplicated (false)
{ {
} }
@ -78,6 +80,7 @@ namespace data
void RouterProfile::Load (const IdentHash& identHash) void RouterProfile::Load (const IdentHash& identHash)
{ {
m_IsUpdated = false;
std::string ident = identHash.ToBase64 (); std::string ident = identHash.ToBase64 ();
std::string path = g_ProfilesStorage.Path(ident); std::string path = g_ProfilesStorage.Path(ident);
boost::property_tree::ptree pt; boost::property_tree::ptree pt;
@ -255,24 +258,36 @@ namespace data
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::unique_lock<std::mutex> l(g_ProfilesMutex);
auto it = g_Profiles.find (identHash); auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ()) if (it != g_Profiles.end ())
{
it->second->SetLastAccessTime (i2p::util::GetSecondsSinceEpoch ());
return it->second; return it->second;
}
} }
auto profile = netdb.NewRouterProfile (); auto profile = netdb.NewRouterProfile ();
profile->Load (identHash); // if possible profile->Load (identHash); // if possible
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::lock_guard<std::mutex> l(g_ProfilesMutex);
g_Profiles.emplace (identHash, profile); g_Profiles.emplace (identHash, profile);
return profile; return profile;
} }
bool IsRouterBanned (const IdentHash& identHash) bool IsRouterBanned (const IdentHash& identHash)
{ {
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::lock_guard<std::mutex> l(g_ProfilesMutex);
auto it = g_Profiles.find (identHash); auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ()) if (it != g_Profiles.end ())
return it->second->IsUnreachable (); return it->second->IsUnreachable ();
return false; return false;
} }
bool IsRouterDuplicated (const IdentHash& identHash)
{
std::lock_guard<std::mutex> l(g_ProfilesMutex);
auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ())
return it->second->IsDuplicated ();
return false;
}
void InitProfilesStorage () void InitProfilesStorage ()
{ {
g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir()); g_ProfilesStorage.SetPlace(i2p::fs::GetDataDir());
@ -290,15 +305,17 @@ namespace data
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > > tmp; std::list<std::pair<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > > tmp;
{ {
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::lock_guard<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{ {
if (ts - it->second->GetLastUpdateTime () > PEER_PROFILE_PERSIST_INTERVAL) if (it->second->IsUpdated () && ts > it->second->GetLastPersistTime () + PEER_PROFILE_PERSIST_INTERVAL)
{ {
if (it->second->IsUpdated ()) tmp.push_back (*it);
tmp.push_back (std::make_pair (it->first, it->second)); it->second->SetLastPersistTime (ts);
it = g_Profiles.erase (it); it->second->SetUpdated (false);
} }
if (!it->second->IsUpdated () && ts > std::max (it->second->GetLastUpdateTime (), it->second->GetLastAccessTime ()) + PEER_PROFILE_PERSIST_INTERVAL)
it = g_Profiles.erase (it);
else else
it++; it++;
} }
@ -312,7 +329,7 @@ namespace data
{ {
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > tmp; std::unordered_map<i2p::data::IdentHash, std::shared_ptr<RouterProfile> > tmp;
{ {
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::lock_guard<std::mutex> l(g_ProfilesMutex);
std::swap (tmp, g_Profiles); std::swap (tmp, g_Profiles);
} }
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
@ -347,7 +364,7 @@ namespace data
{ {
{ {
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
std::unique_lock<std::mutex> l(g_ProfilesMutex); std::lock_guard<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();) for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{ {
if (ts - it->second->GetLastUpdateTime () >= PEER_PROFILE_EXPIRATION_TIMEOUT) if (ts - it->second->GetLastUpdateTime () >= PEER_PROFILE_EXPIRATION_TIMEOUT)
@ -359,5 +376,47 @@ namespace data
return std::async (std::launch::async, DeleteFilesFromDisk); return std::async (std::launch::async, DeleteFilesFromDisk);
} }
bool UpdateRouterProfile (const IdentHash& identHash, std::function<void (std::shared_ptr<RouterProfile>)> update)
{
if (!update) return true;
std::shared_ptr<RouterProfile> profile;
{
std::lock_guard<std::mutex> l(g_ProfilesMutex);
auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ())
profile = it->second;
}
if (profile)
{
update (profile);
return true;
}
// postpone
std::lock_guard<std::mutex> l(g_PostponedUpdatesMutex);
g_PostponedUpdates.emplace_back (identHash, update);
return false;
}
static void ApplyPostponedUpdates (std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > >&& updates)
{
for (const auto& [ident, update] : updates)
{
auto profile = GetRouterProfile (ident);
update (profile);
}
}
std::future<void> FlushPostponedRouterProfileUpdates ()
{
if (g_PostponedUpdates.empty ()) return std::future<void>();
std::list<std::pair<i2p::data::IdentHash, std::function<void (std::shared_ptr<RouterProfile>)> > > updates;
{
std::lock_guard<std::mutex> l(g_PostponedUpdatesMutex);
g_PostponedUpdates.swap (updates);
}
return std::async (std::launch::async, ApplyPostponedUpdates, std::move (updates));
}
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,7 @@
#include <memory> #include <memory>
#include <future> #include <future>
#include <functional>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Identity.h" #include "Identity.h"
@ -40,10 +41,12 @@ namespace data
const int PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE = 2400; // in seconds (40 minutes) const int PEER_PROFILE_OBSOLETE_PROFILES_CLEAN_VARIANCE = 2400; // in seconds (40 minutes)
const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 330; // in seconds (5.5 minutes) const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 330; // in seconds (5.5 minutes)
const int PEER_PROFILE_MAX_DECLINED_INTERVAL = 4400; // in second (1.5 hours) const int PEER_PROFILE_MAX_DECLINED_INTERVAL = 4400; // in second (1.5 hours)
const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes) const int PEER_PROFILE_PERSIST_INTERVAL = 1320; // in seconds (22 minutes)
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes) const int PEER_PROFILE_UNREACHABLE_INTERVAL = 480; // in seconds (8 minutes)
const int PEER_PROFILE_USEFUL_THRESHOLD = 3; const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
const int PEER_PROFILE_ALWAYS_DECLINING_NUM = 5; // num declines in row to consider always declined const int PEER_PROFILE_ALWAYS_DECLINING_NUM = 5; // num declines in row to consider always declined
const int PEER_PROFILE_APPLY_POSTPONED_TIMEOUT = 2100; // in milliseconds
const int PEER_PROFILE_APPLY_POSTPONED_TIMEOUT_VARIANCE = 500; // in milliseconds
class RouterProfile class RouterProfile
{ {
@ -67,6 +70,11 @@ namespace data
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
bool IsUpdated () const { return m_IsUpdated; }; bool IsUpdated () const { return m_IsUpdated; };
void SetUpdated (bool updated) { m_IsUpdated = updated; }
uint64_t GetLastAccessTime () const { return m_LastAccessTime; };
void SetLastAccessTime (uint64_t ts) { m_LastAccessTime = ts; };
uint64_t GetLastPersistTime () const { return m_LastPersistTime; };
void SetLastPersistTime (uint64_t ts) { m_LastPersistTime = ts; };
bool IsUseful() const; bool IsUseful() const;
bool IsDuplicated () const { return m_IsDuplicated; }; bool IsDuplicated () const { return m_IsDuplicated; };
@ -88,7 +96,8 @@ namespace data
private: private:
bool m_IsUpdated; bool m_IsUpdated;
uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime; // in seconds uint64_t m_LastDeclineTime, m_LastUnreachableTime, m_LastUpdateTime,
m_LastAccessTime, m_LastPersistTime; // in seconds
// participation // participation
uint32_t m_NumTunnelsAgreed; uint32_t m_NumTunnelsAgreed;
uint32_t m_NumTunnelsDeclined; uint32_t m_NumTunnelsDeclined;
@ -104,10 +113,13 @@ namespace data
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash); std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);
bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles bool IsRouterBanned (const IdentHash& identHash); // check only existing profiles
bool IsRouterDuplicated (const IdentHash& identHash); // check only existing profiles
void InitProfilesStorage (); void InitProfilesStorage ();
std::future<void> DeleteObsoleteProfiles (); std::future<void> DeleteObsoleteProfiles ();
void SaveProfiles (); void SaveProfiles ();
std::future<void> PersistProfiles (); std::future<void> PersistProfiles ();
bool UpdateRouterProfile (const IdentHash& identHash, std::function<void (std::shared_ptr<RouterProfile>)> update); // return true if updated immediately, and false if postponed
std::future<void> FlushPostponedRouterProfileUpdates ();
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -22,6 +22,7 @@
#include "ECIESX25519AEADRatchetSession.h" #include "ECIESX25519AEADRatchetSession.h"
#include "Transports.h" #include "Transports.h"
#include "Tunnel.h" #include "Tunnel.h"
#include "CryptoKey.h"
#include "RouterContext.h" #include "RouterContext.h"
namespace i2p namespace i2p
@ -33,13 +34,14 @@ namespace i2p
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown), m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID), m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
m_PublishReplyToken (0), m_IsHiddenMode (false) m_PublishReplyToken (0), m_IsHiddenMode (false),
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL), m_IsSaving (false)
{ {
} }
void RouterContext::Init () void RouterContext::Init ()
{ {
srand (i2p::util::GetMillisecondsSinceEpoch () % 1000); srand (m_Rng () % 1000);
m_StartupTime = i2p::util::GetMonotonicSeconds (); m_StartupTime = i2p::util::GetMonotonicSeconds ();
if (!Load ()) if (!Load ())
@ -253,11 +255,36 @@ namespace i2p
void RouterContext::UpdateRouterInfo () void RouterContext::UpdateRouterInfo ()
{ {
std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
{ {
std::lock_guard<std::mutex> l(m_RouterInfoMutex); std::lock_guard<std::mutex> l(m_RouterInfoMutex);
m_RouterInfo.CreateBuffer (m_Keys); m_RouterInfo.CreateBuffer (m_Keys);
buffer = m_RouterInfo.CopyBuffer ();
}
{
// update save buffer to latest
std::lock_guard<std::mutex> l(m_SaveBufferMutex);
m_SaveBuffer = buffer;
}
bool isSaving = false;
if (m_IsSaving.compare_exchange_strong (isSaving, true)) // try to save only if not being saved
{
auto savingRouterInfo = std::async (std::launch::async, [this]()
{
std::shared_ptr<i2p::data::RouterInfo::Buffer> buffer;
while (m_SaveBuffer)
{
{
std::lock_guard<std::mutex> l(m_SaveBufferMutex);
buffer = m_SaveBuffer;
m_SaveBuffer = nullptr;
}
if (buffer)
i2p::data::RouterInfo::SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO), buffer);
}
m_IsSaving = false;
});
} }
m_RouterInfo.SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO));
m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch (); m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch ();
} }
@ -649,12 +676,12 @@ namespace i2p
void RouterContext::SetBandwidth (int limit) void RouterContext::SetBandwidth (int limit)
{ {
if (limit > 2000) { SetBandwidth('X'); } if (limit > (int)i2p::data::EXTRA_BANDWIDTH_LIMIT) { SetBandwidth('X'); }
else if (limit > 256) { SetBandwidth('P'); } else if (limit > (int)i2p::data::HIGH_BANDWIDTH_LIMIT) { SetBandwidth('P'); }
else if (limit > 128) { SetBandwidth('O'); } else if (limit > 128) { SetBandwidth('O'); }
else if (limit > 64) { SetBandwidth('N'); } else if (limit > 64) { SetBandwidth('N'); }
else if (limit > 48) { SetBandwidth('M'); } else if (limit > (int)i2p::data::LOW_BANDWIDTH_LIMIT) { SetBandwidth('M'); }
else if (limit > 12) { SetBandwidth('L'); } else if (limit > 12) { SetBandwidth('L'); }
else { SetBandwidth('K'); } else { SetBandwidth('K'); }
m_BandwidthLimit = limit; // set precise limit m_BandwidthLimit = limit; // set precise limit
} }
@ -1167,7 +1194,8 @@ namespace i2p
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len))); i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len)));
} }
bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) bool RouterContext::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from)
{ {
if (typeID == eI2NPTunnelTest) if (typeID == eI2NPTunnelTest)
{ {
@ -1359,7 +1387,7 @@ namespace i2p
{ {
m_PublishTimer->cancel (); m_PublishTimer->cancel ();
m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL + m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_PUBLISH_INTERVAL +
rand () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE)); m_Rng () % ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE));
m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer, m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishTimer,
this, std::placeholders::_1)); this, std::placeholders::_1));
} }
@ -1434,7 +1462,7 @@ namespace i2p
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ())); i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
} }
else else
LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds"); LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnels. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " milliseconds");
} }
m_PublishExcluded.insert (floodfill->GetIdentHash ()); m_PublishExcluded.insert (floodfill->GetIdentHash ());
m_PublishReplyToken = replyToken; m_PublishReplyToken = replyToken;
@ -1448,7 +1476,7 @@ namespace i2p
if (m_PublishTimer) if (m_PublishTimer)
{ {
m_PublishTimer->cancel (); m_PublishTimer->cancel ();
m_PublishTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONFIRMATION_TIMEOUT)); m_PublishTimer->expires_from_now (boost::posix_time::milliseconds(ROUTER_INFO_CONFIRMATION_TIMEOUT));
m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishResendTimer, m_PublishTimer->async_wait (std::bind (&RouterContext::HandlePublishResendTimer,
this, std::placeholders::_1)); this, std::placeholders::_1));
} }
@ -1471,7 +1499,8 @@ namespace i2p
if (m_CongestionUpdateTimer) if (m_CongestionUpdateTimer)
{ {
m_CongestionUpdateTimer->cancel (); m_CongestionUpdateTimer->cancel ();
m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(ROUTER_INFO_CONGESTION_UPDATE_INTERVAL)); m_CongestionUpdateTimer->expires_from_now (boost::posix_time::seconds(
ROUTER_INFO_CONGESTION_UPDATE_INTERVAL + m_Rng () % ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE));
m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer, m_CongestionUpdateTimer->async_wait (std::bind (&RouterContext::HandleCongestionUpdateTimer,
this, std::placeholders::_1)); this, std::placeholders::_1));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -12,6 +12,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <memory> #include <memory>
#include <random>
#include <unordered_set> #include <unordered_set>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "Identity.h" #include "Identity.h"
@ -34,9 +35,10 @@ namespace garlic
const int ROUTER_INFO_PUBLISH_INTERVAL = 39*60; // in seconds const int ROUTER_INFO_PUBLISH_INTERVAL = 39*60; // in seconds
const int ROUTER_INFO_INITIAL_PUBLISH_INTERVAL = 10; // in seconds const int ROUTER_INFO_INITIAL_PUBLISH_INTERVAL = 10; // in seconds
const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds const int ROUTER_INFO_PUBLISH_INTERVAL_VARIANCE = 105;// in seconds
const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 5; // in seconds const int ROUTER_INFO_CONFIRMATION_TIMEOUT = 1600; // in milliseconds
const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15; const int ROUTER_INFO_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 12*60; // in seconds const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL = 11*60; // in seconds
const int ROUTER_INFO_CONGESTION_UPDATE_INTERVAL_VARIANCE = 130; // in seconds
const int ROUTER_INFO_CLEANUP_INTERVAL = 102; // in seconds const int ROUTER_INFO_CLEANUP_INTERVAL = 102; // in seconds
enum RouterStatus enum RouterStatus
@ -202,7 +204,8 @@ namespace garlic
// implements GarlicDestination // implements GarlicDestination
void HandleI2NPMessage (const uint8_t * buf, size_t len) override; void HandleI2NPMessage (const uint8_t * buf, size_t len) override;
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) override; bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload,
size_t len, uint32_t msgID, i2p::garlic::ECIESX25519AEADRatchetSession * from) override;
private: private:
@ -263,6 +266,10 @@ namespace garlic
uint32_t m_PublishReplyToken; uint32_t m_PublishReplyToken;
bool m_IsHiddenMode; // not publish bool m_IsHiddenMode; // not publish
mutable std::mutex m_RouterInfoMutex; mutable std::mutex m_RouterInfoMutex;
std::mt19937 m_Rng;
std::shared_ptr<i2p::data::RouterInfo::Buffer> m_SaveBuffer;
std::mutex m_SaveBufferMutex; // TODO: make m_SaveBuffer atomic
std::atomic<bool> m_IsSaving;
}; };
extern RouterContext context; extern RouterContext context;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,7 +11,7 @@
#include "I2PEndian.h" #include "I2PEndian.h"
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <boost/lexical_cast.hpp> #include <charconv>
#include <boost/algorithm/string.hpp> // for boost::to_lower #include <boost/algorithm/string.hpp> // for boost::to_lower
#ifndef __cpp_lib_atomic_shared_ptr #ifndef __cpp_lib_atomic_shared_ptr
#include <boost/atomic.hpp> #include <boost/atomic.hpp>
@ -25,6 +25,7 @@
#include "Transports.h" #include "Transports.h"
#include "NetDb.hpp" #include "NetDb.hpp"
#include "RouterContext.h" #include "RouterContext.h"
#include "CryptoKey.h"
#include "RouterInfo.h" #include "RouterInfo.h"
namespace i2p namespace i2p
@ -106,8 +107,7 @@ namespace data
// skip identity // skip identity
size_t identityLen = m_RouterIdentity->GetFullLen (); size_t identityLen = m_RouterIdentity->GetFullLen ();
// read new RI // read new RI
std::stringstream str (std::string ((char *)buf + identityLen, len - identityLen)); ReadFromBuffer (buf + identityLen, len - identityLen);
ReadFromStream (str);
if (!m_IsUnreachable) if (!m_IsUnreachable)
UpdateBuffer (buf, len); // save buffer UpdateBuffer (buf, len); // save buffer
// don't delete buffer until saved to the file // don't delete buffer until saved to the file
@ -195,39 +195,34 @@ namespace data
} }
} }
// parse RI // parse RI
std::stringstream str; if (!ReadFromBuffer (m_Buffer->data () + identityLen, bufferLen - identityLen))
str.write ((const char *)m_Buffer->data () + identityLen, bufferLen - identityLen);
ReadFromStream (str);
if (!str)
{ {
LogPrint (eLogError, "RouterInfo: Malformed message"); LogPrint (eLogError, "RouterInfo: Malformed message");
m_IsUnreachable = true; m_IsUnreachable = true;
} }
} }
void RouterInfo::ReadFromStream (std::istream& s) bool RouterInfo::ReadFromBuffer (const uint8_t * buf, size_t len)
{ {
if (!s) return; if (len < 9) return false;
m_Caps = 0; m_Congestion = eLowCongestion; m_Caps = 0; m_Congestion = eLowCongestion;
s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = bufbe64toh (buf);
m_Timestamp = be64toh (m_Timestamp); size_t offset = 8; // timestamp
// read addresses // read addresses
auto addresses = NewAddresses (); auto addresses = NewAddresses ();
uint8_t numAddresses; uint8_t numAddresses = buf[offset]; offset++;
s.read ((char *)&numAddresses, sizeof (numAddresses));
for (int i = 0; i < numAddresses; i++) for (int i = 0; i < numAddresses; i++)
{ {
if (offset + 9 > len) return false; // 1 byte cost + 8 bytes date
uint8_t supportedTransports = 0; uint8_t supportedTransports = 0;
auto address = NewAddress (); auto address = NewAddress ();
uint8_t cost; // ignore offset++; // cost, ignore
s.read ((char *)&cost, sizeof (cost)); address->date = bufbe64toh (buf + offset); offset += 8; // date
s.read ((char *)&address->date, sizeof (address->date));
bool isHost = false, isStaticKey = false, isV2 = false, isIntroKey = false; bool isHost = false, isStaticKey = false, isV2 = false, isIntroKey = false;
char transportStyle[6]; auto transportStyle = ExtractString (buf + offset, len - offset); offset += transportStyle.length () + 1;
ReadString (transportStyle, 6, s); if (!transportStyle.compare (0, 4, "NTCP")) // NTCP or NTCP2
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
address->transportStyle = eTransportNTCP2; address->transportStyle = eTransportNTCP2;
else if (!strncmp (transportStyle, "SSU", 3)) // SSU or SSU2 else if (!transportStyle.compare (0, 3, "SSU")) // SSU or SSU2
{ {
address->transportStyle = eTransportSSU2; address->transportStyle = eTransportSSU2;
address->ssu.reset (new SSUExt ()); address->ssu.reset (new SSUExt ());
@ -237,24 +232,22 @@ namespace data
address->transportStyle = eTransportUnknown; address->transportStyle = eTransportUnknown;
address->caps = 0; address->caps = 0;
address->port = 0; address->port = 0;
uint16_t size, r = 0; if (offset + 2 > len) return false;
s.read ((char *)&size, sizeof (size)); if (!s) return; uint16_t size = bufbe16toh (buf + offset); offset += 2; // size
size = be16toh (size); if (offset + size >= len) return false;
if (address->transportStyle == eTransportUnknown) if (address->transportStyle == eTransportUnknown)
{ {
// skip unknown address // skip unknown address
s.seekg (size, std::ios_base::cur); offset += size;
if (s) continue; else return; continue;
} }
size_t r = 0;
while (r < size) while (r < size)
{ {
char key[255], value[255]; auto [key, value, sz] = ExtractParam (buf + offset, len - offset);
r += ReadString (key, 255, s); r += sz; offset += sz;
s.seekg (1, std::ios_base::cur); r++; // = if (key.empty ()) continue;
r += ReadString (value, 255, s); if (key == "host")
s.seekg (1, std::ios_base::cur); r++; // ;
if (!s) return;
if (!strcmp (key, "host"))
{ {
boost::system::error_code ecode; boost::system::error_code ecode;
address->host = boost::asio::ip::make_address (value, ecode); address->host = boost::asio::ip::make_address (value, ecode);
@ -268,63 +261,53 @@ namespace data
address->transportStyle = eTransportUnknown; address->transportStyle = eTransportUnknown;
} }
} }
else if (!strcmp (key, "port")) else if (key == "port")
{ {
try auto res = std::from_chars(value.data(), value.data() + value.size(), address->port);
{ if (res.ec != std::errc())
address->port = boost::lexical_cast<int>(value); LogPrint (eLogWarning, "RouterInfo: 'port' conversion error: ", std::make_error_code (res.ec).message ());
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ());
}
} }
else if (!strcmp (key, "mtu")) else if (key == "mtu")
{ {
if (address->ssu) if (address->ssu)
{ {
try auto res = std::from_chars(value.data(), value.data() + value.size(), address->ssu->mtu);
{ if (res.ec != std::errc())
address->ssu->mtu = boost::lexical_cast<int>(value); LogPrint (eLogWarning, "RouterInfo: 'mtu' conversion error: ", std::make_error_code (res.ec).message ());
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ());
}
} }
else else
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2"); LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2");
} }
else if (!strcmp (key, "caps")) else if (key == "caps")
address->caps = ExtractAddressCaps (value); address->caps = ExtractAddressCaps (value);
else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key else if (key == "s") // ntcp2 or ssu2 static key
{ {
if (Base64ToByteStream (value, strlen (value), address->s, 32) == 32 && if (Base64ToByteStream (value, address->s, 32) == 32 &&
!(address->s[31] & 0x80)) // check if x25519 public key !(address->s[31] & 0x80)) // check if x25519 public key
isStaticKey = true; isStaticKey = true;
else else
address->transportStyle = eTransportUnknown; // invalid address address->transportStyle = eTransportUnknown; // invalid address
} }
else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro else if (key == "i") // ntcp2 iv or ssu2 intro
{ {
if (address->IsNTCP2 ()) if (address->IsNTCP2 ())
{ {
if (Base64ToByteStream (value, strlen (value), address->i, 16) == 16) if (Base64ToByteStream (value, address->i, 16) == 16)
address->published = true; // presence of "i" means "published" NTCP2 address->published = true; // presence of "i" means "published" NTCP2
else else
address->transportStyle = eTransportUnknown; // invalid address address->transportStyle = eTransportUnknown; // invalid address
} }
else if (address->IsSSU2 ()) else if (address->IsSSU2 ())
{ {
if (Base64ToByteStream (value, strlen (value), address->i, 32) == 32) if (Base64ToByteStream (value, address->i, 32) == 32)
isIntroKey = true; isIntroKey = true;
else else
address->transportStyle = eTransportUnknown; // invalid address address->transportStyle = eTransportUnknown; // invalid address
} }
} }
else if (!strcmp (key, "v")) else if (key == "v")
{ {
if (!strcmp (value, "2")) if (value == "2")
isV2 = true; isV2 = true;
else else
{ {
@ -340,13 +323,11 @@ namespace data
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped"); LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
continue; continue;
} }
size_t l = strlen(key); unsigned char index = key[key.length () - 1] - '0'; // TODO:
unsigned char index = key[l-1] - '0'; // TODO:
key[l-1] = 0;
if (index > 9) if (index > 9)
{ {
LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped"); LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped");
if (s) continue; else return; continue;
} }
if (index >= address->ssu->introducers.size ()) if (index >= address->ssu->introducers.size ())
{ {
@ -355,34 +336,23 @@ namespace data
address->ssu->introducers.resize (index + 1); address->ssu->introducers.resize (index + 1);
} }
Introducer& introducer = address->ssu->introducers.at (index); Introducer& introducer = address->ssu->introducers.at (index);
if (!strcmp (key, "itag")) auto key1 = key.substr(0, key.length () - 1);
if (key1 == "itag")
{ {
try auto res = std::from_chars(value.data(), value.data() + value.size(), introducer.iTag);
{ if (res.ec != std::errc())
introducer.iTag = boost::lexical_cast<uint32_t>(value); LogPrint (eLogWarning, "RouterInfo: 'itag' conversion error: ", std::make_error_code (res.ec).message ());
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
}
} }
else if (!strcmp (key, "ih")) else if (key1 == "ih")
Base64ToByteStream (value, strlen (value), introducer.iH, 32); Base64ToByteStream (value, introducer.iH, 32);
else if (!strcmp (key, "iexp")) else if (key1 == "iexp")
{ {
try auto res = std::from_chars(value.data(), value.data() + value.size(), introducer.iExp);
{ if (res.ec != std::errc())
introducer.iExp = boost::lexical_cast<uint32_t>(value); LogPrint (eLogWarning, "RouterInfo: 'iexp' conversion error: ", std::make_error_code (res.ec).message ());
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ());
}
} }
} }
if (!s) return;
} }
if (address->transportStyle == eTransportNTCP2) if (address->transportStyle == eTransportNTCP2)
{ {
if (isStaticKey) if (isStaticKey)
@ -446,66 +416,73 @@ namespace data
boost::atomic_store (&m_Addresses, addresses); boost::atomic_store (&m_Addresses, addresses);
#endif #endif
// read peers // read peers
uint8_t numPeers; if (offset + 1 > len) return false;
s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; uint8_t numPeers = buf[offset]; offset++; // num peers
s.seekg (numPeers*32, std::ios_base::cur); // TODO: read peers offset += numPeers*32; // TODO: read peers
// read properties // read properties
if (offset + 2 > len) return false;
m_Version = 0; m_Version = 0;
bool isNetId = false; bool isNetId = false;
std::string family; std::string family;
uint16_t size, r = 0; uint16_t size = bufbe16toh (buf + offset); offset += 2; // size
s.read ((char *)&size, sizeof (size)); if (!s) return; if (offset + size > len) return false;
size = be16toh (size); size_t r = 0;
while (r < size) while (r < size)
{ {
char key[255], value[255]; auto [key, value, sz] = ExtractParam (buf + offset, len - offset);
r += ReadString (key, 255, s); r += sz; offset += sz;
s.seekg (1, std::ios_base::cur); r++; // = if (key.empty ()) continue;
r += ReadString (value, 255, s);
s.seekg (1, std::ios_base::cur); r++; // ;
if (!s) return;
SetProperty (key, value); SetProperty (key, value);
// extract caps // extract caps
if (!strcmp (key, "caps")) if (key == "caps")
{ {
ExtractCaps (value); ExtractCaps (value);
m_IsFloodfill = IsDeclaredFloodfill (); m_IsFloodfill = IsDeclaredFloodfill ();
} }
// extract version // extract version
else if (!strcmp (key, ROUTER_INFO_PROPERTY_VERSION)) else if (key == ROUTER_INFO_PROPERTY_VERSION)
{ {
m_Version = 0; m_Version = 0;
char * ch = value; for (auto ch: value)
while (*ch)
{ {
if (*ch >= '0' && *ch <= '9') if (ch >= '0' && ch <= '9')
{ {
m_Version *= 10; m_Version *= 10;
m_Version += (*ch - '0'); m_Version += (ch - '0');
}
}
if (m_Version < NETDB_MIN_PEER_TEST_VERSION && (m_SupportedTransports & (eSSU2V4 | eSSU2V6)))
{
auto addresses = GetAddresses ();
if (addresses)
{
if ((*addresses)[eSSU2V4Idx]) (*addresses)[eSSU2V4Idx]->caps &= ~eSSUTesting;
if ((*addresses)[eSSU2V6Idx]) (*addresses)[eSSU2V6Idx]->caps &= ~eSSUTesting;
} }
ch++;
} }
} }
// check netId // check netId
else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID)) else if (key == ROUTER_INFO_PROPERTY_NETID)
{ {
isNetId = true; isNetId = true;
if (atoi (value) != i2p::context.GetNetID ()) int netID;
auto res = std::from_chars(value.data(), value.data() + value.size(), netID);
if (res.ec != std::errc() || netID != i2p::context.GetNetID ())
{ {
LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value);
m_IsUnreachable = true; m_IsUnreachable = true;
} }
} }
// family // family
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY)) else if (key == ROUTER_INFO_PROPERTY_FAMILY)
{ {
family = value; family = value;
boost::to_lower (family); boost::to_lower (family);
} }
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY_SIG)) else if (key == ROUTER_INFO_PROPERTY_FAMILY_SIG)
{ {
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) // TODO
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family); m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
else else
{ {
@ -513,12 +490,12 @@ namespace data
SetUnreachable (true); SetUnreachable (true);
} }
} }
if (!s) return;
} }
if (!m_SupportedTransports || !isNetId || !m_Version) if (!m_SupportedTransports || !isNetId || !m_Version)
SetUnreachable (true); SetUnreachable (true);
return true;
} }
bool RouterInfo::IsFamily (FamilyID famid) const bool RouterInfo::IsFamily (FamilyID famid) const
@ -526,12 +503,11 @@ namespace data
return m_FamilyID == famid; return m_FamilyID == famid;
} }
void RouterInfo::ExtractCaps (const char * value) void RouterInfo::ExtractCaps (std::string_view value)
{ {
const char * cap = value; for (auto cap: value)
while (*cap)
{ {
switch (*cap) switch (cap)
{ {
case CAPS_FLAG_FLOODFILL: case CAPS_FLAG_FLOODFILL:
m_Caps |= Caps::eFloodfill; m_Caps |= Caps::eFloodfill;
@ -540,16 +516,16 @@ namespace data
case CAPS_FLAG_LOW_BANDWIDTH2: case CAPS_FLAG_LOW_BANDWIDTH2:
case CAPS_FLAG_LOW_BANDWIDTH3: case CAPS_FLAG_LOW_BANDWIDTH3:
case CAPS_FLAG_LOW_BANDWIDTH4: case CAPS_FLAG_LOW_BANDWIDTH4:
m_BandwidthCap = *cap; m_BandwidthCap = cap;
break; break;
case CAPS_FLAG_HIGH_BANDWIDTH: case CAPS_FLAG_HIGH_BANDWIDTH:
m_Caps |= Caps::eHighBandwidth; m_Caps |= Caps::eHighBandwidth;
m_BandwidthCap = *cap; m_BandwidthCap = cap;
break; break;
case CAPS_FLAG_EXTRA_BANDWIDTH1: case CAPS_FLAG_EXTRA_BANDWIDTH1:
case CAPS_FLAG_EXTRA_BANDWIDTH2: case CAPS_FLAG_EXTRA_BANDWIDTH2:
m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth; m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth;
m_BandwidthCap = *cap; m_BandwidthCap = cap;
break; break;
case CAPS_FLAG_HIDDEN: case CAPS_FLAG_HIDDEN:
m_Caps |= Caps::eHidden; m_Caps |= Caps::eHidden;
@ -571,17 +547,15 @@ namespace data
break; break;
default: ; default: ;
} }
cap++;
} }
} }
uint8_t RouterInfo::ExtractAddressCaps (const char * value) const uint8_t RouterInfo::ExtractAddressCaps (std::string_view value) const
{ {
uint8_t caps = 0; uint8_t caps = 0;
const char * cap = value; for (auto cap: value)
while (*cap)
{ {
switch (*cap) switch (cap)
{ {
case CAPS_FLAG_V4: case CAPS_FLAG_V4:
caps |= AddressCaps::eV4; caps |= AddressCaps::eV4;
@ -597,7 +571,6 @@ namespace data
break; break;
default: ; default: ;
} }
cap++;
} }
return caps; return caps;
} }
@ -661,23 +634,39 @@ namespace data
return SaveToFile (fullPath, m_Buffer); return SaveToFile (fullPath, m_Buffer);
} }
size_t RouterInfo::ReadString (char * str, size_t len, std::istream& s) const std::string_view RouterInfo::ExtractString (const uint8_t * buf, size_t len) const
{ {
uint8_t l; uint8_t l = buf[0];
s.read ((char *)&l, 1); if (l > len)
if (l < len)
{
s.read (str, l);
if (!s) l = 0; // failed, return empty string
str[l] = 0;
}
else
{ {
LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len); LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len);
s.seekg (l, std::ios::cur); // skip l = len;
str[0] = 0;
} }
return l+1; return { (const char *)(buf + 1), l };
}
std::tuple<std::string_view, std::string_view, size_t> RouterInfo::ExtractParam (const uint8_t * buf, size_t len) const
{
auto key = ExtractString (buf, len);
size_t offset = key.length () + 1;
if (offset >= len) return { std::string_view(), std::string_view(), len };
if (buf[offset] != '=')
{
LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead '=' after ", key);
key = std::string_view();
}
offset++;
if (offset >= len) return { key, std::string_view(), len };
auto value = ExtractString (buf + offset, len - offset);
offset += value.length () + 1;
if (offset >= len) return { key, std::string_view(), len };
if (buf[offset] != ';')
{
LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead ';' after ", value);
value = std::string_view();
}
offset++;
return { key, value, offset };
} }
void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps) void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps)
@ -1136,12 +1125,12 @@ namespace data
void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len) void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len)
{ {
m_IsBufferScheduledToDelete = false;
if (!m_Buffer) if (!m_Buffer)
m_Buffer = NewBuffer (); m_Buffer = NewBuffer ();
if (len > m_Buffer->size ()) len = m_Buffer->size (); if (len > m_Buffer->size ()) len = m_Buffer->size ();
memcpy (m_Buffer->data (), buf, len); memcpy (m_Buffer->data (), buf, len);
m_Buffer->SetBufferLen (len); m_Buffer->SetBufferLen (len);
m_IsBufferScheduledToDelete = false;
} }
std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const
@ -1393,9 +1382,9 @@ namespace data
if (!introducer.iTag) continue; if (!introducer.iTag) continue;
if (introducer.iExp) // expiration is specified if (introducer.iExp) // expiration is specified
{ {
WriteString ("iexp" + boost::lexical_cast<std::string>(i), properties); WriteString ("iexp" + std::to_string(i), properties);
properties << '='; properties << '=';
WriteString (boost::lexical_cast<std::string>(introducer.iExp), properties); WriteString (std::to_string(introducer.iExp), properties);
properties << ';'; properties << ';';
} }
i++; i++;
@ -1404,11 +1393,9 @@ namespace data
for (const auto& introducer: address.ssu->introducers) for (const auto& introducer: address.ssu->introducers)
{ {
if (!introducer.iTag) continue; if (!introducer.iTag) continue;
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties); WriteString ("ih" + std::to_string(i), properties);
properties << '='; properties << '=';
char value[64]; auto value = ByteStreamToBase64 (introducer.iH, 32);
size_t l = ByteStreamToBase64 (introducer.iH, 32, value, 64);
value[l] = 0;
WriteString (value, properties); WriteString (value, properties);
properties << ';'; properties << ';';
i++; i++;
@ -1417,9 +1404,9 @@ namespace data
for (const auto& introducer: address.ssu->introducers) for (const auto& introducer: address.ssu->introducers)
{ {
if (!introducer.iTag) continue; if (!introducer.iTag) continue;
WriteString ("itag" + boost::lexical_cast<std::string>(i), properties); WriteString ("itag" + std::to_string(i), properties);
properties << '='; properties << '=';
WriteString (boost::lexical_cast<std::string>(introducer.iTag), properties); WriteString (std::to_string(introducer.iTag), properties);
properties << ';'; properties << ';';
i++; i++;
} }
@ -1433,7 +1420,7 @@ namespace data
{ {
WriteString ("mtu", properties); WriteString ("mtu", properties);
properties << '='; properties << '=';
WriteString (boost::lexical_cast<std::string>(address.ssu->mtu), properties); WriteString (std::to_string(address.ssu->mtu), properties);
properties << ';'; properties << ';';
} }
} }
@ -1441,7 +1428,7 @@ namespace data
{ {
WriteString ("port", properties); WriteString ("port", properties);
properties << '='; properties << '=';
WriteString (boost::lexical_cast<std::string>(address.port), properties); WriteString (std::to_string(address.port), properties);
properties << ';'; properties << ';';
} }
if (address.IsNTCP2 () || address.IsSSU2 ()) if (address.IsNTCP2 () || address.IsSSU2 ())
@ -1476,9 +1463,11 @@ namespace data
s.write (properties.str ().c_str (), properties.str ().size ()); s.write (properties.str ().c_str (), properties.str ().size ());
} }
void LocalRouterInfo::SetProperty (const std::string& key, const std::string& value) void LocalRouterInfo::SetProperty (std::string_view key, std::string_view value)
{ {
m_Properties[key] = value; auto [it, inserted] = m_Properties.emplace (key, value);
if (!inserted)
it->second = value;
} }
void LocalRouterInfo::DeleteProperty (const std::string& key) void LocalRouterInfo::DeleteProperty (const std::string& key)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -11,6 +11,8 @@
#include <inttypes.h> #include <inttypes.h>
#include <string> #include <string>
#include <string_view>
#include <tuple>
#include <map> #include <map>
#include <vector> #include <vector>
#include <array> #include <array>
@ -208,8 +210,8 @@ namespace data
typedef boost::shared_ptr<Addresses> AddressesPtr; typedef boost::shared_ptr<Addresses> AddressesPtr;
#endif #endif
RouterInfo (const std::string& fullPath); RouterInfo (const std::string& fullPath);
RouterInfo (const RouterInfo& ) = default; RouterInfo (const RouterInfo& ) = delete;
RouterInfo& operator=(const RouterInfo& ) = default; RouterInfo& operator=(const RouterInfo& ) = delete;
RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len); RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len);
RouterInfo (const uint8_t * buf, size_t len); RouterInfo (const uint8_t * buf, size_t len);
virtual ~RouterInfo (); virtual ~RouterInfo ();
@ -219,7 +221,7 @@ namespace data
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); }; std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
uint64_t GetTimestamp () const { return m_Timestamp; }; uint64_t GetTimestamp () const { return m_Timestamp; };
int GetVersion () const { return m_Version; }; int GetVersion () const { return m_Version; };
virtual void SetProperty (const std::string& key, const std::string& value) {}; virtual void SetProperty (std::string_view key, std::string_view value) {};
virtual void ClearProperties () {}; virtual void ClearProperties () {};
AddressesPtr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr AddressesPtr GetAddresses () const; // should be called for local RI only, otherwise must return shared_ptr
std::shared_ptr<const Address> GetNTCP2V4Address () const; std::shared_ptr<const Address> GetNTCP2V4Address () const;
@ -294,6 +296,7 @@ namespace data
std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; }; std::shared_ptr<Buffer> GetSharedBuffer () const { return m_Buffer; };
std::shared_ptr<Buffer> CopyBuffer () const; std::shared_ptr<Buffer> CopyBuffer () const;
void ScheduleBufferToDelete () { m_IsBufferScheduledToDelete = true; }; void ScheduleBufferToDelete () { m_IsBufferScheduledToDelete = true; };
void CancelBufferToDelete () { m_IsBufferScheduledToDelete = false; };
bool IsBufferScheduledToDelete () const { return m_IsBufferScheduledToDelete; }; bool IsBufferScheduledToDelete () const { return m_IsBufferScheduledToDelete; };
bool IsUpdated () const { return m_IsUpdated; }; bool IsUpdated () const { return m_IsUpdated; };
@ -332,11 +335,12 @@ namespace data
bool LoadFile (const std::string& fullPath); bool LoadFile (const std::string& fullPath);
void ReadFromFile (const std::string& fullPath); void ReadFromFile (const std::string& fullPath);
void ReadFromStream (std::istream& s); bool ReadFromBuffer (const uint8_t * buf, size_t len); // return false if malformed
void ReadFromBuffer (bool verifySignature); void ReadFromBuffer (bool verifySignature);
size_t ReadString (char* str, size_t len, std::istream& s) const; std::string_view ExtractString (const uint8_t * buf, size_t len) const;
void ExtractCaps (const char * value); std::tuple<std::string_view, std::string_view, size_t> ExtractParam (const uint8_t * buf, size_t len) const;
uint8_t ExtractAddressCaps (const char * value) const; void ExtractCaps (std::string_view value);
uint8_t ExtractAddressCaps (std::string_view value) const;
void UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts); void UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts);
template<typename Filter> template<typename Filter>
std::shared_ptr<const Address> GetAddress (Filter filter) const; std::shared_ptr<const Address> GetAddress (Filter filter) const;
@ -378,7 +382,7 @@ namespace data
void UpdateCaps (uint8_t caps); void UpdateCaps (uint8_t caps);
bool UpdateCongestion (Congestion c); // returns true if updated bool UpdateCongestion (Congestion c); // returns true if updated
void SetProperty (const std::string& key, const std::string& value) override; void SetProperty (std::string_view key, std::string_view value) override;
void DeleteProperty (const std::string& key); void DeleteProperty (const std::string& key);
std::string GetProperty (const std::string& key) const; std::string GetProperty (const std::string& key) const;
void ClearProperties () override { m_Properties.clear (); }; void ClearProperties () override { m_Properties.clear (); };

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -890,7 +890,7 @@ namespace transport
} }
auto session = std::make_shared<SSU2Session> (*this, router, address); auto session = std::make_shared<SSU2Session> (*this, router, address);
if (!isValidEndpoint && router->GetProfile ()->HasLastEndpoint (address->IsV4 ())) if (!isValidEndpoint && router->HasProfile () && router->GetProfile ()->HasLastEndpoint (address->IsV4 ()))
{ {
// router doesn't publish endpoint, but we connected before and hole punch might be alive // router doesn't publish endpoint, but we connected before and hole punch might be alive
auto ep = router->GetProfile ()->GetLastEndpoint (); auto ep = router->GetProfile ()->GetLastEndpoint ();
@ -1251,18 +1251,21 @@ namespace transport
} }
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
m_IncomingTokens.emplace (ep, std::make_pair (token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT))); if (!token) token = 1; // token can't be zero
m_IncomingTokens.try_emplace (ep, token, uint32_t(ts + SSU2_TOKEN_EXPIRATION_TIMEOUT));
return token; return token;
} }
std::pair<uint64_t, uint32_t> SSU2Server::NewIncomingToken (const boost::asio::ip::udp::endpoint& ep) std::pair<uint64_t, uint32_t> SSU2Server::NewIncomingToken (const boost::asio::ip::udp::endpoint& ep)
{ {
m_IncomingTokens.erase (ep); // drop previous
uint64_t token; uint64_t token;
RAND_bytes ((uint8_t *)&token, 8); RAND_bytes ((uint8_t *)&token, 8);
auto ret = std::make_pair (token, uint32_t(i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT)); if (!token) token = 1; // token can't be zero
m_IncomingTokens.emplace (ep, ret); uint32_t expires = i2p::util::GetSecondsSinceEpoch () + SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT;
return ret; auto [it, inserted] = m_IncomingTokens.try_emplace (ep, token, expires);
if (!inserted)
it->second = { token, expires }; // override
return it->second;
} }
std::vector<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers, std::vector<std::shared_ptr<SSU2Session> > SSU2Server::FindIntroducers (int maxNumIntroducers,
@ -1528,6 +1531,11 @@ namespace transport
return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len); return m_Decryptor.Decrypt (msg, msgLen, ad, adLen, key, nonce, buf, len);
} }
void SSU2Server::ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
{
m_ChaCha20 (msg, msgLen, key, nonce, out);
}
void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen, void SSU2Server::SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to) const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to)
{ {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -86,6 +86,7 @@ namespace transport
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len); const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
bool AEADChaCha20Poly1305Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, bool AEADChaCha20Poly1305Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len); const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len);
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; } bool IsMaxNumIntroducers (bool v4) const { return (v4 ? m_Introducers.size () : m_IntroducersV6.size ()) >= SSU2_MAX_NUM_INTRODUCERS; }
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; }; bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from); void AdjustTimeOffset (int64_t offset, std::shared_ptr<const i2p::data::IdentityEx> from);
@ -206,6 +207,7 @@ namespace transport
mutable std::mutex m_ReceivedPacketsQueueMutex; mutable std::mutex m_ReceivedPacketsQueueMutex;
i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor; i2p::crypto::AEADChaCha20Poly1305Encryptor m_Encryptor;
i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor; i2p::crypto::AEADChaCha20Poly1305Decryptor m_Decryptor;
i2p::crypto::ChaCha20Context m_ChaCha20;
// proxy // proxy
bool m_IsThroughProxy; bool m_IsThroughProxy;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2024, The PurpleI2P Project * Copyright (c) 2024-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -46,7 +46,7 @@ namespace transport
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); GetServer ().ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
SetDestConnID (headerX[0]); SetDestConnID (headerX[0]);
// decrypt and handle payload // decrypt and handle payload
uint8_t * payload = buf + 32; uint8_t * payload = buf + 32;
@ -183,7 +183,7 @@ namespace transport
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
memset (n, 0, 12); memset (n, 0, 12);
i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16); GetServer ().ChaCha20 (h + 16, 16, addr->i, n, h + 16);
// send // send
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ()); GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, GetRemoteEndpoint ());
UpdateNumSentBytes (payloadSize + 32); UpdateNumSentBytes (payloadSize + 32);
@ -191,12 +191,7 @@ namespace transport
void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, bool delayed) void SSU2PeerTestSession::SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, bool delayed)
{ {
#if __cplusplus >= 202002L // C++20
m_SignedData.assign (signedData, signedData + signedDataLen); m_SignedData.assign (signedData, signedData + signedDataLen);
#else
m_SignedData.resize (signedDataLen);
memcpy (m_SignedData.data (), signedData, signedDataLen);
#endif
if (!delayed) if (!delayed)
SendPeerTest (msg); SendPeerTest (msg);
// schedule resend for msgs 5 or 6 // schedule resend for msgs 5 or 6
@ -257,7 +252,7 @@ namespace transport
{ {
// we are Charlie // we are Charlie
uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id uint64_t destConnID = htobe64 (((uint64_t)nonce << 32) | nonce); // dest id
uint32_t sourceConnID = ~destConnID; uint64_t sourceConnID = ~destConnID;
SetSourceConnID (sourceConnID); SetSourceConnID (sourceConnID);
SetDestConnID (destConnID); SetDestConnID (destConnID);
SetState (eSSU2SessionStateHolePunch); SetState (eSSU2SessionStateHolePunch);
@ -305,7 +300,7 @@ namespace transport
header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (addr->i, payload + (payloadSize - 12));
memset (n, 0, 12); memset (n, 0, 12);
i2p::crypto::ChaCha20 (h + 16, 16, addr->i, n, h + 16); GetServer ().ChaCha20 (h + 16, 16, addr->i, n, h + 16);
// send // send
GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep); GetServer ().Send (header.buf, 16, h + 16, 16, payload, payloadSize, ep);
UpdateNumSentBytes (payloadSize + 32); UpdateNumSentBytes (payloadSize + 32);
@ -313,12 +308,7 @@ namespace transport
void SSU2HolePunchSession::SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen) void SSU2HolePunchSession::SendHolePunch (const uint8_t * relayResponseBlock, size_t relayResponseBlockLen)
{ {
#if __cplusplus >= 202002L // C++20
m_RelayResponseBlock.assign (relayResponseBlock, relayResponseBlock + relayResponseBlockLen); m_RelayResponseBlock.assign (relayResponseBlock, relayResponseBlock + relayResponseBlockLen);
#else
m_RelayResponseBlock.resize (relayResponseBlockLen);
memcpy (m_RelayResponseBlock.data (), relayResponseBlock, relayResponseBlockLen);
#endif
SendHolePunch (); SendHolePunch ();
ScheduleResend (); ScheduleResend ();
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -92,7 +92,7 @@ namespace transport
m_RTO (SSU2_INITIAL_RTO), m_RelayTag (0),m_ConnectTimer (server.GetService ()), m_RTO (SSU2_INITIAL_RTO), m_RelayTag (0),m_ConnectTimer (server.GetService ()),
m_TerminationReason (eSSU2TerminationReasonNormalClose), m_TerminationReason (eSSU2TerminationReasonNormalClose),
m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32), // min size m_MaxPayloadSize (SSU2_MIN_PACKET_SIZE - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - 32), // min size
m_LastResendTime (0), m_LastResendAttemptTime (0) m_LastResendTime (0), m_LastResendAttemptTime (0), m_NumRanges (0)
{ {
if (noise) if (noise)
m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState);
@ -189,7 +189,7 @@ namespace transport
if (!asz) return false; if (!asz) return false;
payload[17] = asz; payload[17] = asz;
packet->payloadSize = asz + 18; packet->payloadSize = asz + 18;
SignedData s; SignedData<128> s;
s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (session->GetRemoteIdentity ()->GetIdentHash (), 32); // chash s.Insert (session->GetRemoteIdentity ()->GetIdentHash (), 32); // chash
@ -623,7 +623,8 @@ namespace transport
} }
else else
{ {
uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize); uint32_t packetNum = SendData (it->second->payload, it->second->payloadSize,
it->second->numResends > 1 ? SSU2_FLAG_IMMEDIATE_ACK_REQUESTED : 0);
it->second->numResends++; it->second->numResends++;
it->second->sendTime = ts; it->second->sendTime = ts;
resentPackets.emplace (packetNum, it->second); resentPackets.emplace (packetNum, it->second);
@ -682,7 +683,7 @@ namespace transport
} }
const uint8_t nonce[12] = {0}; const uint8_t nonce[12] = {0};
uint64_t headerX[2]; uint64_t headerX[2];
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]); LogPrint (eLogWarning, "SSU2: Unexpected PeerTest message SourceConnID=", connID, " DestConnID=", headerX[0]);
break; break;
} }
@ -748,7 +749,7 @@ namespace transport
payloadSize += 16; payloadSize += 16;
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
i2p::crypto::ChaCha20 (headerX, 48, m_Address->i, nonce, headerX); m_Server.ChaCha20 (headerX, 48, m_Address->i, nonce, headerX);
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted payload from Session Request) for SessionCreated m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted payload from Session Request) for SessionCreated
m_SentHandshakePacket->payloadSize = payloadSize; m_SentHandshakePacket->payloadSize = payloadSize;
// send // send
@ -775,7 +776,7 @@ namespace transport
} }
const uint8_t nonce[12] = {0}; const uint8_t nonce[12] = {0};
uint8_t headerX[48]; uint8_t headerX[48];
i2p::crypto::ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX); m_Server.ChaCha20 (buf + 16, 48, i2p::context.GetSSU2IntroKey (), nonce, headerX);
memcpy (&m_DestConnID, headerX, 8); memcpy (&m_DestConnID, headerX, 8);
uint64_t token; uint64_t token;
memcpy (&token, headerX + 8, 8); memcpy (&token, headerX + 8, 8);
@ -874,7 +875,7 @@ namespace transport
m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted Noise payload from Session Created) m_NoiseState->MixHash (payload, payloadSize); // h = SHA256(h || encrypted Noise payload from Session Created)
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (kh2, payload + (payloadSize - 12));
i2p::crypto::ChaCha20 (headerX, 48, kh2, nonce, headerX); m_Server.ChaCha20 (headerX, 48, kh2, nonce, headerX);
m_State = eSSU2SessionStateSessionCreatedSent; m_State = eSSU2SessionStateSessionCreatedSent;
m_SentHandshakePacket->payloadSize = payloadSize; m_SentHandshakePacket->payloadSize = payloadSize;
// send // send
@ -902,7 +903,7 @@ namespace transport
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
const uint8_t nonce[12] = {0}; const uint8_t nonce[12] = {0};
uint8_t headerX[48]; uint8_t headerX[48];
i2p::crypto::ChaCha20 (buf + 16, 48, kh2, nonce, headerX); m_Server.ChaCha20 (buf + 16, 48, kh2, nonce, headerX);
// KDF for SessionCreated // KDF for SessionCreated
m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header) m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header)
m_NoiseState->MixHash (headerX + 16, 32); // h = SHA256(h || bepk); m_NoiseState->MixHash (headerX + 16, 32); // h = SHA256(h || bepk);
@ -1178,13 +1179,18 @@ namespace transport
LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb"); LogPrint (eLogError, "SSU2: Couldn't update RouterInfo from SessionConfirmed in netdb");
return false; return false;
} }
std::shared_ptr<i2p::data::RouterProfile> profile; // not null if older
bool isOlder = false;
if (ri->GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ()) if (ri->GetTimestamp () + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri1->GetTimestamp ())
{ {
// received RouterInfo is older than one in netdb // received RouterInfo is older than one in netdb
profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile isOlder = true;
if (profile && profile->IsDuplicated ()) if (ri->HasProfile ())
return false; {
auto profile = i2p::data::GetRouterProfile (ri->GetIdentHash ()); // retrieve profile
if (profile && profile->IsDuplicated ())
return false;
}
} }
ri = ri1; ri = ri1;
@ -1198,15 +1204,28 @@ namespace transport
(!m_RemoteEndpoint.address ().is_v6 () || (!m_RemoteEndpoint.address ().is_v6 () ||
memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address memcmp (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), m_Address->host.to_v6 ().to_bytes ().data (), 8))) // temporary address
{ {
if (profile) // older router? if (isOlder) // older router?
profile->Duplicated (); // mark router as duplicated in profile i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Duplicated (); // mark router as duplicated in profile
});
else else
LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host, LogPrint (eLogInfo, "SSU2: Host mismatch between published address ", m_Address->host,
" and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ())); " and actual endpoint ", m_RemoteEndpoint.address (), " from ", i2p::data::GetIdentHashAbbreviation (ri->GetIdentHash ()));
return false; return false;
} }
if (!m_Address->published) if (!m_Address->published)
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint); {
if (ri->HasProfile ())
ri->GetProfile ()->SetLastEndpoint (m_RemoteEndpoint);
else
i2p::data::UpdateRouterProfile (ri->GetIdentHash (),
[ep = m_RemoteEndpoint](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->SetLastEndpoint (ep);
});
}
SetRemoteIdentity (ri->GetRouterIdentity ()); SetRemoteIdentity (ri->GetRouterIdentity ());
AdjustMaxPayloadSize (); AdjustMaxPayloadSize ();
m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now m_Server.AddSessionByRouterHash (shared_from_this ()); // we know remote router now
@ -1264,7 +1283,7 @@ namespace transport
header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (m_Address->i, payload + (payloadSize - 12));
memset (nonce, 0, 12); memset (nonce, 0, 12);
i2p::crypto::ChaCha20 (h + 16, 16, m_Address->i, nonce, h + 16); m_Server.ChaCha20 (h + 16, 16, m_Address->i, nonce, h + 16);
// send // send
if (m_Server.AddPendingOutgoingSession (shared_from_this ())) if (m_Server.AddPendingOutgoingSession (shared_from_this ()))
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
@ -1286,7 +1305,7 @@ namespace transport
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint8_t h[32]; uint8_t h[32];
memcpy (h, header.buf, 16); memcpy (h, header.buf, 16);
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16); m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
memcpy (&m_DestConnID, h + 16, 8); memcpy (&m_DestConnID, h + 16, 8);
// decrypt // decrypt
CreateNonce (be32toh (header.h.packetNum), nonce); CreateNonce (be32toh (header.h.packetNum), nonce);
@ -1338,7 +1357,7 @@ namespace transport
header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24)); header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 24));
header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 12)); header.ll[1] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), payload + (payloadSize - 12));
memset (nonce, 0, 12); memset (nonce, 0, 12);
i2p::crypto::ChaCha20 (h + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16); m_Server.ChaCha20 (h + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, h + 16);
// send // send
m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint); m_Server.Send (header.buf, 16, h + 16, 16, payload, payloadSize, m_RemoteEndpoint);
} }
@ -1362,7 +1381,7 @@ namespace transport
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX); m_Server.ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX);
uint64_t token = headerX[1]; uint64_t token = headerX[1];
if (token) if (token)
m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT);
@ -1411,7 +1430,7 @@ namespace transport
} }
uint8_t nonce[12] = {0}; uint8_t nonce[12] = {0};
uint64_t headerX[2]; // sourceConnID, token uint64_t headerX[2]; // sourceConnID, token
i2p::crypto::ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX); m_Server.ChaCha20 (buf + 16, 16, i2p::context.GetSSU2IntroKey (), nonce, (uint8_t *)headerX);
m_DestConnID = headerX[0]; m_DestConnID = headerX[0];
// decrypt and handle payload // decrypt and handle payload
uint8_t * payload = buf + 32; uint8_t * payload = buf + 32;
@ -1479,11 +1498,11 @@ namespace transport
ResendHandshakePacket (); // assume we receive ResendHandshakePacket (); // assume we receive
return; return;
} }
if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ())) if (from != m_RemoteEndpoint && !i2p::transport::transports.IsInReservedRange (from.address ()) &&
(!m_PathChallenge || from != m_PathChallenge->second)) // path challenge was not sent to this endpoint yet
{ {
LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from); LogPrint (eLogInfo, "SSU2: Remote endpoint update ", m_RemoteEndpoint, "->", from);
m_RemoteEndpoint = from; SendPathChallenge (from);
SendPathChallenge ();
} }
if (len < 32) if (len < 32)
{ {
@ -1641,10 +1660,11 @@ namespace transport
LogPrint (eLogDebug, "SSU2: Path response"); LogPrint (eLogDebug, "SSU2: Path response");
if (m_PathChallenge) if (m_PathChallenge)
{ {
i2p::data::IdentHash hash; if (buf64toh (buf + offset) == m_PathChallenge->first)
SHA256 (buf + offset, size, hash); {
if (hash == *m_PathChallenge) m_RemoteEndpoint = m_PathChallenge->second;
m_PathChallenge.reset (nullptr); m_PathChallenge.reset (nullptr);
}
} }
break; break;
} }
@ -1744,6 +1764,7 @@ namespace transport
HandleAckRange (firstPacketNum, ackThrough, i2p::util::GetMillisecondsSinceEpoch ()); // acnt HandleAckRange (firstPacketNum, ackThrough, i2p::util::GetMillisecondsSinceEpoch ()); // acnt
// ranges // ranges
len -= 5; len -= 5;
if (!len || m_SentPackets.empty ()) return; // don't handle ranges if nothing to acknowledge
const uint8_t * ranges = buf + 5; const uint8_t * ranges = buf + 5;
while (len > 0 && firstPacketNum && ackThrough - firstPacketNum < SSU2_MAX_NUM_ACK_PACKETS) while (len > 0 && firstPacketNum && ackThrough - firstPacketNum < SSU2_MAX_NUM_ACK_PACKETS)
{ {
@ -1945,6 +1966,7 @@ namespace transport
void SSU2Session::HandleRelayRequest (const uint8_t * buf, size_t len) void SSU2Session::HandleRelayRequest (const uint8_t * buf, size_t len)
{ {
// we are Bob // we are Bob
if (len < 9) return;
auto mts = i2p::util::GetMillisecondsSinceEpoch (); auto mts = i2p::util::GetMillisecondsSinceEpoch ();
uint32_t nonce = bufbe32toh (buf + 1); // nonce uint32_t nonce = bufbe32toh (buf + 1); // nonce
uint32_t relayTag = bufbe32toh (buf + 5); // relay tag uint32_t relayTag = bufbe32toh (buf + 5); // relay tag
@ -1978,7 +2000,7 @@ namespace transport
packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0; packet->payloadSize = r ? CreateRouterInfoBlock (packet->payload, m_MaxPayloadSize - len - 32, r) : 0;
if (!packet->payloadSize && r) if (!packet->payloadSize && r)
session->SendFragmentedMessage (CreateDatabaseStoreMsg (r)); session->SendFragmentedMessage (CreateDatabaseStoreMsg (r));
packet->payloadSize += CreateRelayIntroBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize, buf + 1, len -1); packet->payloadSize += CreateRelayIntroBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize, buf + 1, len - 1);
if (packet->payloadSize < m_MaxPayloadSize) if (packet->payloadSize < m_MaxPayloadSize)
packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); packet->payloadSize += CreatePaddingBlock (packet->payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize);
uint32_t packetNum = session->SendData (packet->payload, packet->payloadSize); uint32_t packetNum = session->SendData (packet->payload, packet->payloadSize);
@ -1993,18 +2015,24 @@ namespace transport
void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len, int attempts) void SSU2Session::HandleRelayIntro (const uint8_t * buf, size_t len, int attempts)
{ {
// we are Charlie // we are Charlie
if (len < 47) return;
SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept; SSU2RelayResponseCode code = eSSU2RelayResponseCodeAccept;
boost::asio::ip::udp::endpoint ep; boost::asio::ip::udp::endpoint ep;
std::shared_ptr<const i2p::data::RouterInfo::Address> addr; std::shared_ptr<const i2p::data::RouterInfo::Address> addr;
auto r = i2p::data::netdb.FindRouter (buf + 1); // Alice auto r = i2p::data::netdb.FindRouter (buf + 1); // Alice
if (r) if (r)
{ {
SignedData s; SignedData<128> s;
s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue s.Insert ((const uint8_t *)"RelayRequestData", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (i2p::context.GetIdentHash (), 32); // chash s.Insert (i2p::context.GetIdentHash (), 32); // chash
s.Insert (buf + 33, 14); // nonce, relay tag, timestamp, ver, asz s.Insert (buf + 33, 14); // nonce, relay tag, timestamp, ver, asz
uint8_t asz = buf[46]; uint8_t asz = buf[46];
if (asz + 47 + r->GetIdentity ()->GetSignatureLen () > len)
{
LogPrint (eLogWarning, "SSU2: Malformed RelayIntro len=", len);
return;
}
s.Insert (buf + 47, asz); // Alice Port, Alice IP s.Insert (buf + 47, asz); // Alice Port, Alice IP
if (s.Verify (r->GetIdentity (), buf + 47 + asz)) if (s.Verify (r->GetIdentity (), buf + 47 + asz))
{ {
@ -2093,6 +2121,7 @@ namespace transport
void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len) void SSU2Session::HandleRelayResponse (const uint8_t * buf, size_t len)
{ {
if (len < 6) return;
uint32_t nonce = bufbe32toh (buf + 2); uint32_t nonce = bufbe32toh (buf + 2);
if (m_State == eSSU2SessionStateIntroduced) if (m_State == eSSU2SessionStateIntroduced)
{ {
@ -2113,7 +2142,9 @@ namespace transport
auto it = m_RelaySessions.find (nonce); auto it = m_RelaySessions.find (nonce);
if (it != m_RelaySessions.end ()) if (it != m_RelaySessions.end ())
{ {
if (it->second.first && it->second.first->IsEstablished ()) auto relaySession = it->second.first;
m_RelaySessions.erase (it);
if (relaySession && relaySession->IsEstablished ())
{ {
// we are Bob, message from Charlie // we are Bob, message from Charlie
auto packet = m_Server.GetSentPacketsPool ().AcquireShared (); auto packet = m_Server.GetSentPacketsPool ().AcquireShared ();
@ -2123,12 +2154,12 @@ namespace transport
memcpy (payload + 3, buf, len); // forward to Alice as is memcpy (payload + 3, buf, len); // forward to Alice as is
packet->payloadSize = len + 3; packet->payloadSize = len + 3;
packet->payloadSize += CreatePaddingBlock (payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize); packet->payloadSize += CreatePaddingBlock (payload + packet->payloadSize, m_MaxPayloadSize - packet->payloadSize);
uint32_t packetNum = it->second.first->SendData (packet->payload, packet->payloadSize); uint32_t packetNum = relaySession->SendData (packet->payload, packet->payloadSize);
if (m_RemoteVersion >= SSU2_MIN_RELAY_RESPONSE_RESEND_VERSION) if (m_RemoteVersion >= SSU2_MIN_RELAY_RESPONSE_RESEND_VERSION)
{ {
// sometimes Alice doesn't ack this RelayResponse in older versions // sometimes Alice doesn't ack this RelayResponse in older versions
packet->sendTime = i2p::util::GetMillisecondsSinceEpoch (); packet->sendTime = i2p::util::GetMillisecondsSinceEpoch ();
it->second.first->m_SentPackets.emplace (packetNum, packet); relaySession->m_SentPackets.emplace (packetNum, packet);
} }
} }
else else
@ -2137,25 +2168,31 @@ namespace transport
if (!buf[1]) // status code accepted? if (!buf[1]) // status code accepted?
{ {
// verify signature // verify signature
uint8_t csz = buf[11]; uint8_t csz = (len >= 12) ? buf[11] : 0;
SignedData s; if (csz + 12 + relaySession->GetRemoteIdentity ()->GetSignatureLen () > len)
{
LogPrint (eLogWarning, "SSU2: Malformed RelayResponse len=", len);
relaySession->Done ();
return;
}
SignedData<128> s;
s.Insert ((const uint8_t *)"RelayAgreementOK", 16); // prologue s.Insert ((const uint8_t *)"RelayAgreementOK", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (buf + 2, 10 + csz); // nonce, timestamp, ver, csz and Charlie's endpoint s.Insert (buf + 2, 10 + csz); // nonce, timestamp, ver, csz and Charlie's endpoint
if (s.Verify (it->second.first->GetRemoteIdentity (), buf + 12 + csz)) if (s.Verify (relaySession->GetRemoteIdentity (), buf + 12 + csz))
{ {
if (it->second.first->m_State == eSSU2SessionStateIntroduced) // HolePunch not received yet if (relaySession->m_State == eSSU2SessionStateIntroduced) // HolePunch not received yet
{ {
// update Charlie's endpoint // update Charlie's endpoint
if (ExtractEndpoint (buf + 12, csz, it->second.first->m_RemoteEndpoint)) if (ExtractEndpoint (buf + 12, csz, relaySession->m_RemoteEndpoint))
{ {
// update token // update token
uint64_t token; uint64_t token;
memcpy (&token, buf + len - 8, 8); memcpy (&token, buf + len - 8, 8);
m_Server.UpdateOutgoingToken (it->second.first->m_RemoteEndpoint, m_Server.UpdateOutgoingToken (relaySession->m_RemoteEndpoint,
token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT);
// connect to Charlie, HolePunch will be ignored // connect to Charlie, HolePunch will be ignored
it->second.first->ConnectAfterIntroduction (); relaySession->ConnectAfterIntroduction ();
} }
else else
LogPrint (eLogWarning, "SSU2: RelayResponse can't extract endpoint"); LogPrint (eLogWarning, "SSU2: RelayResponse can't extract endpoint");
@ -2164,16 +2201,15 @@ namespace transport
else else
{ {
LogPrint (eLogWarning, "SSU2: RelayResponse signature verification failed"); LogPrint (eLogWarning, "SSU2: RelayResponse signature verification failed");
it->second.first->Done (); relaySession->Done ();
} }
} }
else else
{ {
LogPrint (eLogInfo, "SSU2: RelayResponse status code=", (int)buf[1], " nonce=", bufbe32toh (buf + 2)); LogPrint (eLogInfo, "SSU2: RelayResponse status code=", (int)buf[1], " nonce=", bufbe32toh (buf + 2));
it->second.first->Done (); relaySession->Done ();
} }
} }
m_RelaySessions.erase (it);
} }
else else
LogPrint (eLogDebug, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2)); LogPrint (eLogDebug, "SSU2: RelayResponse unknown nonce ", bufbe32toh (buf + 2));
@ -2242,10 +2278,13 @@ namespace transport
case 2: // Charlie from Bob case 2: // Charlie from Bob
{ {
// sign with Charlie's key // sign with Charlie's key
if (len < offset + 9) return;
uint8_t asz = buf[offset + 9]; uint8_t asz = buf[offset + 9];
std::vector<uint8_t> newSignedData (asz + 10 + i2p::context.GetIdentity ()->GetSignatureLen ()); size_t l = asz + 10 + i2p::context.GetIdentity ()->GetSignatureLen ();
if (len < offset + l) return;
std::vector<uint8_t> newSignedData (l);
memcpy (newSignedData.data (), buf + offset, asz + 10); memcpy (newSignedData.data (), buf + offset, asz + 10);
SignedData s; SignedData<128> s;
s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (buf + 3, 32); // ahash s.Insert (buf + 3, 32); // ahash
@ -2353,10 +2392,16 @@ namespace transport
if (GetRouterStatus () == eRouterStatusUnknown) if (GetRouterStatus () == eRouterStatusUnknown)
SetTestingState (true); SetTestingState (true);
auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie
if (r) if (r && len >= offset + 9)
{ {
uint8_t asz = buf[offset + 9]; uint8_t asz = buf[offset + 9];
SignedData s; if (len < offset + asz + 10 + r->GetIdentity ()->GetSignatureLen ())
{
LogPrint (eLogWarning, "Malformed PeerTest 4 len=", len);
session->Done ();
return;
}
SignedData<128> s;
s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (i2p::context.GetIdentity ()->GetIdentHash (), 32); // ahash s.Insert (i2p::context.GetIdentity ()->GetIdentHash (), 32); // ahash
@ -2515,17 +2560,19 @@ namespace transport
return nullptr; return nullptr;
} }
void SSU2Session::AdjustMaxPayloadSize () void SSU2Session::AdjustMaxPayloadSize (size_t maxMtu)
{ {
auto addr = FindLocalAddress (); auto addr = FindLocalAddress ();
if (addr && addr->ssu) if (addr && addr->ssu)
{ {
int mtu = addr->ssu->mtu; int mtu = addr->ssu->mtu;
if (!mtu && addr->IsV4 ()) mtu = SSU2_MAX_PACKET_SIZE; if (!mtu && addr->IsV4 ()) mtu = SSU2_MAX_PACKET_SIZE;
if (mtu > (int)maxMtu) mtu = maxMtu;
if (m_Address && m_Address->ssu && (!mtu || m_Address->ssu->mtu < mtu)) if (m_Address && m_Address->ssu && (!mtu || m_Address->ssu->mtu < mtu))
mtu = m_Address->ssu->mtu; mtu = m_Address->ssu->mtu;
if (mtu) if (mtu)
{ {
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE; if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
m_MaxPayloadSize = mtu - (addr->IsV6 () ? IPV6_HEADER_SIZE: IPV4_HEADER_SIZE) - UDP_HEADER_SIZE - 32; m_MaxPayloadSize = mtu - (addr->IsV6 () ? IPV6_HEADER_SIZE: IPV4_HEADER_SIZE) - UDP_HEADER_SIZE - 32;
LogPrint (eLogDebug, "SSU2: Session MTU=", mtu, ", max payload size=", m_MaxPayloadSize); LogPrint (eLogDebug, "SSU2: Session MTU=", mtu, ", max payload size=", m_MaxPayloadSize);
@ -2624,17 +2671,17 @@ namespace transport
size_t SSU2Session::CreateAckBlock (uint8_t * buf, size_t len) size_t SSU2Session::CreateAckBlock (uint8_t * buf, size_t len)
{ {
if (len < 8) return 0; if (len < 8) return 0;
int maxNumRanges = (len - 8) >> 1;
if (maxNumRanges > SSU2_MAX_NUM_ACK_RANGES) maxNumRanges = SSU2_MAX_NUM_ACK_RANGES;
buf[0] = eSSU2BlkAck; buf[0] = eSSU2BlkAck;
uint32_t ackThrough = m_OutOfSequencePackets.empty () ? m_ReceivePacketNum : *m_OutOfSequencePackets.rbegin (); uint32_t ackThrough = m_OutOfSequencePackets.empty () ? m_ReceivePacketNum : *m_OutOfSequencePackets.rbegin ();
htobe32buf (buf + 3, ackThrough); // Ack Through htobe32buf (buf + 3, ackThrough); // Ack Through
uint16_t acnt = 0; uint16_t acnt = 0;
int numRanges = 0;
if (ackThrough) if (ackThrough)
{ {
if (m_OutOfSequencePackets.empty ()) if (m_OutOfSequencePackets.empty ())
{
acnt = std::min ((int)ackThrough, SSU2_MAX_NUM_ACNT); // no gaps acnt = std::min ((int)ackThrough, SSU2_MAX_NUM_ACNT); // no gaps
m_NumRanges = 0;
}
else else
{ {
auto it = m_OutOfSequencePackets.rbegin (); it++; // prev packet num auto it = m_OutOfSequencePackets.rbegin (); it++; // prev packet num
@ -2647,93 +2694,102 @@ namespace transport
it++; it++;
} }
// ranges // ranges
uint32_t lastNum = ackThrough - acnt; if (!m_NumRanges)
if (acnt > SSU2_MAX_NUM_ACNT)
{ {
auto d = std::div (acnt - SSU2_MAX_NUM_ACNT, SSU2_MAX_NUM_ACNT); int maxNumRanges = (len - 8) >> 1;
acnt = SSU2_MAX_NUM_ACNT; if (maxNumRanges > SSU2_MAX_NUM_ACK_RANGES) maxNumRanges = SSU2_MAX_NUM_ACK_RANGES;
if (d.quot > maxNumRanges) int numRanges = 0;
uint32_t lastNum = ackThrough - acnt;
if (acnt > SSU2_MAX_NUM_ACNT)
{ {
d.quot = maxNumRanges; auto d = std::div (acnt - SSU2_MAX_NUM_ACNT, SSU2_MAX_NUM_ACNT);
d.rem = 0; acnt = SSU2_MAX_NUM_ACNT;
} if (d.quot > maxNumRanges)
// Acks only ranges for acnt
for (int i = 0; i < d.quot; i++)
{
buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // NACKs 0, Acks 255
numRanges++;
}
if (d.rem > 0)
{
buf[8 + numRanges*2] = 0; buf[8 + numRanges*2 + 1] = d.rem;
numRanges++;
}
}
int numPackets = acnt + numRanges*SSU2_MAX_NUM_ACNT;
while (it != m_OutOfSequencePackets.rend () &&
numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS)
{
if (lastNum - (*it) > SSU2_MAX_NUM_ACNT)
{
// NACKs only ranges
if (lastNum > (*it) + SSU2_MAX_NUM_ACNT*(maxNumRanges - numRanges)) break; // too many NACKs
while (lastNum - (*it) > SSU2_MAX_NUM_ACNT)
{ {
buf[8 + numRanges*2] = SSU2_MAX_NUM_ACNT; buf[8 + numRanges*2 + 1] = 0; // NACKs 255, Acks 0 d.quot = maxNumRanges;
lastNum -= SSU2_MAX_NUM_ACNT; d.rem = 0;
}
// Acks only ranges for acnt
for (int i = 0; i < d.quot; i++)
{
m_Ranges[numRanges*2] = 0; m_Ranges[numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // NACKs 0, Acks 255
numRanges++;
}
if (d.rem > 0)
{
m_Ranges[numRanges*2] = 0; m_Ranges[numRanges*2 + 1] = d.rem;
numRanges++; numRanges++;
numPackets += SSU2_MAX_NUM_ACNT;
} }
} }
// NACKs and Acks ranges int numPackets = acnt + numRanges*SSU2_MAX_NUM_ACNT;
buf[8 + numRanges*2] = lastNum - (*it) - 1; // NACKs while (it != m_OutOfSequencePackets.rend () &&
numPackets += buf[8 + numRanges*2]; numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS)
lastNum = *it; it++;
int numAcks = 1;
while (it != m_OutOfSequencePackets.rend () && lastNum > 0 && *it == lastNum - 1)
{ {
numAcks++; lastNum--; if (lastNum - (*it) > SSU2_MAX_NUM_ACNT)
it++; {
} // NACKs only ranges
while (numAcks > SSU2_MAX_NUM_ACNT) if (lastNum > (*it) + SSU2_MAX_NUM_ACNT*(maxNumRanges - numRanges)) break; // too many NACKs
{ while (lastNum - (*it) > SSU2_MAX_NUM_ACNT)
// Acks only ranges {
buf[8 + numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // Acks 255 m_Ranges[numRanges*2] = SSU2_MAX_NUM_ACNT; m_Ranges[numRanges*2 + 1] = 0; // NACKs 255, Acks 0
numAcks -= SSU2_MAX_NUM_ACNT; lastNum -= SSU2_MAX_NUM_ACNT;
numRanges++; numRanges++;
numPackets += SSU2_MAX_NUM_ACNT; numPackets += SSU2_MAX_NUM_ACNT;
buf[8 + numRanges*2] = 0; // NACKs 0 }
if (numRanges >= maxNumRanges || numPackets >= SSU2_MAX_NUM_ACK_PACKETS) break; }
} // NACKs and Acks ranges
if (numAcks > SSU2_MAX_NUM_ACNT) numAcks = SSU2_MAX_NUM_ACNT; m_Ranges[numRanges*2] = lastNum - (*it) - 1; // NACKs
buf[8 + numRanges*2 + 1] = (uint8_t)numAcks; // Acks numPackets += m_Ranges[numRanges*2];
numPackets += numAcks; lastNum = *it; it++;
numRanges++; int numAcks = 1;
} while (it != m_OutOfSequencePackets.rend () && lastNum > 0 && *it == lastNum - 1)
if (it == m_OutOfSequencePackets.rend () && {
numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS) numAcks++; lastNum--;
{ it++;
// add range between out-of-sequence and received }
int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1; while (numAcks > SSU2_MAX_NUM_ACNT)
if (nacks > 0) {
{ // Acks only ranges
if (nacks > SSU2_MAX_NUM_ACNT) nacks = SSU2_MAX_NUM_ACNT; m_Ranges[numRanges*2 + 1] = SSU2_MAX_NUM_ACNT; // Acks 255
buf[8 + numRanges*2] = nacks; numAcks -= SSU2_MAX_NUM_ACNT;
buf[8 + numRanges*2 + 1] = std::min ((int)m_ReceivePacketNum + 1, SSU2_MAX_NUM_ACNT); numRanges++;
numPackets += SSU2_MAX_NUM_ACNT;
m_Ranges[numRanges*2] = 0; // NACKs 0
if (numRanges >= maxNumRanges || numPackets >= SSU2_MAX_NUM_ACK_PACKETS) break;
}
if (numAcks > SSU2_MAX_NUM_ACNT) numAcks = SSU2_MAX_NUM_ACNT;
m_Ranges[numRanges*2 + 1] = (uint8_t)numAcks; // Acks
numPackets += numAcks;
numRanges++; numRanges++;
} }
if (it == m_OutOfSequencePackets.rend () &&
numRanges < maxNumRanges && numPackets < SSU2_MAX_NUM_ACK_PACKETS)
{
// add range between out-of-sequence and received
int nacks = *m_OutOfSequencePackets.begin () - m_ReceivePacketNum - 1;
if (nacks > 0)
{
if (nacks > SSU2_MAX_NUM_ACNT) nacks = SSU2_MAX_NUM_ACNT;
m_Ranges[numRanges*2] = nacks;
m_Ranges[numRanges*2 + 1] = std::min ((int)m_ReceivePacketNum + 1, SSU2_MAX_NUM_ACNT);
numRanges++;
}
}
m_NumRanges = numRanges;
} }
if (m_NumRanges)
memcpy (buf + 8, m_Ranges, m_NumRanges*2);
} }
} }
buf[7] = (uint8_t)acnt; // acnt buf[7] = (uint8_t)acnt; // acnt
htobe16buf (buf + 1, 5 + numRanges*2); htobe16buf (buf + 1, 5 + m_NumRanges*2);
return 8 + numRanges*2; return 8 + m_NumRanges*2;
} }
size_t SSU2Session::CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize) size_t SSU2Session::CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize)
{ {
if (len < 3 || len < minSize) return 0; if (len < 3 || len < minSize) return 0;
size_t paddingSize = m_Server.GetRng ()() & 0x0F; // 0 - 15 size_t paddingSize = m_Server.GetRng ()() & 0x1F; // 0 - 31
if (paddingSize + 3 > len) paddingSize = len - 3; if (paddingSize + 3 > len) paddingSize = len - 3;
else if (paddingSize + 3 < minSize) paddingSize = minSize - 3; else if (paddingSize + 3 < minSize) paddingSize = minSize - 3;
buf[0] = eSSU2BlkPadding; buf[0] = eSSU2BlkPadding;
@ -2835,7 +2891,7 @@ namespace transport
LogPrint (eLogError, "SSU2: Buffer for RelayResponse signature is too small ", len); LogPrint (eLogError, "SSU2: Buffer for RelayResponse signature is too small ", len);
return 0; return 0;
} }
SignedData s; SignedData<128> s;
s.Insert ((const uint8_t *)"RelayAgreementOK", 16); // prologue s.Insert ((const uint8_t *)"RelayAgreementOK", 16); // prologue
if (code == eSSU2RelayResponseCodeAccept || code >= 64) // Charlie if (code == eSSU2RelayResponseCodeAccept || code >= 64) // Charlie
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
@ -2897,7 +2953,7 @@ namespace transport
size_t asz = CreateEndpoint (signedData + 10, 86, boost::asio::ip::udp::endpoint (localAddress->host, localAddress->port)); size_t asz = CreateEndpoint (signedData + 10, 86, boost::asio::ip::udp::endpoint (localAddress->host, localAddress->port));
signedData[9] = asz; signedData[9] = asz;
// signature // signature
SignedData s; SignedData<128> s;
s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue s.Insert ((const uint8_t *)"PeerTestValidate", 16); // prologue
s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash s.Insert (GetRemoteIdentity ()->GetIdentHash (), 32); // bhash
s.Insert (signedData, 10 + asz); // ver, nonce, ts, asz, Alice's endpoint s.Insert (signedData, 10 + asz); // ver, nonce, ts, asz, Alice's endpoint
@ -2961,11 +3017,17 @@ namespace transport
} }
m_OutOfSequencePackets.erase (m_OutOfSequencePackets.begin (), it); m_OutOfSequencePackets.erase (m_OutOfSequencePackets.begin (), it);
} }
m_NumRanges = 0; // recalculate ranges when create next Ack
} }
m_ReceivePacketNum = packetNum; m_ReceivePacketNum = packetNum;
} }
else else
{
if (m_NumRanges && (m_OutOfSequencePackets.empty () ||
packetNum != (*m_OutOfSequencePackets.rbegin ()) + 1))
m_NumRanges = 0; // reset ranges if received packet is not next
m_OutOfSequencePackets.insert (packetNum); m_OutOfSequencePackets.insert (packetNum);
}
return true; return true;
} }
@ -2996,38 +3058,67 @@ namespace transport
void SSU2Session::SendPathResponse (const uint8_t * data, size_t len) void SSU2Session::SendPathResponse (const uint8_t * data, size_t len)
{ {
if (len > m_MaxPayloadSize - 3) uint8_t payload[SSU2_MAX_PACKET_SIZE];
size_t payloadSize = 0;
// datetime block
payload[0] = eSSU2BlkDateTime;
htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000);
payloadSize += 7;
// address block
payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, m_RemoteEndpoint);
// path response
if (payloadSize + len > m_MaxPayloadSize)
{ {
LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len); LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len);
return; return;
} }
uint8_t payload[SSU2_MAX_PACKET_SIZE]; payload[payloadSize] = eSSU2BlkPathResponse;
payload[0] = eSSU2BlkPathResponse; htobe16buf (payload + payloadSize + 1, len);
htobe16buf (payload + 1, len); memcpy (payload + payloadSize + 3, data, len);
memcpy (payload + 3, data, len); payloadSize += len + 3;
size_t payloadSize = len + 3; // ack block
if (payloadSize < m_MaxPayloadSize) if (payloadSize < m_MaxPayloadSize)
payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0); payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize);
// padding
if (payloadSize < m_MaxPayloadSize)
payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize);
SendData (payload, payloadSize); SendData (payload, payloadSize);
} }
void SSU2Session::SendPathChallenge () void SSU2Session::SendPathChallenge (const boost::asio::ip::udp::endpoint& to)
{ {
AdjustMaxPayloadSize (SSU2_MIN_PACKET_SIZE); // reduce to minimum
m_WindowSize = SSU2_MIN_WINDOW_SIZE; // reduce window to minimum
uint8_t payload[SSU2_MAX_PACKET_SIZE]; uint8_t payload[SSU2_MAX_PACKET_SIZE];
payload[0] = eSSU2BlkPathChallenge; size_t payloadSize = 0;
size_t len = m_Server.GetRng ()() % (m_MaxPayloadSize - 3); // datetime block
htobe16buf (payload + 1, len); payload[0] = eSSU2BlkDateTime;
if (len > 0) htobe16buf (payload + 1, 4);
{ htobe32buf (payload + 3, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000);
RAND_bytes (payload + 3, len); payloadSize += 7;
i2p::data::IdentHash * hash = new i2p::data::IdentHash (); // address block with new address
SHA256 (payload + 3, len, *hash); payloadSize += CreateAddressBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, to);
m_PathChallenge.reset (hash); // path challenge block
} payload[payloadSize] = eSSU2BlkPathChallenge;
len += 3; uint64_t challenge;
if (len < m_MaxPayloadSize) RAND_bytes ((uint8_t *)&challenge, 8);
len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0); htobe16buf (payload + payloadSize + 1, 8); // always 8 bytes
SendData (payload, len); htobuf64 (payload + payloadSize + 3, challenge);
payloadSize += 11;
m_PathChallenge = std::make_unique<std::pair<uint64_t, boost::asio::ip::udp::endpoint> >(challenge, to);
// ack block
if (payloadSize < m_MaxPayloadSize)
payloadSize += CreateAckBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize);
// padding block
if (payloadSize < m_MaxPayloadSize)
payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize);
// send to new endpoint
auto existing = m_RemoteEndpoint;
m_RemoteEndpoint = to; // send path challenge to new endpoint
SendData (payload, payloadSize);
m_RemoteEndpoint = existing; // restore endpoint back until path response received
} }
void SSU2Session::CleanUp (uint64_t ts) void SSU2Session::CleanUp (uint64_t ts)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, The PurpleI2P Project * Copyright (c) 2022-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -327,7 +327,7 @@ namespace transport
void SendQuickAck (); void SendQuickAck ();
void SendTermination (); void SendTermination ();
void SendPathResponse (const uint8_t * data, size_t len); void SendPathResponse (const uint8_t * data, size_t len);
void SendPathChallenge (); void SendPathChallenge (const boost::asio::ip::udp::endpoint& to);
void HandleDateTime (const uint8_t * buf, size_t len); void HandleDateTime (const uint8_t * buf, size_t len);
void HandleRouterInfo (const uint8_t * buf, size_t len); void HandleRouterInfo (const uint8_t * buf, size_t len);
@ -336,7 +336,7 @@ namespace transport
virtual void HandleAddress (const uint8_t * buf, size_t len); virtual void HandleAddress (const uint8_t * buf, size_t len);
size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep); size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
std::shared_ptr<const i2p::data::RouterInfo::Address> FindLocalAddress () const; std::shared_ptr<const i2p::data::RouterInfo::Address> FindLocalAddress () const;
void AdjustMaxPayloadSize (); void AdjustMaxPayloadSize (size_t maxMtu = SSU2_MAX_PACKET_SIZE);
bool GetTestingState () const; bool GetTestingState () const;
void SetTestingState(bool testing) const; void SetTestingState(bool testing) const;
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size); std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
@ -394,9 +394,11 @@ namespace transport
boost::asio::deadline_timer m_ConnectTimer; boost::asio::deadline_timer m_ConnectTimer;
SSU2TerminationReason m_TerminationReason; SSU2TerminationReason m_TerminationReason;
size_t m_MaxPayloadSize; size_t m_MaxPayloadSize;
std::unique_ptr<i2p::data::IdentHash> m_PathChallenge; std::unique_ptr<std::pair<uint64_t, boost::asio::ip::udp::endpoint> > m_PathChallenge;
std::unordered_map<uint32_t, uint32_t> m_ReceivedI2NPMsgIDs; // msgID -> timestamp in seconds std::unordered_map<uint32_t, uint32_t> m_ReceivedI2NPMsgIDs; // msgID -> timestamp in seconds
uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds uint64_t m_LastResendTime, m_LastResendAttemptTime; // in milliseconds
int m_NumRanges;
uint8_t m_Ranges[SSU2_MAX_NUM_ACK_RANGES*2]; // ranges sent with previous Ack if any
}; };
inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce) inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -7,6 +7,10 @@
*/ */
#include <memory> #include <memory>
#include <openssl/evp.h>
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
#include <openssl/core_names.h>
#endif
#include "Log.h" #include "Log.h"
#include "Signature.h" #include "Signature.h"
@ -14,6 +18,163 @@ namespace i2p
{ {
namespace crypto namespace crypto
{ {
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
DSAVerifier::DSAVerifier ():
m_PublicKey (nullptr)
{
}
DSAVerifier::~DSAVerifier ()
{
if (m_PublicKey)
EVP_PKEY_free (m_PublicKey);
}
void DSAVerifier::SetPublicKey (const uint8_t * signingKey)
{
if (m_PublicKey)
EVP_PKEY_free (m_PublicKey);
BIGNUM * pub = BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL);
m_PublicKey = CreateDSA (pub);
BN_free (pub);
}
bool DSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
// calculate SHA1 digest
uint8_t digest[20], sign[48];
SHA1 (buf, len, digest);
// signature
DSA_SIG * sig = DSA_SIG_new();
DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL));
// to DER format
uint8_t * s = sign;
auto l = i2d_DSA_SIG (sig, &s);
DSA_SIG_free(sig);
// verify
auto ctx = EVP_PKEY_CTX_new (m_PublicKey, NULL);
EVP_PKEY_verify_init(ctx);
EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1());
bool ret = EVP_PKEY_verify(ctx, sign, l, digest, 20);
EVP_PKEY_CTX_free(ctx);
return ret;
}
DSASigner::DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
{
BIGNUM * priv = BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL);
m_PrivateKey = CreateDSA (nullptr, priv);
BN_free (priv);
}
DSASigner::~DSASigner ()
{
if (m_PrivateKey)
EVP_PKEY_free (m_PrivateKey);
}
void DSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
uint8_t digest[20], sign[48];
SHA1 (buf, len, digest);
auto ctx = EVP_PKEY_CTX_new (m_PrivateKey, NULL);
EVP_PKEY_sign_init(ctx);
EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1());
size_t l = 48;
EVP_PKEY_sign(ctx, sign, &l, digest, 20);
const uint8_t * s1 = sign;
DSA_SIG * sig = d2i_DSA_SIG (NULL, &s1, l);
const BIGNUM * r, * s;
DSA_SIG_get0 (sig, &r, &s);
bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2);
bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2);
DSA_SIG_free(sig);
EVP_PKEY_CTX_free(ctx);
}
void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
{
EVP_PKEY * paramskey = CreateDSA();
EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new_from_pkey(NULL, paramskey, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY * pkey = nullptr;
EVP_PKEY_keygen(ctx, &pkey);
BIGNUM * pub = NULL, * priv = NULL;
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pub);
bn2buf (pub, signingPublicKey, DSA_PUBLIC_KEY_LENGTH);
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv);
bn2buf (priv, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH);
BN_free (pub); BN_free (priv);
EVP_PKEY_free (pkey);
EVP_PKEY_free (paramskey);
EVP_PKEY_CTX_free (ctx);
}
#else
DSAVerifier::DSAVerifier ()
{
m_PublicKey = CreateDSA ();
}
DSAVerifier::~DSAVerifier ()
{
DSA_free (m_PublicKey);
}
void DSAVerifier::SetPublicKey (const uint8_t * signingKey)
{
DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL);
}
bool DSAVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
// calculate SHA1 digest
uint8_t digest[20];
SHA1 (buf, len, digest);
// signature
DSA_SIG * sig = DSA_SIG_new();
DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL));
// DSA verification
int ret = DSA_do_verify (digest, 20, sig, m_PublicKey);
DSA_SIG_free(sig);
return ret;
}
DSASigner::DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey)
{
m_PrivateKey = CreateDSA ();
DSA_set0_key (m_PrivateKey, BN_bin2bn (signingPublicKey, DSA_PUBLIC_KEY_LENGTH, NULL), BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL));
}
DSASigner::~DSASigner ()
{
DSA_free (m_PrivateKey);
}
void DSASigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
uint8_t digest[20];
SHA1 (buf, len, digest);
DSA_SIG * sig = DSA_do_sign (digest, 20, m_PrivateKey);
const BIGNUM * r, * s;
DSA_SIG_get0 (sig, &r, &s);
bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2);
bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2);
DSA_SIG_free(sig);
}
void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
{
DSA * dsa = CreateDSA ();
DSA_generate_key (dsa);
const BIGNUM * pub_key, * priv_key;
DSA_get0_key(dsa, &pub_key, &priv_key);
bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH);
bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH);
DSA_free (dsa);
}
#endif
#if OPENSSL_EDDSA #if OPENSSL_EDDSA
EDDSA25519Verifier::EDDSA25519Verifier (): EDDSA25519Verifier::EDDSA25519Verifier ():
m_Pkey (nullptr) m_Pkey (nullptr)
@ -149,5 +310,178 @@ namespace crypto
LogPrint (eLogError, "EdDSA signing key is not set"); LogPrint (eLogError, "EdDSA signing key is not set");
} }
#endif #endif
#if (OPENSSL_VERSION_NUMBER >= 0x030000000)
static const OSSL_PARAM EDDSA25519phParams[] =
{
OSSL_PARAM_utf8_string ("instance", (char *)"Ed25519ph", 9),
OSSL_PARAM_END
};
bool EDDSA25519phVerifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
auto pkey = GetPkey ();
if (pkey)
{
uint8_t digest[64];
SHA512 (buf, len, digest);
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
EVP_DigestVerifyInit_ex (ctx, NULL, NULL, NULL, NULL, pkey, EDDSA25519phParams);
auto ret = EVP_DigestVerify (ctx, signature, 64, digest, 64);
EVP_MD_CTX_destroy (ctx);
return ret;
}
else
LogPrint (eLogError, "EdDSA verification key is not set");
return false;
}
EDDSA25519phSigner::EDDSA25519phSigner (const uint8_t * signingPrivateKey):
EDDSA25519Signer (signingPrivateKey)
{
}
void EDDSA25519phSigner::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
auto pkey = GetPkey ();
if (pkey)
{
uint8_t digest[64];
SHA512 (buf, len, digest);
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
size_t l = 64;
uint8_t sig[64];
EVP_DigestSignInit_ex (ctx, NULL, NULL, NULL, NULL, pkey, EDDSA25519phParams);
if (!EVP_DigestSign (ctx, sig, &l, digest, 64))
LogPrint (eLogError, "EdDSA signing failed");
memcpy (signature, sig, 64);
EVP_MD_CTX_destroy (ctx);
}
else
LogPrint (eLogError, "EdDSA signing key is not set");
}
#endif
#if OPENSSL_PQ
MLDSA44Verifier::MLDSA44Verifier ():
m_Pkey (nullptr)
{
}
MLDSA44Verifier::~MLDSA44Verifier ()
{
EVP_PKEY_free (m_Pkey);
}
void MLDSA44Verifier::SetPublicKey (const uint8_t * signingKey)
{
if (m_Pkey)
{
EVP_PKEY_free (m_Pkey);
m_Pkey = nullptr;
}
OSSL_PARAM params[] =
{
OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PUB_KEY, (uint8_t *)signingKey, GetPublicKeyLen ()),
OSSL_PARAM_END
};
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "ML-DSA-44", NULL);
if (ctx)
{
EVP_PKEY_fromdata_init (ctx);
EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY, params);
EVP_PKEY_CTX_free (ctx);
}
else
LogPrint (eLogError, "MLDSA44 can't create PKEY context");
}
bool MLDSA44Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
bool ret = false;
if (m_Pkey)
{
EVP_PKEY_CTX * vctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL);
if (vctx)
{
EVP_SIGNATURE * sig = EVP_SIGNATURE_fetch (NULL, "ML-DSA-44", NULL);
if (sig)
{
int encode = 1;
OSSL_PARAM params[] =
{
OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode),
OSSL_PARAM_END
};
EVP_PKEY_verify_message_init (vctx, sig, params);
ret = EVP_PKEY_verify (vctx, signature, GetSignatureLen (), buf, len);
EVP_SIGNATURE_free (sig);
}
EVP_PKEY_CTX_free (vctx);
}
else
LogPrint (eLogError, "MLDSA44 can't obtain context from PKEY");
}
else
LogPrint (eLogError, "MLDSA44 verification key is not set");
return ret;
}
MLDSA44Signer::MLDSA44Signer (const uint8_t * signingPrivateKey):
m_Pkey (nullptr)
{
OSSL_PARAM params[] =
{
OSSL_PARAM_octet_string (OSSL_PKEY_PARAM_PRIV_KEY, (uint8_t *)signingPrivateKey, MLDSA44_PRIVATE_KEY_LENGTH),
OSSL_PARAM_END
};
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "ML-DSA-44", NULL);
if (ctx)
{
EVP_PKEY_fromdata_init (ctx);
EVP_PKEY_fromdata (ctx, &m_Pkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY, params);
EVP_PKEY_CTX_free (ctx);
}
else
LogPrint (eLogError, "MLDSA44 can't create PKEY context");
}
MLDSA44Signer::~MLDSA44Signer ()
{
if (m_Pkey) EVP_PKEY_free (m_Pkey);
}
void MLDSA44Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
if (m_Pkey)
{
EVP_PKEY_CTX * sctx = EVP_PKEY_CTX_new_from_pkey (NULL, m_Pkey, NULL);
if (sctx)
{
EVP_SIGNATURE * sig = EVP_SIGNATURE_fetch (NULL, "ML-DSA-44", NULL);
if (sig)
{
int encode = 1;
OSSL_PARAM params[] =
{
OSSL_PARAM_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode),
OSSL_PARAM_END
};
EVP_PKEY_sign_message_init (sctx, sig, params);
size_t siglen = MLDSA44_SIGNATURE_LENGTH;
EVP_PKEY_sign (sctx, signature, &siglen, buf, len);
EVP_SIGNATURE_free (sig);
}
EVP_PKEY_CTX_free (sctx);
}
else
LogPrint (eLogError, "MLDSA44 can't obtain context from PKEY");
}
else
LogPrint (eLogError, "MLDSA44 signing key is not set");
}
#endif
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -43,6 +43,7 @@ namespace crypto
virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0;
}; };
// DSA
const size_t DSA_PUBLIC_KEY_LENGTH = 128; const size_t DSA_PUBLIC_KEY_LENGTH = 128;
const size_t DSA_SIGNATURE_LENGTH = 40; const size_t DSA_SIGNATURE_LENGTH = 40;
const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2; const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2;
@ -50,87 +51,47 @@ namespace crypto
{ {
public: public:
DSAVerifier () DSAVerifier ();
{ ~DSAVerifier ();
m_PublicKey = CreateDSA ();
}
void SetPublicKey (const uint8_t * signingKey) // implements Verifier
{ void SetPublicKey (const uint8_t * signingKey) override;
DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL); bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const override;
} size_t GetPublicKeyLen () const override { return DSA_PUBLIC_KEY_LENGTH; };
size_t GetSignatureLen () const override { return DSA_SIGNATURE_LENGTH; };
~DSAVerifier ()
{
DSA_free (m_PublicKey);
}
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
// calculate SHA1 digest
uint8_t digest[20];
SHA1 (buf, len, digest);
// signature
DSA_SIG * sig = DSA_SIG_new();
DSA_SIG_set0 (sig, BN_bin2bn (signature, DSA_SIGNATURE_LENGTH/2, NULL), BN_bin2bn (signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2, NULL));
// DSA verification
int ret = DSA_do_verify (digest, 20, sig, m_PublicKey);
DSA_SIG_free(sig);
return ret;
}
size_t GetPublicKeyLen () const { return DSA_PUBLIC_KEY_LENGTH; };
size_t GetSignatureLen () const { return DSA_SIGNATURE_LENGTH; };
private: private:
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
EVP_PKEY * m_PublicKey;
#else
DSA * m_PublicKey; DSA * m_PublicKey;
#endif
}; };
class DSASigner: public Signer class DSASigner: public Signer
{ {
public: public:
DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey);
// openssl 1.1 always requires DSA public key even for signing // openssl 1.1 always requires DSA public key even for signing
{ ~DSASigner ();
m_PrivateKey = CreateDSA ();
DSA_set0_key (m_PrivateKey, BN_bin2bn (signingPublicKey, DSA_PUBLIC_KEY_LENGTH, NULL), BN_bin2bn (signingPrivateKey, DSA_PRIVATE_KEY_LENGTH, NULL));
}
~DSASigner () // implements Signer
{ void Sign (const uint8_t * buf, int len, uint8_t * signature) const override;
DSA_free (m_PrivateKey);
}
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
uint8_t digest[20];
SHA1 (buf, len, digest);
DSA_SIG * sig = DSA_do_sign (digest, 20, m_PrivateKey);
const BIGNUM * r, * s;
DSA_SIG_get0 (sig, &r, &s);
bn2buf (r, signature, DSA_SIGNATURE_LENGTH/2);
bn2buf (s, signature + DSA_SIGNATURE_LENGTH/2, DSA_SIGNATURE_LENGTH/2);
DSA_SIG_free(sig);
}
private: private:
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
EVP_PKEY * m_PrivateKey;
#else
DSA * m_PrivateKey; DSA * m_PrivateKey;
#endif
}; };
inline void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey);
{
DSA * dsa = CreateDSA ();
DSA_generate_key (dsa);
const BIGNUM * pub_key, * priv_key;
DSA_get0_key(dsa, &pub_key, &priv_key);
bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH);
bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH);
DSA_free (dsa);
}
// ECDSA
struct SHA256Hash struct SHA256Hash
{ {
static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
@ -161,7 +122,6 @@ namespace crypto
enum { hashLen = 64 }; enum { hashLen = 64 };
}; };
// EcDSA
template<typename Hash, int curve, size_t keyLen> template<typename Hash, int curve, size_t keyLen>
class ECDSAVerifier: public Verifier class ECDSAVerifier: public Verifier
{ {
@ -304,13 +264,27 @@ namespace crypto
private: private:
#if OPENSSL_EDDSA #if OPENSSL_EDDSA
EVP_PKEY * m_Pkey; EVP_PKEY * m_Pkey;
protected:
EVP_PKEY * GetPkey () const { return m_Pkey; };
#else #else
EDDSAPoint m_PublicKey; EDDSAPoint m_PublicKey;
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
#endif #endif
}; };
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
class EDDSA25519phVerifier: public EDDSA25519Verifier
{
public:
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
};
#endif
class EDDSA25519SignerCompat: public Signer class EDDSA25519SignerCompat: public Signer
{ {
public: public:
@ -339,6 +313,10 @@ namespace crypto
void Sign (const uint8_t * buf, int len, uint8_t * signature) const; void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
protected:
EVP_PKEY * GetPkey () const { return m_Pkey; };
private: private:
EVP_PKEY * m_Pkey; EVP_PKEY * m_Pkey;
@ -348,6 +326,18 @@ namespace crypto
typedef EDDSA25519SignerCompat EDDSA25519Signer; typedef EDDSA25519SignerCompat EDDSA25519Signer;
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
class EDDSA25519phSigner: public EDDSA25519Signer
{
public:
EDDSA25519phSigner (const uint8_t * signingPrivateKey);
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
};
#endif #endif
inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
@ -530,6 +520,57 @@ namespace crypto
RedDSA25519Signer signer (signingPrivateKey); RedDSA25519Signer signer (signingPrivateKey);
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH); memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
} }
#if OPENSSL_PQ
#include <openssl/core_names.h>
// Post-Quantum
const size_t MLDSA44_PUBLIC_KEY_LENGTH = 1312;
const size_t MLDSA44_SIGNATURE_LENGTH = 2420;
const size_t MLDSA44_PRIVATE_KEY_LENGTH = 2560;
class MLDSA44Verifier: public Verifier
{
public:
MLDSA44Verifier ();
void SetPublicKey (const uint8_t * signingKey);
~MLDSA44Verifier ();
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
size_t GetPublicKeyLen () const { return MLDSA44_PUBLIC_KEY_LENGTH; };
size_t GetSignatureLen () const { return MLDSA44_SIGNATURE_LENGTH; };
size_t GetPrivateKeyLen () const { return MLDSA44_PRIVATE_KEY_LENGTH; };
private:
EVP_PKEY * m_Pkey;
};
class MLDSA44Signer: public Signer
{
public:
MLDSA44Signer (const uint8_t * signingPrivateKey);
~MLDSA44Signer ();
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
private:
EVP_PKEY * m_Pkey;
};
inline void CreateMLDSA44RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
{
EVP_PKEY * pkey = EVP_PKEY_Q_keygen (NULL, NULL, "ML-DSA-44");
size_t len = MLDSA44_PUBLIC_KEY_LENGTH;
EVP_PKEY_get_octet_string_param (pkey, OSSL_PKEY_PARAM_PUB_KEY, signingPublicKey, MLDSA44_PUBLIC_KEY_LENGTH, &len);
len = MLDSA44_PRIVATE_KEY_LENGTH;
EVP_PKEY_get_octet_string_param (pkey, OSSL_PKEY_PARAM_PRIV_KEY, signingPrivateKey, MLDSA44_PRIVATE_KEY_LENGTH, &len);
EVP_PKEY_free (pkey);
}
#endif
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -19,39 +19,55 @@ namespace i2p
{ {
namespace stream namespace stream
{ {
void SendBufferQueue::Add (std::shared_ptr<SendBuffer> buf) void SendBufferQueue::Add (std::shared_ptr<SendBuffer>&& buf)
{ {
if (buf) if (buf)
{ {
m_Buffers.push_back (buf);
m_Size += buf->len; m_Size += buf->len;
m_Buffers.push_back (std::move (buf));
} }
} }
size_t SendBufferQueue::Get (uint8_t * buf, size_t len) size_t SendBufferQueue::Get (uint8_t * buf, size_t len)
{ {
if (!m_Size) return 0;
size_t offset = 0; size_t offset = 0;
while (!m_Buffers.empty () && offset < len) if (len >= m_Size)
{ {
auto nextBuffer = m_Buffers.front (); for (auto& it: m_Buffers)
auto rem = nextBuffer->GetRemainingSize ();
if (offset + rem <= len)
{ {
// whole buffer auto rem = it->GetRemainingSize ();
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); memcpy (buf + offset, it->GetRemaningBuffer (), rem);
offset += rem; offset += rem;
m_Buffers.pop_front (); // delete it
}
else
{
// partially
rem = len - offset;
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem);
nextBuffer->offset += rem;
offset = len; // break
} }
m_Buffers.clear ();
m_Size = 0;
return offset;
}
else
{
while (!m_Buffers.empty () && offset < len)
{
auto nextBuffer = m_Buffers.front ();
auto rem = nextBuffer->GetRemainingSize ();
if (offset + rem <= len)
{
// whole buffer
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem);
offset += rem;
m_Buffers.pop_front (); // delete it
}
else
{
// partially
rem = len - offset;
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem);
nextBuffer->offset += rem;
offset = len; // break
}
}
m_Size -= offset;
} }
m_Size -= offset;
return offset; return offset;
} }
@ -59,7 +75,7 @@ namespace stream
{ {
if (!m_Buffers.empty ()) if (!m_Buffers.empty ())
{ {
for (auto it: m_Buffers) for (auto& it: m_Buffers)
it->Cancel (); it->Cancel ();
m_Buffers.clear (); m_Buffers.clear ();
m_Size = 0; m_Size = 0;
@ -80,7 +96,7 @@ namespace stream
m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO),
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0),
m_Jitter (0), m_MinPacingTime (0), m_Jitter (0), m_MinPacingTime (0),
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0),
m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed
m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU)
{ {
@ -107,7 +123,7 @@ namespace stream
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0), m_Jitter (0), m_MinPacingTime (0), m_PrevRTTSample (INITIAL_RTT), m_WindowSizeTail (0), m_Jitter (0), m_MinPacingTime (0),
m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_PacingTime (INITIAL_PACING_TIME), m_PacingTimeRem (0), m_LastSendTime (0), m_LastACKRecieveTime (0), m_ACKRecieveInterval (local.GetOwner ()->GetStreamingAckDelay ()), m_RemoteLeaseChangeTime (0), m_LastWindowIncTime (0),
m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed m_LastACKSendTime (0), m_PacketACKInterval (1), m_PacketACKIntervalRem (0), // for limit inbound speed
m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU) m_NumResendAttempts (0), m_NumPacketsToSend (0), m_MTU (STREAMING_MTU)
{ {
@ -613,10 +629,8 @@ namespace stream
if (wasInitial) if (wasInitial)
ScheduleResend (); ScheduleResend ();
} }
if (m_IsClientChoked && ackThrough > m_DropWindowDelaySequenceNumber) if (m_IsClientChoked && ackThrough >= m_DropWindowDelaySequenceNumber)
{
m_IsClientChoked = false; m_IsClientChoked = false;
}
if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber) if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber)
{ {
m_IsFirstRttSample = true; m_IsFirstRttSample = true;
@ -719,10 +733,10 @@ namespace stream
else if (handler) else if (handler)
handler(boost::system::error_code ()); handler(boost::system::error_code ());
auto s = shared_from_this (); auto s = shared_from_this ();
boost::asio::post (m_Service, [s, buffer]() boost::asio::post (m_Service, [s, buffer = std::move(buffer)]() mutable
{ {
if (buffer) if (buffer)
s->m_SendBuffer.Add (buffer); s->m_SendBuffer.Add (std::move(buffer));
s->SendBuffer (); s->SendBuffer ();
}); });
} }
@ -1297,8 +1311,14 @@ namespace stream
m_NumPacketsToSend = 1; m_PacingTimeRem = 0; m_NumPacketsToSend = 1; m_PacingTimeRem = 0;
} }
m_IsSendTime = true; m_IsSendTime = true;
if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) if (m_WindowIncCounter && (m_WindowSize < MAX_WINDOW_SIZE || m_WindowDropTargetSize) && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime && m_RTT <= m_SlowRTT)
{ {
float winSize = m_WindowSize;
if (m_WindowDropTargetSize)
winSize = m_WindowDropTargetSize;
float maxWinSize = MAX_WINDOW_SIZE;
if (m_LastWindowIncTime)
maxWinSize = (ts - m_LastWindowIncTime) / (m_RTT / MAX_WINDOW_SIZE_INC_PER_RTT) + winSize;
for (int i = 0; i < m_NumPacketsToSend; i++) for (int i = 0; i < m_NumPacketsToSend; i++)
{ {
if (m_WindowIncCounter) if (m_WindowIncCounter)
@ -1307,12 +1327,17 @@ namespace stream
{ {
if (m_LastWindowDropSize && (m_LastWindowDropSize >= m_WindowDropTargetSize)) if (m_LastWindowDropSize && (m_LastWindowDropSize >= m_WindowDropTargetSize))
m_WindowDropTargetSize += 1 - (1 / ((m_LastWindowDropSize + PREV_SPEED_KEEP_TIME_COEFF) / m_WindowDropTargetSize)); // some magic here m_WindowDropTargetSize += 1 - (1 / ((m_LastWindowDropSize + PREV_SPEED_KEEP_TIME_COEFF) / m_WindowDropTargetSize)); // some magic here
else if (m_LastWindowDropSize && (m_LastWindowDropSize < m_WindowSize)) else if (m_LastWindowDropSize && (m_LastWindowDropSize < m_WindowDropTargetSize))
m_WindowDropTargetSize += (m_WindowDropTargetSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; // some magic here m_WindowDropTargetSize += (m_WindowDropTargetSize - (m_LastWindowDropSize - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; // some magic here
else else
m_WindowDropTargetSize += (m_WindowDropTargetSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize; m_WindowDropTargetSize += (m_WindowDropTargetSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowDropTargetSize;
if (m_WindowDropTargetSize > MAX_WINDOW_SIZE) m_WindowDropTargetSize = MAX_WINDOW_SIZE; if (m_WindowDropTargetSize > MAX_WINDOW_SIZE) m_WindowDropTargetSize = MAX_WINDOW_SIZE;
m_WindowIncCounter--; m_WindowIncCounter--;
if (m_WindowDropTargetSize >= maxWinSize)
{
m_WindowDropTargetSize = maxWinSize;
break;
}
} }
else else
{ {
@ -1324,11 +1349,17 @@ namespace stream
m_WindowSize += (m_WindowSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize; m_WindowSize += (m_WindowSize - (1 - PREV_SPEED_KEEP_TIME_COEFF)) / m_WindowSize;
if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE; if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
m_WindowIncCounter--; m_WindowIncCounter--;
if (m_WindowSize >= maxWinSize)
{
m_WindowSize = maxWinSize;
break;
}
} }
} }
else else
break; break;
} }
m_LastWindowIncTime = ts;
UpdatePacingTime (); UpdatePacingTime ();
} }
else if (m_WindowIncCounter && m_WindowSize == MAX_WINDOW_SIZE && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime) else if (m_WindowIncCounter && m_WindowSize == MAX_WINDOW_SIZE && !m_SendBuffer.IsEmpty () && m_PacingTime > m_MinPacingTime)
@ -1646,14 +1677,22 @@ namespace stream
void Stream::ProcessWindowDrop () void Stream::ProcessWindowDrop ()
{ {
if (m_WindowSize > m_LastWindowDropSize) if (m_WindowDropTargetSize)
{ m_WindowDropTargetSize = (m_WindowDropTargetSize / 2) * 0.75; // congestion window size and -25% to drain queue
m_LastWindowDropSize = (m_LastWindowDropSize + m_WindowSize + m_WindowSizeTail) / 2;
if (m_LastWindowDropSize > MAX_WINDOW_SIZE) m_LastWindowDropSize = MAX_WINDOW_SIZE;
}
else else
m_LastWindowDropSize = m_WindowSize; {
m_WindowDropTargetSize = m_LastWindowDropSize - (m_LastWindowDropSize / 4); // -25%; if (m_WindowSize < m_LastWindowDropSize)
{
m_LastWindowDropSize = std::max ((m_WindowSize - MAX_WINDOW_SIZE_INC_PER_RTT), (m_WindowSize - (m_LastWindowDropSize - m_WindowSize)));
if (m_LastWindowDropSize < MIN_WINDOW_SIZE) m_LastWindowDropSize = MIN_WINDOW_SIZE;
}
else
{
m_LastWindowDropSize = std::max ((m_WindowSize - MAX_WINDOW_SIZE_INC_PER_RTT), ((m_LastWindowDropSize + m_WindowSize + m_WindowSizeTail) / 2));
if (m_LastWindowDropSize > MAX_WINDOW_SIZE) m_LastWindowDropSize = MAX_WINDOW_SIZE;
}
m_WindowDropTargetSize = m_LastWindowDropSize * 0.75; // -25% to drain queue
}
if (m_WindowDropTargetSize < MIN_WINDOW_SIZE) if (m_WindowDropTargetSize < MIN_WINDOW_SIZE)
m_WindowDropTargetSize = MIN_WINDOW_SIZE; m_WindowDropTargetSize = MIN_WINDOW_SIZE;
m_WindowIncCounter = 0; // disable window growth m_WindowIncCounter = 0; // disable window growth

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -57,6 +57,7 @@ namespace stream
const int INITIAL_WINDOW_SIZE = 10; const int INITIAL_WINDOW_SIZE = 10;
const int MIN_WINDOW_SIZE = 3; const int MIN_WINDOW_SIZE = 3;
const int MAX_WINDOW_SIZE = 512; const int MAX_WINDOW_SIZE = 512;
const int MAX_WINDOW_SIZE_INC_PER_RTT = 16;
const double RTT_EWMA_ALPHA = 0.25; const double RTT_EWMA_ALPHA = 0.25;
const double SLOWRTT_EWMA_ALPHA = 0.05; const double SLOWRTT_EWMA_ALPHA = 0.05;
const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer
@ -149,7 +150,7 @@ namespace stream
SendBufferQueue (): m_Size (0) {}; SendBufferQueue (): m_Size (0) {};
~SendBufferQueue () { CleanUp (); }; ~SendBufferQueue () { CleanUp (); };
void Add (std::shared_ptr<SendBuffer> buf); void Add (std::shared_ptr<SendBuffer>&& buf);
size_t Get (uint8_t * buf, size_t len); size_t Get (uint8_t * buf, size_t len);
size_t GetSize () const { return m_Size; }; size_t GetSize () const { return m_Size; };
bool IsEmpty () const { return m_Buffers.empty (); }; bool IsEmpty () const { return m_Buffers.empty (); };
@ -299,7 +300,7 @@ namespace stream
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_WindowSizeTail; int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample, m_WindowSizeTail;
double m_Jitter; double m_Jitter;
uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds uint64_t m_MinPacingTime, m_PacingTime, m_PacingTimeRem, // microseconds
m_LastSendTime, m_LastACKRecieveTime, m_ACKRecieveInterval, m_RemoteLeaseChangeTime; // milliseconds m_LastSendTime, m_LastACKRecieveTime, m_ACKRecieveInterval, m_RemoteLeaseChangeTime, m_LastWindowIncTime; // milliseconds
uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed uint64_t m_LastACKSendTime, m_PacketACKInterval, m_PacketACKIntervalRem; // for limit inbound speed
int m_NumResendAttempts, m_NumPacketsToSend; int m_NumResendAttempts, m_NumPacketsToSend;
size_t m_MTU; size_t m_MTU;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -12,10 +12,14 @@
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <string.h> #include <string.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <string>
#include <string_view>
#include "Base.h" #include "Base.h"
namespace i2p { namespace i2p
namespace data { {
namespace data
{
template<size_t sz> template<size_t sz>
class Tag class Tag
{ {
@ -58,26 +62,22 @@ namespace data {
std::string ToBase64 (size_t len = sz) const std::string ToBase64 (size_t len = sz) const
{ {
char str[sz*2]; return i2p::data::ByteStreamToBase64 (m_Buf, len);
size_t l = i2p::data::ByteStreamToBase64 (m_Buf, len, str, sz*2);
return std::string (str, str + l);
} }
std::string ToBase32 (size_t len = sz) const std::string ToBase32 (size_t len = sz) const
{ {
char str[sz*2]; return i2p::data::ByteStreamToBase32 (m_Buf, len);
size_t l = i2p::data::ByteStreamToBase32 (m_Buf, len, str, sz*2);
return std::string (str, str + l);
} }
size_t FromBase32 (const std::string& s) size_t FromBase32 (std::string_view s)
{ {
return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); return i2p::data::Base32ToByteStream (s, m_Buf, sz);
} }
size_t FromBase64 (const std::string& s) size_t FromBase64 (std::string_view s)
{ {
return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); return i2p::data::Base64ToByteStream (s, m_Buf, sz);
} }
uint8_t GetBit (int i) const uint8_t GetBit (int i) const

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -101,13 +101,13 @@ namespace tunnel
TunnelMessageBlock block; TunnelMessageBlock block;
block.deliveryType = eDeliveryTypeLocal; block.deliveryType = eDeliveryTypeLocal;
block.data = msg; block.data = msg;
std::unique_lock<std::mutex> l(m_SendMutex); std::lock_guard<std::mutex> l(m_SendMutex);
m_Gateway.PutTunnelDataMsg (block); m_Gateway.PutTunnelDataMsg (block);
} }
void TransitTunnelGateway::FlushTunnelDataMsgs () void TransitTunnelGateway::FlushTunnelDataMsgs ()
{ {
std::unique_lock<std::mutex> l(m_SendMutex); std::lock_guard<std::mutex> l(m_SendMutex);
m_Gateway.SendBuffer (); m_Gateway.SendBuffer ();
} }
@ -130,20 +130,36 @@ namespace tunnel
EncryptTunnelMsg (tunnelMsg, newMsg); EncryptTunnelMsg (tunnelMsg, newMsg);
LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ()); LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ());
m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); std::lock_guard<std::mutex> l(m_HandleMutex);
if (!m_Endpoint) m_Endpoint = std::make_unique<TunnelEndpoint>(false); // transit endpoint is always outbound
m_Endpoint->HandleDecryptedTunnelDataMsg (newMsg);
} }
void TransitTunnelEndpoint::FlushTunnelDataMsgs () void TransitTunnelEndpoint::FlushTunnelDataMsgs ()
{ {
m_Endpoint.FlushI2NPMsgs (); if (m_Endpoint)
{
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint->FlushI2NPMsgs ();
}
}
void TransitTunnelEndpoint::Cleanup ()
{
if (m_Endpoint)
{
std::lock_guard<std::mutex> l(m_HandleMutex);
m_Endpoint->Cleanup ();
}
} }
std::string TransitTunnelEndpoint::GetNextPeerName () const std::string TransitTunnelEndpoint::GetNextPeerName () const
{ {
auto hash = m_Endpoint.GetCurrentHash (); if (!m_Endpoint) return "";
auto hash = m_Endpoint->GetCurrentHash ();
if (hash) if (hash)
{ {
const auto& sender = m_Endpoint.GetSender (); const auto& sender = m_Endpoint->GetSender ();
if (sender) if (sender)
{ {
auto transport = sender->GetCurrentTransport (); auto transport = sender->GetCurrentTransport ();
@ -180,7 +196,7 @@ namespace tunnel
} }
TransitTunnels::TransitTunnels (): TransitTunnels::TransitTunnels ():
m_IsRunning (false) m_IsRunning (false), m_Rng(i2p::util::GetMonotonicMicroseconds ()%1000000LL)
{ {
} }
@ -320,19 +336,44 @@ namespace tunnel
// check if we accept this tunnel // check if we accept this tunnel
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel; std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
uint8_t retCode = 0; uint8_t retCode = 0;
if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL) if (i2p::context.AcceptsTunnels ())
{
auto congestionLevel = i2p::context.GetCongestionLevel (false);
if (congestionLevel < CONGESTION_LEVEL_FULL)
{
if (congestionLevel >= CONGESTION_LEVEL_MEDIUM)
{
// random reject depending on congestion level
int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
if (congestionLevel > level)
retCode = 30;
}
}
else
retCode = 30;
}
else
retCode = 30; retCode = 30;
if (!retCode) if (!retCode)
{ {
// create new transit tunnel i2p::data::IdentHash nextIdent(clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET);
transitTunnel = i2p::tunnel::CreateTransitTunnel ( bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, {
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), // create new transit tunnel
layerKey, ivKey, transitTunnel = CreateTransitTunnel (
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); nextIdent,
if (!AddTransitTunnel (transitTunnel)) bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
layerKey, ivKey,
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
isEndpoint);
if (!AddTransitTunnel (transitTunnel))
retCode = 30;
}
else
// decline tunnel going to duplicated router
retCode = 30; retCode = 30;
} }
@ -444,7 +485,7 @@ namespace tunnel
if (congestionLevel < CONGESTION_LEVEL_FULL) if (congestionLevel < CONGESTION_LEVEL_FULL)
{ {
// random reject depending on congestion level // random reject depending on congestion level
int level = i2p::tunnel::tunnels.GetRng ()() % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM; int level = m_Rng () % (CONGESTION_LEVEL_FULL - CONGESTION_LEVEL_MEDIUM) + CONGESTION_LEVEL_MEDIUM;
if (congestionLevel > level) if (congestionLevel > level)
accept = false; accept = false;
} }
@ -452,23 +493,32 @@ namespace tunnel
accept = false; accept = false;
} }
} }
// replace record to reply
if (accept) if (accept)
{ {
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( i2p::data::IdentHash nextIdent(clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET);
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bool isEndpoint = clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, if (isEndpoint || !i2p::data::IsRouterDuplicated (nextIdent))
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), {
clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, auto transitTunnel = CreateTransitTunnel (
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, nextIdent,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
if (!AddTransitTunnel (transitTunnel)) clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
isEndpoint);
if (!AddTransitTunnel (transitTunnel))
retCode = 30;
}
else
// decline tunnel going to duplicated router
retCode = 30; retCode = 30;
} }
else else
retCode = 30; // always reject with bandwidth reason (30) retCode = 30; // always reject with bandwidth reason (30)
// replace record to reply
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode; record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
// encrypt reply // encrypt reply

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -97,19 +97,19 @@ namespace tunnel
TransitTunnelEndpoint (uint32_t receiveTunnelID, TransitTunnelEndpoint (uint32_t receiveTunnelID,
const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID, const i2p::data::IdentHash& nextIdent, uint32_t nextTunnelID,
const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey): const i2p::crypto::AESKey& layerKey, const i2p::crypto::AESKey& ivKey):
TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey) {};
m_Endpoint (false) {}; // transit endpoint is always outbound
void Cleanup () override { m_Endpoint.Cleanup (); } void Cleanup () override;
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override; void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
void FlushTunnelDataMsgs () override; void FlushTunnelDataMsgs () override;
size_t GetNumTransmittedBytes () const override { return m_Endpoint.GetNumReceivedBytes (); } size_t GetNumTransmittedBytes () const override { return m_Endpoint ? m_Endpoint->GetNumReceivedBytes () : 0; }
std::string GetNextPeerName () const override; std::string GetNextPeerName () const override;
private: private:
TunnelEndpoint m_Endpoint; std::mutex m_HandleMutex;
std::unique_ptr<TunnelEndpoint> m_Endpoint;
}; };
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID, std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
@ -151,6 +151,7 @@ namespace tunnel
std::unique_ptr<std::thread> m_Thread; std::unique_ptr<std::thread> m_Thread;
std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels; std::list<std::shared_ptr<TransitTunnel> > m_TransitTunnels;
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue; i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_TunnelBuildMsgQueue;
std::mt19937 m_Rng;
public: public:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -10,7 +10,7 @@
#define TRANSPORT_SESSION_H__ #define TRANSPORT_SESSION_H__
#include <inttypes.h> #include <inttypes.h>
#include <iostream> #include <string.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <mutex> #include <mutex>
@ -28,45 +28,51 @@ namespace transport
const size_t IPV6_HEADER_SIZE = 40; const size_t IPV6_HEADER_SIZE = 40;
const size_t UDP_HEADER_SIZE = 8; const size_t UDP_HEADER_SIZE = 8;
template<size_t sz>
class SignedData class SignedData
{ {
public: public:
SignedData () {} SignedData (): m_Size(0) {}
SignedData (const SignedData& other) SignedData (const SignedData& other)
{ {
m_Stream << other.m_Stream.rdbuf (); m_Size = other.m_Size;
memcpy (m_Buf, other.m_Buf, m_Size);
} }
void Reset () void Reset ()
{ {
m_Stream.str(""); m_Size = 0;
} }
void Insert (const uint8_t * buf, size_t len) size_t Insert (const uint8_t * buf, size_t len)
{ {
m_Stream.write ((char *)buf, len); if (m_Size + len > sz) len = sz - m_Size;
memcpy (m_Buf + m_Size, buf, len);
m_Size += len;
return len;
} }
template<typename T> template<typename T>
void Insert (T t) void Insert (T t)
{ {
m_Stream.write ((char *)&t, sizeof (T)); Insert ((const uint8_t *)&t, sizeof (T));
} }
bool Verify (std::shared_ptr<const i2p::data::IdentityEx> ident, const uint8_t * signature) const bool Verify (std::shared_ptr<const i2p::data::IdentityEx> ident, const uint8_t * signature) const
{ {
return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); return ident->Verify (m_Buf, m_Size, signature);
} }
void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const
{ {
keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); keys.Sign (m_Buf, m_Size, signature);
} }
private: private:
std::stringstream m_Stream; uint8_t m_Buf[sz];
size_t m_Size;
}; };
const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -160,7 +160,8 @@ namespace transport
m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0), m_TotalSentBytes (0), m_TotalReceivedBytes (0), m_TotalTransitTransmittedBytes (0),
m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0), m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth (0),
m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0), m_InBandwidth15s (0), m_OutBandwidth15s (0), m_TransitBandwidth15s (0),
m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0) m_InBandwidth5m (0), m_OutBandwidth5m (0), m_TransitBandwidth5m (0),
m_Rng(i2p::util::GetMonotonicMicroseconds () % 1000000LL)
{ {
} }
@ -338,7 +339,7 @@ namespace transport
if (m_IsNAT) if (m_IsNAT)
{ {
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL)); m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
} }
} }
@ -560,7 +561,14 @@ namespace transport
bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer) bool Transports::ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer)
{ {
if (!peer->router) // reconnect if (!peer->router) // reconnect
peer->SetRouter (netdb.FindRouter (ident)); // try to get new one from netdb {
auto r = netdb.FindRouter (ident); // try to get new one from netdb
if (r)
{
peer->SetRouter (r);
r->CancelBufferToDelete ();
}
}
if (peer->router) // we have RI already if (peer->router) // we have RI already
{ {
if (peer->priority.empty ()) if (peer->priority.empty ())
@ -647,7 +655,7 @@ namespace transport
return true; return true;
} }
void Transports::SetPriority (std::shared_ptr<Peer> peer) const void Transports::SetPriority (std::shared_ptr<Peer> peer)
{ {
static const std::vector<i2p::data::RouterInfo::SupportedTransports> static const std::vector<i2p::data::RouterInfo::SupportedTransports>
ntcp2Priority = ntcp2Priority =
@ -672,8 +680,21 @@ namespace transport
auto directTransports = compatibleTransports & peer->router->GetPublishedTransports (); auto directTransports = compatibleTransports & peer->router->GetPublishedTransports ();
peer->numAttempts = 0; peer->numAttempts = 0;
peer->priority.clear (); peer->priority.clear ();
bool isReal = peer->router->GetProfile ()->IsReal ();
bool ssu2 = isReal ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real std::shared_ptr<RouterProfile> profile;
if (peer->router->HasProfile ()) profile = peer->router->GetProfile (); // only if in memory
bool ssu2 = false; // NTCP2 by default
bool isReal = profile ? profile->IsReal () : true;
if (isReal)
{
ssu2 = m_Rng () & 1; // 1/2
if (ssu2 && !profile)
{
profile = peer->router->GetProfile (); // load profile if necessary
isReal = profile->IsReal ();
if (!isReal) ssu2 = false; // try NTCP2 if router is not confirmed real
}
}
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority; const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
if (directTransports) if (directTransports)
{ {
@ -701,7 +722,8 @@ namespace transport
// try recently connected SSU2 if any // try recently connected SSU2 if any
auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) & auto supportedTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
peer->router->GetCompatibleTransports (false); peer->router->GetCompatibleTransports (false);
if (supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) if ((supportedTransports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) &&
peer->router->HasProfile ())
{ {
auto ep = peer->router->GetProfile ()->GetLastEndpoint (); auto ep = peer->router->GetProfile ()->GetLastEndpoint ();
if (!ep.address ().is_unspecified () && ep.port ()) if (!ep.address ().is_unspecified () && ep.port ())
@ -791,7 +813,7 @@ namespace transport
} }
else else
{ {
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service) if (m_Service)
{ {
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service); auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
@ -829,7 +851,7 @@ namespace transport
} }
else else
{ {
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE; testDelay += PEER_TEST_DELAY_INTERVAL + m_Rng() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service) if (m_Service)
{ {
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service); auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
@ -886,7 +908,11 @@ namespace transport
auto transport = peer->priority[peer->numAttempts-1]; auto transport = peer->priority[peer->numAttempts-1];
if (transport == i2p::data::RouterInfo::eNTCP2V4 || if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh) transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
peer->router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real i2p::data::UpdateRouterProfile (ident,
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Connected (); // outgoing NTCP2 connection if always real
});
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
} }
peer->numAttempts = 0; peer->numAttempts = 0;
@ -921,7 +947,11 @@ namespace transport
session->SendI2NPMessages (msgs); // send DatabaseStore session->SendI2NPMessages (msgs); // send DatabaseStore
} }
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
if (r) r->GetProfile ()->Connected (); i2p::data::UpdateRouterProfile (ident,
[](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->Connected ();
});
auto ts = i2p::util::GetSecondsSinceEpoch (); auto ts = i2p::util::GetSecondsSinceEpoch ();
auto peer = std::make_shared<Peer>(r, ts); auto peer = std::make_shared<Peer>(r, ts);
peer->sessions.push_back (session); peer->sessions.push_back (session);
@ -955,8 +985,13 @@ namespace transport
} }
else else
{ {
std::lock_guard<std::mutex> l(m_PeersMutex); {
m_Peers.erase (it); std::lock_guard<std::mutex> l(m_PeersMutex);
m_Peers.erase (it);
}
// delete buffer of just disconnected router
auto r = i2p::data::netdb.FindRouter (ident);
if (r && !r->IsUpdated ()) r->ScheduleBufferToDelete ();
} }
} }
} }
@ -1006,7 +1041,7 @@ namespace transport
if (session) if (session)
session->SendLocalRouterInfo (true); session->SendLocalRouterInfo (true);
it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL + it->second->nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE; m_Rng() % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
} }
++it; ++it;
} }
@ -1020,7 +1055,7 @@ namespace transport
// if still testing or unknown, repeat peer test // if still testing or unknown, repeat peer test
if (ipv4Testing || ipv6Testing) if (ipv4Testing || ipv6Testing)
PeerTest (ipv4Testing, ipv6Testing); PeerTest (ipv4Testing, ipv6Testing);
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT)); m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(2 * SESSION_CREATION_TIMEOUT + m_Rng() % SESSION_CREATION_TIMEOUT));
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1)); m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
} }
} }
@ -1030,7 +1065,7 @@ namespace transport
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
{ {
PeerTest (); PeerTest ();
m_PeerTestTimer->expires_from_now (boost::posix_time::minutes(PEER_TEST_INTERVAL)); m_PeerTestTimer->expires_from_now (boost::posix_time::seconds(PEER_TEST_INTERVAL + m_Rng() % PEER_TEST_INTERVAL_VARIANCE));
m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1)); m_PeerTestTimer->async_wait (std::bind (&Transports::HandlePeerTestTimer, this, std::placeholders::_1));
} }
} }
@ -1160,7 +1195,7 @@ namespace transport
std::lock_guard<std::mutex> lock(m_TrustedRoutersMutex); std::lock_guard<std::mutex> lock(m_TrustedRoutersMutex);
m_TrustedRouters.clear(); m_TrustedRouters.clear();
for (const auto & ri : routers ) for (const auto & ri : routers )
m_TrustedRouters.push_back(ri); m_TrustedRouters.insert(ri);
} }
bool Transports::RoutesRestricted() const bool Transports::RoutesRestricted() const
@ -1177,7 +1212,7 @@ namespace transport
} }
/** XXX: if routes are not restricted this dies */ /** XXX: if routes are not restricted this dies */
std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer() const std::shared_ptr<const i2p::data::RouterInfo> Transports::GetRestrictedPeer()
{ {
{ {
std::lock_guard<std::mutex> l(m_FamilyMutex); std::lock_guard<std::mutex> l(m_FamilyMutex);
@ -1186,7 +1221,7 @@ namespace transport
if(sz > 1) if(sz > 1)
{ {
auto it = m_TrustedFamilies.begin (); auto it = m_TrustedFamilies.begin ();
std::advance(it, rand() % sz); std::advance(it, m_Rng() % sz);
fam = *it; fam = *it;
} }
else if (sz == 1) else if (sz == 1)
@ -1201,23 +1236,32 @@ namespace transport
auto sz = m_TrustedRouters.size(); auto sz = m_TrustedRouters.size();
if (sz) if (sz)
{ {
if(sz == 1)
return i2p::data::netdb.FindRouter(m_TrustedRouters[0]);
auto it = m_TrustedRouters.begin(); auto it = m_TrustedRouters.begin();
std::advance(it, rand() % sz); if(sz > 1)
std::advance(it, m_Rng() % sz);
return i2p::data::netdb.FindRouter(*it); return i2p::data::netdb.FindRouter(*it);
} }
} }
return nullptr; return nullptr;
} }
bool Transports::IsRestrictedPeer(const i2p::data::IdentHash & ih) const bool Transports::IsTrustedRouter (const i2p::data::IdentHash& ih) const
{ {
{ if (m_TrustedRouters.empty ()) return false;
std::lock_guard<std::mutex> l(m_TrustedRoutersMutex); std::lock_guard<std::mutex> l(m_TrustedRoutersMutex);
for (const auto & r : m_TrustedRouters ) #if __cplusplus >= 202002L // C++20
if ( r == ih ) return true; if (m_TrustedRouters.contains (ih))
} #else
if (m_TrustedRouters.count (ih) > 0)
#endif
return true;
return false;
}
bool Transports::IsRestrictedPeer(const i2p::data::IdentHash& ih) const
{
if (IsTrustedRouter (ih)) return true;
{ {
std::lock_guard<std::mutex> l(m_FamilyMutex); std::lock_guard<std::mutex> l(m_FamilyMutex);
auto ri = i2p::data::netdb.FindRouter(ih); auto ri = i2p::data::netdb.FindRouter(ih);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -15,11 +15,13 @@
#include <condition_variable> #include <condition_variable>
#include <functional> #include <functional>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <string> #include <string>
#include <memory> #include <memory>
#include <atomic> #include <atomic>
#include <random>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include "TransportSession.h" #include "TransportSession.h"
#include "SSU2.h" #include "SSU2.h"
@ -106,7 +108,8 @@ namespace transport
}; };
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
const int PEER_TEST_INTERVAL = 71; // in minutes const int PEER_TEST_INTERVAL = 68*60; // in seconds
const int PEER_TEST_INTERVAL_VARIANCE = 3*60; // in seconds
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
const int MAX_NUM_DELAYED_MESSAGES = 150; const int MAX_NUM_DELAYED_MESSAGES = 150;
@ -168,7 +171,7 @@ namespace transport
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const; std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer (bool isHighBandwidth) const;
/** get a trusted first hop for restricted routes */ /** get a trusted first hop for restricted routes */
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const; std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer();
/** do we want to use restricted routes? */ /** do we want to use restricted routes? */
bool RoutesRestricted() const; bool RoutesRestricted() const;
/** restrict routes to use only these router families for first hops */ /** restrict routes to use only these router families for first hops */
@ -176,7 +179,8 @@ namespace transport
/** restrict routes to use only these routers for first hops */ /** restrict routes to use only these routers for first hops */
void RestrictRoutesToRouters(const std::set<i2p::data::IdentHash>& routers); void RestrictRoutesToRouters(const std::set<i2p::data::IdentHash>& routers);
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const; bool IsTrustedRouter (const i2p::data::IdentHash& ih) const;
bool IsRestrictedPeer(const i2p::data::IdentHash& ih) const;
void PeerTest (bool ipv4 = true, bool ipv6 = true); void PeerTest (bool ipv4 = true, bool ipv6 = true);
@ -191,7 +195,7 @@ namespace transport
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident); void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
std::shared_ptr<TransportSession> PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs); std::shared_ptr<TransportSession> PostMessages (const i2p::data::IdentHash& ident, std::list<std::shared_ptr<i2p::I2NPMessage> >& msgs);
bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer); bool ConnectToPeer (const i2p::data::IdentHash& ident, std::shared_ptr<Peer> peer);
void SetPriority (std::shared_ptr<Peer> peer) const; void SetPriority (std::shared_ptr<Peer> peer);
void HandlePeerCleanupTimer (const boost::system::error_code& ecode); void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
void HandlePeerTestTimer (const boost::system::error_code& ecode); void HandlePeerTestTimer (const boost::system::error_code& ecode);
void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode); void HandleUpdateBandwidthTimer (const boost::system::error_code& ecode);
@ -235,10 +239,11 @@ namespace transport
mutable std::mutex m_FamilyMutex; mutable std::mutex m_FamilyMutex;
/** which routers for first hop to trust */ /** which routers for first hop to trust */
std::vector<i2p::data::IdentHash> m_TrustedRouters; std::unordered_set<i2p::data::IdentHash> m_TrustedRouters;
mutable std::mutex m_TrustedRoutersMutex; mutable std::mutex m_TrustedRoutersMutex;
i2p::I2NPMessagesHandler m_LoopbackHandler; i2p::I2NPMessagesHandler m_LoopbackHandler;
std::mt19937 m_Rng;
public: public:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -103,7 +103,7 @@ namespace tunnel
if (m_Config->IsShort ()) if (m_Config->IsShort ())
{ {
auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr; auto ident = m_Config->GetFirstHop () ? m_Config->GetFirstHop ()->ident : nullptr;
if (ident && ident->GetIdentHash () != outboundTunnel->GetNextIdentHash ()) // don't encrypt if IBGW = OBEP if (ident && ident->GetIdentHash () != outboundTunnel->GetEndpointIdentHash ()) // don't encrypt if IBGW = OBEP
{ {
auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ()); auto msg1 = i2p::garlic::WrapECIESX25519MessageForRouter (msg, ident->GetEncryptionPublicKey ());
if (msg1) msg = msg1; if (msg1) msg = msg1;
@ -179,9 +179,12 @@ namespace tunnel
{ {
uint8_t ret = hop->GetRetCode (msg + 1); uint8_t ret = hop->GetRetCode (msg + 1);
LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret); LogPrint (eLogDebug, "Tunnel: Build response ret code=", (int)ret);
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ()); if (hop->ident)
if (profile) i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
profile->TunnelBuildResponse (ret); [ret](std::shared_ptr<i2p::data::RouterProfile> profile)
{
if (profile) profile->TunnelBuildResponse (ret);
});
if (ret) if (ret)
// if any of participants declined the tunnel is not established // if any of participants declined the tunnel is not established
established = false; established = false;
@ -278,6 +281,21 @@ namespace tunnel
m_Endpoint.HandleDecryptedTunnelDataMsg (msg); m_Endpoint.HandleDecryptedTunnelDataMsg (msg);
} }
bool InboundTunnel::Recreate ()
{
if (!IsRecreated ())
{
auto pool = GetTunnelPool ();
if (pool)
{
SetRecreated (true);
pool->RecreateInboundTunnel (std::static_pointer_cast<InboundTunnel>(shared_from_this ()));
return true;
}
}
return false;
}
ZeroHopsInboundTunnel::ZeroHopsInboundTunnel (): ZeroHopsInboundTunnel::ZeroHopsInboundTunnel ():
InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()), InboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
m_NumReceivedBytes (0) m_NumReceivedBytes (0)
@ -297,22 +315,28 @@ namespace tunnel
void OutboundTunnel::SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg) void OutboundTunnel::SendTunnelDataMsgTo (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr<i2p::I2NPMessage> msg)
{ {
TunnelMessageBlock block; TunnelMessageBlock block;
block.tunnelID = 0; // Initialize tunnelID to a default value
if (gwHash) if (gwHash)
{ {
block.hash = gwHash; block.hash = gwHash;
if (gwTunnel) if (gwTunnel)
{ {
block.deliveryType = eDeliveryTypeTunnel; block.deliveryType = eDeliveryTypeTunnel;
block.tunnelID = gwTunnel; block.tunnelID = gwTunnel; // Set tunnelID only if gwTunnel is non-zero
} }
else else
{
block.deliveryType = eDeliveryTypeRouter; block.deliveryType = eDeliveryTypeRouter;
}
} }
else else
{
block.deliveryType = eDeliveryTypeLocal; block.deliveryType = eDeliveryTypeLocal;
block.data = msg; }
SendTunnelDataMsgs ({block}); block.data = msg;
SendTunnelDataMsgs({block});
} }
void OutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs) void OutboundTunnel::SendTunnelDataMsgs (const std::vector<TunnelMessageBlock>& msgs)
@ -328,6 +352,21 @@ namespace tunnel
LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ()); LogPrint (eLogError, "Tunnel: Incoming message for outbound tunnel ", GetTunnelID ());
} }
bool OutboundTunnel::Recreate ()
{
if (!IsRecreated ())
{
auto pool = GetTunnelPool ();
if (pool)
{
SetRecreated (true);
pool->RecreateOutboundTunnel (std::static_pointer_cast<OutboundTunnel>(shared_from_this ()));
return true;
}
}
return false;
}
ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel (): ZeroHopsOutboundTunnel::ZeroHopsOutboundTunnel ():
OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()), OutboundTunnel (std::make_shared<ZeroHopsTunnelConfig> ()),
m_NumSentBytes (0) m_NumSentBytes (0)
@ -434,7 +473,7 @@ namespace tunnel
std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel () std::shared_ptr<OutboundTunnel> Tunnels::GetNextOutboundTunnel ()
{ {
if (m_OutboundTunnels.empty ()) return nullptr; if (m_OutboundTunnels.empty ()) return nullptr;
uint32_t ind = rand () % m_OutboundTunnels.size (), i = 0; uint32_t ind = m_Rng () % m_OutboundTunnels.size (), i = 0;
std::shared_ptr<OutboundTunnel> tunnel; std::shared_ptr<OutboundTunnel> tunnel;
for (const auto& it: m_OutboundTunnels) for (const auto& it: m_OutboundTunnels)
{ {
@ -711,8 +750,17 @@ namespace tunnel
void Tunnels::ManageTunnels (uint64_t ts) void Tunnels::ManageTunnels (uint64_t ts)
{ {
ManagePendingTunnels (ts); ManagePendingTunnels (ts);
ManageInboundTunnels (ts); std::vector<std::shared_ptr<Tunnel> > tunnelsToRecreate;
ManageOutboundTunnels (ts); ManageInboundTunnels (ts, tunnelsToRecreate);
ManageOutboundTunnels (ts, tunnelsToRecreate);
// rec-create in random order
if (!tunnelsToRecreate.empty ())
{
if (tunnelsToRecreate.size () > 1)
std::shuffle (tunnelsToRecreate.begin(), tunnelsToRecreate.end(), m_Rng);
for (auto& it: tunnelsToRecreate)
it->Recreate ();
}
} }
void Tunnels::ManagePendingTunnels (uint64_t ts) void Tunnels::ManagePendingTunnels (uint64_t ts)
@ -743,11 +791,11 @@ namespace tunnel
while (hop) while (hop)
{ {
if (hop->ident) if (hop->ident)
{ i2p::data::UpdateRouterProfile (hop->ident->GetIdentHash (),
auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ()); [](std::shared_ptr<i2p::data::RouterProfile> profile)
if (profile) {
profile->TunnelNonReplied (); if (profile) profile->TunnelNonReplied ();
} });
hop = hop->next; hop = hop->next;
} }
} }
@ -775,7 +823,7 @@ namespace tunnel
} }
} }
void Tunnels::ManageOutboundTunnels (uint64_t ts) void Tunnels::ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
{ {
for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();) for (auto it = m_OutboundTunnels.begin (); it != m_OutboundTunnels.end ();)
{ {
@ -799,10 +847,7 @@ namespace tunnel
auto pool = tunnel->GetTunnelPool (); auto pool = tunnel->GetTunnelPool ();
// let it die if the tunnel pool has been reconfigured and this is old // let it die if the tunnel pool has been reconfigured and this is old
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops()) if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
{ toRecreate.push_back (tunnel);
tunnel->SetRecreated (true);
pool->RecreateOutboundTunnel (tunnel);
}
} }
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
tunnel->SetState (eTunnelStateExpiring); tunnel->SetState (eTunnelStateExpiring);
@ -827,7 +872,7 @@ namespace tunnel
} }
} }
void Tunnels::ManageInboundTunnels (uint64_t ts) void Tunnels::ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate)
{ {
for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();) for (auto it = m_InboundTunnels.begin (); it != m_InboundTunnels.end ();)
{ {
@ -851,10 +896,7 @@ namespace tunnel
auto pool = tunnel->GetTunnelPool (); auto pool = tunnel->GetTunnelPool ();
// let it die if the tunnel pool was reconfigured and has different number of hops // let it die if the tunnel pool was reconfigured and has different number of hops
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops()) if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
{ toRecreate.push_back (tunnel);
tunnel->SetRecreated (true);
pool->RecreateInboundTunnel (tunnel);
}
} }
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT) if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -99,6 +99,7 @@ namespace tunnel
void SetRecreated (bool recreated) { m_IsRecreated = recreated; }; void SetRecreated (bool recreated) { m_IsRecreated = recreated; };
int GetNumHops () const { return m_Hops.size (); }; int GetNumHops () const { return m_Hops.size (); };
virtual bool IsInbound() const = 0; virtual bool IsInbound() const = 0;
virtual bool Recreate () = 0;
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; }; std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; }; void SetTunnelPool (std::shared_ptr<TunnelPool> pool) { m_Pool = pool; };
@ -150,6 +151,7 @@ namespace tunnel
void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override; void HandleTunnelDataMsg (std::shared_ptr<i2p::I2NPMessage>&& tunnelMsg) override;
bool IsInbound() const override { return false; } bool IsInbound() const override { return false; }
bool Recreate () override;
private: private:
@ -166,6 +168,7 @@ namespace tunnel
void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override; void HandleTunnelDataMsg (std::shared_ptr<I2NPMessage>&& msg) override;
virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); }; virtual size_t GetNumReceivedBytes () const { return m_Endpoint.GetNumReceivedBytes (); };
bool IsInbound() const override { return true; } bool IsInbound() const override { return true; }
bool Recreate () override;
// override TunnelBase // override TunnelBase
void Cleanup () override { m_Endpoint.Cleanup (); }; void Cleanup () override { m_Endpoint.Cleanup (); };
@ -246,8 +249,6 @@ namespace tunnel
uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; }; uint32_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.GetNumTransitTunnels () / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; } int GetCongestionLevel() const { return m_MaxNumTransitTunnels ? CONGESTION_LEVEL_FULL * m_TransitTunnels.GetNumTransitTunnels () / m_MaxNumTransitTunnels : CONGESTION_LEVEL_FULL; }
std::mt19937& GetRng () { return m_Rng; };
private: private:
template<class TTunnel> template<class TTunnel>
@ -264,8 +265,8 @@ namespace tunnel
void Run (); void Run ();
void ManageTunnels (uint64_t ts); void ManageTunnels (uint64_t ts);
void ManageOutboundTunnels (uint64_t ts); void ManageOutboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
void ManageInboundTunnels (uint64_t ts); void ManageInboundTunnels (uint64_t ts, std::vector<std::shared_ptr<Tunnel> >& toRecreate);
void ManagePendingTunnels (uint64_t ts); void ManagePendingTunnels (uint64_t ts);
template<class PendingTunnels> template<class PendingTunnels>
void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts); void ManagePendingTunnels (PendingTunnels& pendingTunnels, uint64_t ts);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -258,9 +258,8 @@ namespace tunnel
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum,
bool isLastFragment, const uint8_t * fragment, size_t size) bool isLastFragment, const uint8_t * fragment, size_t size)
{ {
std::unique_ptr<Fragment> f(new Fragment (isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), size)); if (!m_OutOfSequenceFragments.try_emplace ((uint64_t)msgID << 32 | fragmentNum,
memcpy (f->data.data (), fragment, size); isLastFragment, i2p::util::GetMillisecondsSinceEpoch (), fragment, size).second)
if (!m_OutOfSequenceFragments.emplace ((uint64_t)msgID << 32 | fragmentNum, std::move (f)).second)
LogPrint (eLogInfo, "TunnelMessage: Duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); LogPrint (eLogInfo, "TunnelMessage: Duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID);
} }
@ -290,7 +289,7 @@ namespace tunnel
if (it != m_OutOfSequenceFragments.end ()) if (it != m_OutOfSequenceFragments.end ())
{ {
LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found"); LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found");
size_t size = it->second->data.size (); size_t size = it->second.data.size ();
if (msg.data->len + size > msg.data->maxLen) if (msg.data->len + size > msg.data->maxLen)
{ {
LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough"); LogPrint (eLogWarning, "TunnelMessage: Tunnel endpoint I2NP message size ", msg.data->maxLen, " is not enough");
@ -298,9 +297,9 @@ namespace tunnel
*newMsg = *(msg.data); *newMsg = *(msg.data);
msg.data = newMsg; msg.data = newMsg;
} }
if (msg.data->Concat (it->second->data.data (), size) < size) // concatenate out-of-sync fragment if (msg.data->Concat (it->second.data.data (), size) < size) // concatenate out-of-sync fragment
LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen); LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen);
if (it->second->isLastFragment) if (it->second.isLastFragment)
// message complete // message complete
msg.nextFragmentNum = 0; msg.nextFragmentNum = 0;
else else
@ -349,7 +348,7 @@ namespace tunnel
// out-of-sequence fragments // out-of-sequence fragments
for (auto it = m_OutOfSequenceFragments.begin (); it != m_OutOfSequenceFragments.end ();) for (auto it = m_OutOfSequenceFragments.begin (); it != m_OutOfSequenceFragments.end ();)
{ {
if (ts > it->second->receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT) if (ts > it->second.receiveTime + i2p::I2NP_MESSAGE_EXPIRATION_TIMEOUT)
it = m_OutOfSequenceFragments.erase (it); it = m_OutOfSequenceFragments.erase (it);
else else
++it; ++it;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -32,7 +32,8 @@ namespace tunnel
struct Fragment struct Fragment
{ {
Fragment (bool last, uint64_t t, size_t size): isLastFragment (last), receiveTime (t), data (size) {}; Fragment (bool last, uint64_t t, const uint8_t * buf, size_t size):
isLastFragment (last), receiveTime (t), data (size) { memcpy (data.data(), buf, size); };
bool isLastFragment; bool isLastFragment;
uint64_t receiveTime; // milliseconds since epoch uint64_t receiveTime; // milliseconds since epoch
std::vector<uint8_t> data; std::vector<uint8_t> data;
@ -48,7 +49,7 @@ namespace tunnel
void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg); void HandleDecryptedTunnelDataMsg (std::shared_ptr<I2NPMessage> msg);
void FlushI2NPMsgs (); void FlushI2NPMsgs ();
const i2p::data::IdentHash * GetCurrentHash () const; // return null if not avaiable const i2p::data::IdentHash * GetCurrentHash () const; // return null if not available
const std::unique_ptr<TunnelTransportSender>& GetSender () const { return m_Sender; }; const std::unique_ptr<TunnelTransportSender>& GetSender () const { return m_Sender; };
private: private:
@ -67,7 +68,7 @@ namespace tunnel
private: private:
std::unordered_map<uint32_t, TunnelMessageBlockEx> m_IncompleteMessages; std::unordered_map<uint32_t, TunnelMessageBlockEx> m_IncompleteMessages;
std::unordered_map<uint64_t, std::unique_ptr<Fragment> > m_OutOfSequenceFragments; // ((msgID << 8) + fragment#)->fragment std::unordered_map<uint64_t, Fragment> m_OutOfSequenceFragments; // ((msgID << 8) + fragment#)->fragment
bool m_IsInbound; bool m_IsInbound;
size_t m_NumReceivedBytes; size_t m_NumReceivedBytes;
TunnelMessageBlockEx m_CurrentMessage; TunnelMessageBlockEx m_CurrentMessage;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2024, The PurpleI2P Project * Copyright (c) 2013-2025, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -351,10 +351,13 @@ namespace tunnel
{ {
it.second.first->SetState (eTunnelStateFailed); it.second.first->SetState (eTunnelStateFailed);
std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex); std::unique_lock<std::mutex> l(m_OutboundTunnelsMutex);
if (m_OutboundTunnels.size () > 1 || m_NumOutboundTunnels <= 1) // don't fail last tunnel if (m_OutboundTunnels.size () > 1) // don't fail last tunnel
m_OutboundTunnels.erase (it.second.first); m_OutboundTunnels.erase (it.second.first);
else else
{
it.second.first->SetState (eTunnelStateTestFailed); it.second.first->SetState (eTunnelStateTestFailed);
CreateOutboundTunnel (); // create new tunnel immediately because last one failed
}
} }
else if (it.second.first->GetState () != eTunnelStateExpiring) else if (it.second.first->GetState () != eTunnelStateExpiring)
it.second.first->SetState (eTunnelStateTestFailed); it.second.first->SetState (eTunnelStateTestFailed);
@ -368,13 +371,16 @@ namespace tunnel
bool failed = false; bool failed = false;
{ {
std::unique_lock<std::mutex> l(m_InboundTunnelsMutex); std::unique_lock<std::mutex> l(m_InboundTunnelsMutex);
if (m_InboundTunnels.size () > 1 || m_NumInboundTunnels <= 1) // don't fail last tunnel if (m_InboundTunnels.size () > 1) // don't fail last tunnel
{ {
m_InboundTunnels.erase (it.second.second); m_InboundTunnels.erase (it.second.second);
failed = true; failed = true;
} }
else else
{
it.second.second->SetState (eTunnelStateTestFailed); it.second.second->SetState (eTunnelStateTestFailed);
CreateInboundTunnel (); // create new tunnel immediately because last one failed
}
} }
if (failed && m_LocalDestination) if (failed && m_LocalDestination)
m_LocalDestination->SetLeaseSetUpdated (true); m_LocalDestination->SetLeaseSetUpdated (true);
@ -560,7 +566,7 @@ namespace tunnel
i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false); i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint, false);
if (hop) if (hop)
{ {
if (!hop->GetProfile ()->IsBad ()) if (!hop->HasProfile () || !hop->GetProfile ()->IsBad ())
break; break;
} }
else if (tryClient) else if (tryClient)
@ -588,7 +594,7 @@ namespace tunnel
(inbound && i2p::transport::transports.GetNumPeers () > 25)) (inbound && i2p::transport::transports.GetNumPeers () > 25))
{ {
auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ()); auto r = i2p::transport::transports.GetRandomPeer (m_IsHighBandwidth && !i2p::context.IsLimitedConnectivity ());
if (r && r->IsECIES () && !r->GetProfile ()->IsBad () && if (r && r->IsECIES () && (!r->HasProfile () || !r->GetProfile ()->IsBad ()) &&
(numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4 (numHops > 1 || (r->IsV4 () && (!inbound || r->IsPublished (true))))) // first inbound must be published ipv4
{ {
prevHop = r; prevHop = r;

Some files were not shown because too many files have changed in this diff Show more