Compare commits

..

172 Commits

Author SHA1 Message Date
orignal
3b97feb89f 2.50.2 2024-01-06 15:07:51 -05:00
orignal
a8135b8d18 2.50.2 2024-01-06 14:51:42 -05:00
orignal
5cf1961fa4 drop updated routers from future 2024-01-06 11:31:01 -05:00
orignal
c5cab05a6b reset peding time offset if correct time was received 2024-01-02 19:42:49 -05:00
orignal
b855c71891 don't adjust clock if time offsets are too different 2023-12-31 14:39:59 -05:00
orignal
21f41a2b2a correct time offset direction 2023-12-31 10:14:24 -05:00
orignal
8319dd6b25 drop exploratory and leaseset lookups for non-floodfill router 2023-12-30 19:49:16 -05:00
orignal
d4c47d90cb adjust time offset after second time discrepancy 2023-12-30 17:16:28 -05:00
orignal
302af823a3 fixed race condition with openssl 3.2.0 2023-12-30 15:55:53 -05:00
r4sas
69ee6112b3 [changelog] fix version
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-23 19:53:39 +00:00
r4sas
816a58f292 2.50.1
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-23 18:13:31 +00:00
orignal
43e130ee34 reinitialize context before each Sign/Verify call to make it working with openssl 3.2 2023-12-19 19:29:08 -05:00
orignal
8ffc1486a4 test-eddsa added 2023-12-18 09:32:12 -05:00
orignal
0e98dd5c70 use fallback EdDSA implementation with openssl 3.2.0 due to regression in EVP_DigestSign (#23075) 2023-12-18 07:40:40 -05:00
r4sas
beffdb9fe1 [apparmor] add profile for docker container
Author: corona@mail.i2p

Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-18 10:06:49 +00:00
r4sas
05eda2bc9e [gha] build docker containers only on specific paths changes
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-18 09:55:10 +00:00
r4sas
c3429bb1a9 [gha] return freebsd build back
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-18 09:38:08 +00:00
r4sas
53c6b10177 [make] get the mistakenly deleted pthread back
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-17 19:41:28 +00:00
r4sas
c2d7133174 [make] fix windows msys2 build
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-12-17 19:30:55 +00:00
orignal
9b82265cd8 2.50.0 2023-12-17 11:07:10 -05:00
orignal
c802c2deb0 update yggdrasil ressed address 2023-12-05 15:48:26 -05:00
orignal
c215f2e8d1 check router for null pointer 2023-11-23 13:06:50 -05:00
orignal
d327533b56 close unclaimed acceptors after 3 seconds 2023-11-17 18:50:52 -05:00
orignal
94255ebaf4 STREAM ACCEPT queue 2023-11-17 13:44:30 -05:00
orignal
21259204b1 eliminate send buffer mutex completely 2023-11-14 09:39:36 -05:00
orignal
8d6eb5b6b2 don't lock mutex in AsyncSend 2023-11-13 19:12:07 -05:00
orignal
9632e7ba03 exclude NAT64 ipv6 addresses 2023-11-12 18:32:57 -05:00
Dimitris Apostolou
1a02819187 Remove deprecated bind_at_load from macOS 2023-11-12 10:30:30 +00:00
Fabrice Fontaine
6b33250c59 build/CMakeLists.txt: enable C language
Detection of libatomic is broken since version 2.47.0 and
b7f0d87daf
because C language is not enabled anymore:

-- Looking for __atomic_fetch_add_4 in atomic
-- Looking for __atomic_fetch_add_4 in atomic - not found
CMake Error at cmake_modules/CheckAtomic.cmake:59 (message):
  Host compiler appears to require libatomic, but cannot find it.
Call Stack (most recent call first):
  CMakeLists.txt:54 (include)

Indeed if C language is not enabled, the test will be run with the C++
compiler resulting in the following error:

Building CXX object CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o
        /home/fabrice/buildroot/output/host/bin/x86_64-linux-g++ --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot   -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4  -DNDEBUG -o CMakeFiles/cmTC_03d01.dir/CheckFunctionExists.cxx.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-NApnv9/CheckFunctionExists.cxx
        <command-line>: error: new declaration ‘char __atomic_fetch_add_4()’ ambiguates built-in declaration ‘unsigned int __atomic_fetch_add_4(volatile void*, unsigned int, int)’ [-fpermissive]

whereas with a C compiler, we'll get:

Building C object CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o
        /home/fabrice/buildroot/output/host/bin/x86_64-linux-gcc --sysroot=/home/fabrice/buildroot/output/host/x86_64-buildroot-linux-gnu/sysroot   -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -O1 -g0 -D_FORTIFY_SOURCE=2 -DCHECK_FUNCTION_EXISTS=__atomic_fetch_add_4  -DNDEBUG -o CMakeFiles/cmTC_7e47b.dir/CheckFunctionExists.c.o -c /home/fabrice/buildroot/output/build/i2pd-2.49.0/build/CMakeFiles/CMakeScratch/TryCompile-e0zFMG/CheckFunctionExists.c
        <command-line>: warning: conflicting types for built-in function ‘__atomic_fetch_add_4’; expected ‘unsigned int(volatile void *, unsigned int,  int)’ [-Wbuiltin-declaration-mismatch]

Fix #1908

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2023-11-12 10:29:24 +00:00
orignal
083034fa35 send peer tests with random delays 2023-11-09 21:56:32 -05:00
R4SAS
0021501d75 [gha] disable FreeBSD build
Additional info: https://github.com/vmactions/freebsd-vm/issues/74
2023-10-31 22:39:51 +03:00
R4SAS
379be2a29e [gha] Update FreeBSD build action 2023-10-31 22:33:12 +03:00
orignal
a3f62e1d71 check actual distance with router to reduce expiration time 2023-10-31 13:20:04 -04:00
orignal
a6ee1e648e recognize trailing padding as part of base64 address 2023-10-31 09:10:56 -04:00
orignal
575268d360 reduce expiration time for low bandwidth and far routers 2023-10-30 20:02:48 -04:00
orignal
69b0bef206 fixed possible invalid pointer when send error response 2023-10-30 10:09:47 -04:00
orignal
e1b4feb618 correct base64 check 2023-10-30 08:10:17 -04:00
orignal
3286bdb4a7 verify jump link for valid characters 2023-10-29 22:11:38 -04:00
orignal
c8ae15041f Merge pull request #1980 from freeacetone/openssl
Yggdrasil reseed address replaced by address for 4.X+ version
2023-10-29 07:44:51 -04:00
acetone
e090b9052a Yggdrasil reseed address replaced by address for 4.X+ version 2023-10-29 11:57:14 +03:00
Dex
0ef9c08326 fix manpage typo for ipv4 flag 2023-10-28 16:25:51 +00:00
orignal
d04b19d77c don't recalculate badwidth if clock was adjusted too much 2023-10-18 18:09:41 -04:00
orignal
04adc14b76 ls@mail.i2p yggdrasil reseed added 2023-10-16 18:46:59 -04:00
orignal
0dee0609ea Merge pull request #1972 from Vort/nominmax
Fix MSVC compilation for std::max
2023-10-15 11:31:56 -04:00
Vort
0a519d8072 Fix MSVC compilation for std::max 2023-10-15 18:08:15 +03:00
orignal
0cc91dd2d2 don't pick too active peer 2023-10-15 08:31:55 -04:00
orignal
606e35eec1 reseed.us.prestium.org reseed added 2023-10-10 12:59:40 -04:00
orignal
e926b0392f reseed.is.prestium.org reseed added 2023-10-07 14:22:53 -04:00
orignal
9980bfa0e7 Update README.md 2023-09-30 14:10:45 -04:00
orignal
efdbe26755 try peer test again if Unknown 2023-09-28 18:40:51 -04:00
orignal
bb3ae8f5e4 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2023-09-28 16:06:33 -04:00
orignal
1e6edf06a2 send already accepting error response 2023-09-28 16:05:13 -04:00
hfsfox
0cf656cd76 Add Haiku OS support (#1970) 2023-09-28 22:30:38 +03:00
r4sas
fb420bb563 [cpu] more builtin version check changes
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-18 18:12:26 +00:00
r4sas
3da5061426 [cpu] Increase GCC version for use of builtin CPU extensions checker
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-18 17:11:45 +00:00
orignal
dd32f1ed6d Merge pull request #1968 from PurpleI2P/cpu
[cpu] use short defines instead of long checks
2023-09-17 14:38:16 -04:00
r4sas
1857f14be8 [cpu] use short defines instead of long checks
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-17 18:33:42 +00:00
r4sas
9c25a88707 [i18n] update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-17 16:21:36 +00:00
r4sas
c599d65307 [i18n] update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-17 15:59:11 +00:00
r4sas
4d573f6655 2.49.0
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-17 15:38:13 +00:00
orignal
3a4238729a 2.49.0 2023-09-17 10:41:31 -04:00
orignal
df6bb6d9b8 2.49.0 2023-09-17 10:19:57 -04:00
orignal
918aa556ef fixed non-x86 build 2023-09-15 11:37:45 -04:00
r4sas
1e7feae0df [rpm] remove BuildRequires tabulation
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-10 13:08:00 +03:00
r4sas
70829ee79e [rpm] add Fedora ELN support
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-10 13:02:52 +03:00
r4sas
4ed19c05f6 [cpu] split AES detect for GNU C < 5
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-07 21:20:52 +00:00
r4sas
4a5e16b994 [cpu] tests with preprocessor
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-07 16:56:53 +00:00
r4sas
c53ad2012c [cpu] use cpuid on gcc < 5
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-09-06 23:30:16 +03:00
R4SAS
7b6aa41ca8 CPU: remove AVX code, switch to __builtin for AES detection (#1959)
* [cpu] remove avx detect and code blocks, try to switch to __builtin
* [cpu] use __builtin_* only on x86 systems
* [cpu] perform check in separate function
* [cpu] set AES definition on MSVC
* update x86 and aes support checks at compile time
* [cmake] update comment about AES on MSVC
2023-08-31 19:52:51 +03:00
జిందం వాఐి
32c5ff23a6 Differentiate cryptocurrency & its associated address (#1951) 2023-08-31 19:51:21 +03:00
orignal
c112276eea memory poll for RouterProfile 2023-08-26 10:57:05 -04:00
Chad Fraleigh
662a59d0fd Eliminate additional undefined behavior of bit shifting signed int. 2023-08-16 19:49:18 +00:00
orignal
72919ec076 Merge pull request #1960 from chadf/chacha20-buf-outlen
Fixed buf offset EVP_EncryptFinal_ex() to include outlen.
2023-08-15 17:56:45 -04:00
Chad Fraleigh
627b8dca83 Fixed buf offset EVP_EncryptFinal_ex() to include outlen. 2023-08-13 17:08:14 -07:00
orignal
7bcc905f05 exclude SSU1 introducers 2023-08-07 21:28:13 -04:00
orignal
8447822c35 don't publish intrducers with zero tag 2023-08-05 15:25:16 -04:00
orignal
411063e3b5 Merge pull request #1958 from Vort/session_log
improve transport session logging
2023-08-05 13:55:03 -04:00
Vort
9bac680f2a improve transport session logging 2023-08-05 18:25:01 +03:00
orignal
38795a41cb don't publish introducers with zero iTag 2023-08-05 08:55:06 -04:00
orignal
e170c39dfc Merge pull request #1957 from Vort/peer_test
Separate test status from network status
2023-08-04 08:21:54 -04:00
Vort
68f4961f1a separate test status from network status 2023-07-30 15:44:16 +03:00
orignal
ae5239de43 remove introducer from RouterInfo after 60 minutes 2023-07-23 07:42:36 -04:00
orignal
2064504cce fixed send keepalive for existing session 2023-07-23 07:17:10 -04:00
orignal
4aa631c33f clear implied list if no more introducers found 2023-07-22 16:51:19 -04:00
orignal
d6834d6a9a keep non-published, but not-expired introducers in the introducers list 2023-07-22 15:03:03 -04:00
orignal
413e25f20e don't pick too old session for introducer 2023-07-22 10:13:05 -04:00
orignal
b8e19bf5f1 reduced peer test interval and added peer test interval variance 2023-07-22 08:50:49 -04:00
orignal
c7efd465fa padding for path response 2023-07-21 18:25:28 -04:00
orignal
6e9a3422e9 correct min size for keepalive 2023-07-21 07:59:09 -04:00
orignal
d3cd8517b7 Merge pull request #1952 from Vort/explicit0hops
allow 0 hops with explicitPeers
2023-07-19 10:43:03 -04:00
Vort
f13cc0b862 allow 0 hops with explicitPeers 2023-07-19 16:43:40 +03:00
orignal
0754255c1f drop incoming session from too old or from future routers 2023-07-17 21:08:26 -04:00
orignal
902899ae24 don't pick completely unreachable peers 2023-07-17 19:49:42 -04:00
orignal
c620fc1232 clear unreachable flag upon succesive connect 2023-07-17 18:44:51 -04:00
orignal
e7157cf15e don't create paired inbound tunnel if length is different 2023-07-17 17:57:30 -04:00
r4sas
940a97db11 [gha] fix msvc build
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-07-16 14:02:53 +03:00
orignal
8e63f8f333 consider all addresses non published for U and H routers 2023-07-15 17:11:56 -04:00
orignal
5e97b54d1b Merge pull request #1950 from Vort/term_fix
fix termination block processing and size check
2023-07-15 13:53:17 -04:00
Vort
ea7cf1cf69 fix termination block processing and size check 2023-07-15 18:44:37 +03:00
orignal
17c4038c60 select router with ipv4 for endpoint 2023-07-11 13:16:35 -04:00
orignal
5022a9c610 Merge pull request #1948 from chadf/fuzzing-5
Use offset from Identity::signingKey instead of Identity::certificate for key.
2023-07-10 08:06:47 -04:00
orignal
ca8ec6286a Merge pull request #1947 from chadf/fuzzing-4
Eliminate undefined behavior of bit shifting signed int.
2023-07-10 08:03:10 -04:00
orignal
5142459e12 Merge pull request #1945 from chadf/fuzzing-2
Fixed division by zero due to thread race condition.
2023-07-10 08:01:46 -04:00
orignal
8590dbd3d3 Merge pull request #1946 from chadf/fuzzing-3
Fixed crash when Base64ToByteStream() is only given '=' characters.
2023-07-10 08:00:30 -04:00
Chad Fraleigh
c4be5f7fdb Use offset from Identity::signingKey instead of Identity::certificate for key. 2023-07-09 18:45:30 -07:00
Chad Fraleigh
47dc5591b9 Eliminate undefined behavior of bit shifting signed int. 2023-07-09 15:09:17 -07:00
Chad Fraleigh
2bb48b4546 Fixed crash when Base64ToByteStream() is only given '=' characters. 2023-07-09 13:12:22 -07:00
Chad Fraleigh
638e9b4d7f Fixed division by zero due to thread race condition. 2023-07-08 17:07:04 -07:00
orignal
b8f998f76a don't delete BOBDestination if used by another BOBSession 2023-07-06 13:08:39 -04:00
orignal
5f43026986 check if local destination is not null 2023-07-06 12:30:33 -04:00
orignal
13f263b791 correct transport comptibility for OBEP in second attempt 2023-06-30 11:54:55 -04:00
orignal
07c529173e send current version of the subnegotiation in user/password response 2023-06-17 10:08:04 -04:00
orignal
fee940238a handle SOCK5 authrosation with empty user/password 2023-06-17 07:52:06 -04:00
R4SAS
ca02b5d860 debian: add compat patches for previous releases
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2023-06-12 14:45:34 +00:00
r4sas
fba23a4528 i18n: update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-12 16:33:21 +03:00
r4sas
a0795d8534 set server tunnel inport in ClientContext from port (#1936)
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-12 05:12:07 +03:00
r4sas
03cc6e0524 use uint16_t for ports
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-12 05:10:32 +03:00
r4sas
3af1f4bc76 Use of 'server' type tunnel port as inport (#1936)
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-12 00:32:44 +03:00
orignal
52b2d6c393 2.48.0 2023-06-11 15:44:16 -04:00
orignal
bb52056aec correct index for connected transport 2023-06-11 06:48:47 -04:00
r4sas
75aa9f2c0c i18n: update translation file
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-10 04:30:48 +03:00
r4sas
4e426727e9 Webconsole: fix output on i2p tunnels, add b32 on dest page
Fixes:
* adding of "Client Destinations" section header when there is no such tunnels
* Print error when destination is not found instead of empty page

Adds:
* Print b32 on destination page

Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-10 04:12:38 +03:00
r4sas
09f233dbfb NetDB: ignore LeaseSet store request if not floodfill
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-06-06 01:00:07 +03:00
r4sas
dfe5df29e1 suppress build warnings on windows
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-30 21:05:15 +03:00
AsciiMoth
d5ee1f602f Update dates in license (#1934)
Update copyright timestamp in LICENSE file from 2020 to actual 2023
2023-05-30 17:27:40 +03:00
orignal
86173400d5 don't drop profile of real router too early 2023-05-29 08:49:45 -04:00
r4sas
ae439b5385 SSU2: check if socket is opened before sending data, handle network_reset error
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-27 01:00:19 +03:00
r4sas
dc6a42c26f [contrib] update example config file comments, remove ssu option
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-23 00:44:48 +03:00
r4sas
fdf38f45d9 more debug messages at destinations stop
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-23 00:44:47 +03:00
r4sas
a2726cf206 [cmake] print commit-based version if option is used
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-23 00:44:46 +03:00
r4sas
e56d243c3f [win32] suppress fallthrough warning
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-05-23 00:44:42 +03:00
orignal
e95fb3ab89 allow user/password authentication 2023-05-22 08:58:04 -04:00
orignal
c984f89dfb don't handle unecnrypted DatabaseSearchReply msg if came throug client tunnel 2023-05-21 18:43:58 -04:00
orignal
5a09c11e90 Merge pull request #1927 from wekoq/refactor_TBM_handling
refactor TBM hadling
2023-05-08 12:48:45 -04:00
weko
d44be2fd73 fix typo 2023-05-08 15:33:40 +00:00
weko
a158647153 refactor TBM hadling 2023-05-08 14:52:48 +00:00
orignal
623c3f4605 check for max number of records in tunnel build and tunnel build reply messages 2023-05-06 18:07:21 -04:00
orignal
8a52295882 make router real upon successive outgoing NTCP2 session. Eliminate static keys table 2023-05-06 16:43:09 -04:00
orignal
f2bc2598dc Merge pull request #1925 from wekoq/openssl
Do not save useless peer profiles
2023-05-06 06:34:59 -04:00
weko
1d8a91c5cc redo no save useless profiles 2023-05-06 08:04:27 +00:00
orignal
3bc56ba423 store 'connected' in 'usage' section 2023-05-06 08:04:27 +00:00
orignal
e068a3cf22 store 'connected' in 'usage' section 2023-05-05 19:58:58 -04:00
weko
2e2cbe7803 save profile if has connected 2023-05-05 22:46:48 +00:00
weko
1c1452e06b Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2023-05-05 22:42:46 +00:00
orignal
c757b6d020 reset floodfill cap for unknown floodfills 2023-05-05 18:22:11 -04:00
weko
8fcab7b0c1 fix incorrect merge conflict resolve 2023-05-05 21:55:31 +00:00
weko
7646147ed2 save only non-default peer profile 2023-05-05 21:44:54 +00:00
orignal
b6de474fda don't include unconfirmed floodfill to the list if we have enough floodfills already 2023-05-05 16:14:54 -04:00
orignal
2f74e670a5 invalidate routers with incorrect family signature 2023-05-04 15:32:19 -04:00
orignal
c1168c2aa0 don't catch RouterInfo at OBEP 2023-05-04 09:39:37 -04:00
orignal
1bd6390f78 check if s is x25519 public key 2023-05-04 08:20:38 -04:00
orignal
a9e9e14c42 Merge pull request #1921 from contextswap/openssl
limit aes-ni assembly to x86
2023-05-03 12:21:00 -04:00
orignal
19471dbb90 Merge pull request #1922 from SidorKozlov/zombie-config
Configurable minimum successful tunnels
2023-05-03 11:43:19 -04:00
SidorKozlov
3b13a3f2a1 Configurable minimum successful tunnels 2023-05-03 16:13:03 +02:00
orignal
4ce2ef1d83 make router unreachable if AEAD fails in SessionCreated 2023-05-03 07:43:28 -04:00
contextswap
12d0abda55 [
Signed-off-by: contextswap <ctxswp@proton.me>
2023-05-03 19:10:16 +09:00
contextswap
7418f11651 limit aesni inline asm to x86
Signed-off-by: contextswap <ctxswp@proton.me>
2023-05-03 19:04:16 +09:00
orignal
fb83ca42f4 Merge pull request #1919 from wekoq/openssl
Recognize invalid static key
2023-05-01 16:17:00 -04:00
weko
dab34e9051 get indent hash directly 2023-05-01 20:08:08 +00:00
weko
ec2297ed9d Recognize invalid static key 2023-05-01 19:28:32 +00:00
orignal
7c535159bc static keys table 2023-04-30 20:05:35 -04:00
orignal
2af4a2b58d override reply token only if non-zero 2023-04-28 08:01:02 -04:00
orignal
ead6a6dca3 correct parsing of caught RouterInfo at IBGW and OBEP 2023-04-27 21:37:30 -04:00
orignal
0ce15ffc91 check for incomplete HTTP header 2023-04-26 21:34:22 -04:00
orignal
76adac31c3 enrcrypt lookup if being sent through a tunnel 2023-04-24 19:25:26 -04:00
r4sas
edfcd23b01 [webconsole] added a button to prematurely release a leaseset
Signed-off-by: r4sas <r4sas@i2pmail.org>
2023-04-24 14:01:21 +03:00
orignal
f21e1c75d5 check tagset for null 2023-04-23 15:31:24 -04:00
orignal
786c27c8ec publish encrypted RouterInfo 2023-04-21 22:27:55 -04:00
orignal
c34df2090c don't reply to DatabaseStore messages extracted from transit 2023-04-21 21:31:14 -04:00
orignal
5769a41208 use unordered_map for LeaseSets 2023-04-21 14:54:54 -04:00
orignal
dc265367dc drop unexpected I2NP messages 2023-04-20 14:23:41 -04:00
orignal
c22fc75370 set router properties from incoming connections 2023-04-19 19:48:09 -04:00
120 changed files with 2588 additions and 1295 deletions

View File

@@ -34,3 +34,6 @@ trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2
[*.patch]
trim_trailing_whitespace = false

View File

@@ -4,7 +4,7 @@ on: [push, pull_request]
jobs:
build:
runs-on: macos-12
runs-on: ubuntu-latest
name: with UPnP
steps:
@@ -13,7 +13,7 @@ jobs:
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.3.0
uses: vmactions/freebsd-vm@v1
with:
usesh: true
mem: 2048

View File

@@ -29,7 +29,7 @@ jobs:
- name: Install Boost
uses: crazy-max/ghaction-chocolatey@v2
with:
args: install boost-msvc-14.3
args: install boost-msvc-14.3 --version=1.81.0
- name: Install OpenSSL
uses: crazy-max/ghaction-chocolatey@v2

View File

@@ -5,6 +5,16 @@ on:
branches:
- openssl
- docker
paths:
- .github/workflows/docker.yml
- contrib/docker/**
- contrib/certificates/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'

View File

@@ -1,6 +1,86 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.50.2] - 2024-01-06
###Fixed
- Crash with OpenSSL 3.2.0
- False positive clock skew detection
## [2.50.1] - 2023-12-23
###Fixed
- Support for new EdDSA usage behavior in OpenSSL 3.2.0
## [2.50.0] - 2023-12-18
### Added
- Support of concurrent ACCEPTs on SAM 3.1
- Haiku OS support
- Low bandwidth and far routers can expire before 1 hour
### Changed
- Don't pick too active peer for first hop
- Try peer test again if status is Unknown
- Send peer tests with random delay
- Reseeds list
### Fixed
- XSS vulnerability in addresshelper
- Publishing NAT64 ipv6 addresses
- Deadlock in AsyncSend callback
## [2.49.0] - 2023-09-18
### Added
- Handle SOCK5 authorization with empty user/password
- Drop incoming transport sessions from too old or from future routers
- Memory pool for router profiles
- Allow 0 hops in explicitPeers
### Changed
- Separate network and testing status
- Remove AVX code
- Improve NTCP2 transport session logging
- Select router with ipv4 for tunnel endpoint
- Consider all addresses non-published for U and H routers even if they have host/port
- Don't pick completely unreachable routers for tunnels
- Exclude SSU1 introducers from SSU2 addresses
- Don't create paired inbound tunnel if length is different
- Remove introducer from RouterInfo after 60 minutes
- Reduce SSU2 keep alive interval and add keep alive interval variance
- Don't pick too old sessions for introducer
### Fixed
- Version of the subnegotiation in user/password SOCKS5 response
- Send keepalive for existing session with introducer
- Buffer offset for EVP_EncryptFinal_ex() to include outlen
- Termination block size processing for transport sessions
- Crash if deleted BOB destination was shared between few BOB sessions
- Introducers with zero tag
- Padding for SSU2 path response
## [2.48.0] - 2023-06-12
### Added
- Allow user/password authentication method for SOCK5 proxy
- Publish reject all congestion cap 'G' if transit is not accepted
- 'critical' log level
- Print b32 on webconsole destination page
- Webconsole button to drop a remote LeaseSet
- limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup
- Recognize real routers if successfully connected or responded to tunnel build request
### Changed
- Bypass slow transport sessions for first hop selection
- Limit AESNI inline asm to x86/x64
- Create smaller I2NP packets if possible
- Make router unreachable if AEAD tag verification fails in SessionCreated
- Don't include a router to floodfills list until it's confirmed as real
- Drop LeaseSet store request if not floodfill
- Bypass medium congestion('D') routers for client tunnels
- Publish encrypted RouterInfo through tunnels
- Check if s is valid x25519 public key
- Check if socket is open before sending data in SSU2
### Fixed
- Webconsole empty page if destination is not found
- i2p.streaming.answerPings param
- Reload tunnels
- Address caps for unspecified ipv6 address
- Incomplete HTTP headers in I2P tunnels
- SSU2 socket network exceptions on Windows
- Use of 'server' type tunnel port as inport (#1936)
## [2.47.0] - 2023-03-11
### Added
- Congestion caps

View File

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

View File

@@ -67,6 +67,9 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.bsd
else ifneq (, $(findstring haiku, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.haiku
else # not supported
$(error Not supported platform)
endif
@@ -118,7 +121,7 @@ obj/%.o: %.cpp | mk_obj_dir
-include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS)
$(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS)
ifneq ($(USE_STATIC),yes)

10
Makefile.haiku Normal file
View File

@@ -0,0 +1,10 @@
CXX = g++
CXXFLAGS := -Wall -std=c++11
INCFLAGS = -I/system/develop/headers
DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE
LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP
LDLIBS += -lminiupnpc
endif

View File

@@ -5,14 +5,11 @@ WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static
LDFLAGS := ${LD_DEBUG} -static -fPIC -msse
NEEDED_CXXFLAGS += -std=c++17
DEFINES += -DWIN32_LEAN_AND_MEAN
# Boost libraries suffix
BOOST_SUFFIX = -mt
# UPNP Support
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB
@@ -20,17 +17,18 @@ ifeq ($(USE_UPNP),yes)
endif
LDLIBS += \
-lboost_system$(BOOST_SUFFIX) \
-lboost_date_time$(BOOST_SUFFIX) \
-lboost_filesystem$(BOOST_SUFFIX) \
-lboost_program_options$(BOOST_SUFFIX) \
-lssl \
-lcrypto \
-lz \
$(MINGW_PREFIX)/lib/libboost_system-mt.a \
$(MINGW_PREFIX)/lib/libboost_date_time-mt.a \
$(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \
$(MINGW_PREFIX)/lib/libboost_program_options-mt.a \
$(MINGW_PREFIX)/lib/libssl.a \
$(MINGW_PREFIX)/lib/libcrypto.a \
$(MINGW_PREFIX)/lib/libz.a \
-lwsock32 \
-lws2_32 \
-lgdi32 \
-liphlpapi \
-lcrypt32 \
-lgdi32 \
-lole32 \
-luuid \
-lpthread
@@ -48,6 +46,7 @@ endif
ifeq ($(USE_AESNI),yes)
NEEDED_CXXFLAGS += -maes
LDFLAGS += -maes
DEFINES += -D__AES__
endif

View File

@@ -5,7 +5,6 @@ DEFINES := -DMAC_OSX
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDFLAGS += -Wl,-dead_strip
LDFLAGS += -Wl,-dead_strip_dylibs
LDFLAGS += -Wl,-bind_at_load
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_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread

View File

@@ -99,13 +99,23 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http
Donations
---------
BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f
LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59
ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG
XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH
**E-Mail**: ```i2porignal at yandex.com```
**BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f```
**LTC**: ```LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59```
**ETH**: ```0x9e5bac70d20d1079ceaa111127f4fb3bccce379d```
**GST**: ```GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG```
**DASH**: ```Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF```
**ZEC**: ```t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ```
**ANC**: ```AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z```
**XMR**: ```497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH```
License
-------

View File

@@ -145,18 +145,19 @@ namespace win32
s << bytes << " Bytes\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing)
{
switch (status)
{
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Test"; break;
case eRouterStatusFirewalled: s << "FW"; break;
case eRouterStatusUnknown: s << "Unk"; break;
case eRouterStatusProxy: s << "Proxy"; break;
case eRouterStatusMesh: s << "Mesh"; break;
default: s << "Unk";
};
if (testing)
s << " (Test)";
if (i2p::context.GetError () != eRouterErrorNone)
{
switch (i2p::context.GetError ())
@@ -179,11 +180,11 @@ namespace win32
{
s << "\n";
s << "Status: ";
ShowNetworkStatus (s, i2p::context.GetStatus ());
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting ());
if (i2p::context.SupportsV6 ())
{
s << " / ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6 ());
}
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
@@ -348,6 +349,9 @@ namespace win32
}
}
}
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
#endif
}
case WM_TRAYICON:
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -25,7 +25,7 @@ project(
i2pd
VERSION ${PROJECT_VERSION}
HOMEPAGE_URL "https://i2pd.website/"
LANGUAGES CXX
LANGUAGES C CXX
)
# configurable options
@@ -121,7 +121,7 @@ if(WIN32)
)
file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
endif()
@@ -139,6 +139,10 @@ if(APPLE)
add_definitions(-DMAC_OSX)
endif()
if(HAIKU)
add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE)
endif()
if(MSVC)
add_definitions(-DWINVER=0x0600)
add_definitions(-D_WIN32_WINNT=0x0600)
@@ -197,14 +201,11 @@ endif()
# Note: AES-NI and AVX is available on x86-based CPU's.
# Here also ARM64 implementation, but currently we don't support it.
# MSVC is not supported.
if(MSVC)
message(STATUS "AES-NI is not supported on MSVC, option was disabled")
set(WITH_AESNI OFF)
endif()
# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code.
if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
endif()
add_definitions(-D__AES__)
endif()
@@ -329,7 +330,11 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
message(STATUS " BINARY : ${WITH_BINARY}")
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
message(STATUS " UPnP : ${WITH_UPNP}")
if(WITH_GIT_VERSION)
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})")
else()
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
endif()
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------")

View File

@@ -0,0 +1,42 @@
# _________________________________________
# / Copy this file to the right location \
# | then load with: |
# | |
# | apparmor_parser -r -W |
# | /etc/apparmor.d/docker-i2pd |
# | |
# | docker run --security-opt |
# | "apparmor=docker-i2pd" ... |
# | purplei2p/i2pd |
# | |
# \ And "aa-status" to verify it's loaded. /
# -----------------------------------------
# \ ^__^
# \ (oo)\_______
# (__)\ )\/\
# ||----w |
# || ||
#include <tunables/global>
profile docker-i2pd flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/openssl>
#include <abstractions/nameservice>
/bin/busybox ix,
/usr/local/bin/i2pd ix,
/entrypoint.sh ixr,
/i2pd_certificates/** r,
/home/i2pd/data/** rw,
/home/i2pd/data/i2pd.pid k,
deny /home/i2pd/data/i2pd.conf w,
deny /home/i2pd/data/tunnels.conf w,
deny /home/i2pd/data/tunnels.d/** w,
deny /home/i2pd/data/certificates/** w,
deny /home/i2pd/data/i2pd.log r,
}

View File

@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFdTCCA12gAwIBAgIEQ5vCxzANBgkqhkiG9w0BAQ0FADBrMQswCQYDVQQGEwJY
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAw
HhcNMjMxMDE2MjAwNTA5WhcNMzMxMDEzMjAwNTA5WjBrMQswCQYDVQQGEwJYWDEL
MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnltb3Vz
IE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPcbKRtf4PzrDa0iRit0XrwnmA
2c1fJhkBipdPor7gMOAlkR82H1lkZSizR7kTZnr7vYqjDrOQr7bl5Dy3qo8/YCbZ
jsnUCTIIgIJQUxUlR40RjaSXphqzUEiXKHR6b0RahhFisQ3hlbbgzSch5YgSLKws
hOLi+eDSXw+HlwHlWFlT1XOKxSTJ/F3Bv40gxqZVC2pbxiPOeRZHQ6Ojw75lxTSF
gww2WzgztiWt4X9BO1yepnVqhAVRPmTfGUMfKzq9jkMzZKeQFV4uZSP9nCqzEpYd
WNDUfpTWiAQ9F+BwFXGusXXA3tGVwS7s6IEoiJFM5fsoJYfRoWGh3/1eirhBXW7U
M6oubMSTADyrvfjLfJBMmMnc2hNblRlKr0ZKUjMfv8cnyT4kQxlXLAHHXY2P89TM
TEVODkU48gnv6tC4t1JCb1/Da+3yVMjNX6rCzQfUwnLFrWthrwiI0NivAKFtiZjq
w1/ZQcYke2YyeqcfXMn+NTUA22Sm2mJoMo7jUf+rbM9Pi27/DncJgRGj5qwY0D3S
gc7829EjuZNPttGBmae1EmO7WQMB32cqdmItnV2FXpMhnn9h0u5H52kYqwn+mdtc
dTJRcbfKG1RTr3UjFISaTwL8qigMIkVXIzcpnr/R/sSeEs8xCqfsJ6rb4dCyFx+M
hqQcOCL5tumyd4W/LQIDAQABoyEwHzAdBgNVHQ4EFgQUgfaOG5HCnlW82wZ5BahL
GRO06igwDQYJKoZIhvcNAQENBQADggIBAKdVpqS9qF7gGotgXaVA1iP5YNsWlTvG
daGqeA/87//U21W6gpq82FhzsmsvUtXZfIeVIlDPI7WNDzS+A3K/KKrwM7dLgSie
r9eMl3D8WYPU95QF4mAlRyl7PCCsYoVjyvfro0iq3/iudIA5476rjfLdTXRi5hAT
qemPj0S+6sRjKEldRtGXrQATFlvLIWVYpgHijdDDx5M2hAz2y0mFxlDZTlA4BhL4
DwtGlVKmbc2x5MvIQM4UhbQqkxYS4gXnzf5Qx9QIytHfTr/hmbrkhKR1GCO31BSk
x9LhZxdI8LlwKSo6YgwXEB9E0M/tplaK9iZJFv4HPYLZrVJpb4IklMumyLMrgW5P
fR0dgKn+R9lk0emJ1Cu+qyyzf1vsLycYBwaEztINn4VK+/HfDFpnVCvJOyNuDmj5
KBLIoGdGoVfylmnc+e8zAXe+DY41fgniHMISOO78P8Bx9vTB+rhqnOUr9MzlUxPB
sKGjbXy2YynEqiGb+9g344v/+ukTSDenqTPHVzJ5uOi0iedy+3ASzUNN6GJocovP
167VOhwaETM0FwiKe0VdZRLLbbZ79CtJC0tmgcgPQPRa9Ldr6KN7u1J3D6lUp6zl
byPom10ueKONRb36t7ai79l2SEUZRSMkx6AXIU0JJ1SMtQtav7b5LkpYJfdL7+vO
dDx2/Za0VmdD
-----END CERTIFICATE-----

View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFyDCCA7CgAwIBAgIRAO8lBnTo+hlvglQwug2jHZkwDQYJKoZIhvcNAQELBQAw
cDELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGTAXBgNVBAMM
EG51bGxAaTJwbWFpbC5vcmcwHhcNMjMwOTIxMjIzMTM2WhcNMzMwOTIxMjIzMTM2
WjBwMQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYD
VQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UE
AwwQbnVsbEBpMnBtYWlsLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBAMMpAvaHwzuZZ6qelRU4jcgpuAIZFH++F1Te4b1t02pRfnQ0Eeh04VC1JxO0
XjUr1/iszEyvrI4+AdxaobDyRFPylkOLtfec4d2ciDc1cupj6y2vyYhMVN31rrvE
ve7sKoTHJ5Dx+UPGOVZZsSsmK9TXIU23W2bo7k2VnjVBXdWZyNE4twfTYCosDnYA
1HIEaIUFVv+COqw2pktxkMmfUAlnDLeVSfsAzEr37K+x0Xk5hO8m6GWQx0NRjjYp
gyEcFhWAJjAYaF3gUVR9rVVky1OeFhZgxE/KzVrW7uc84ZCMKITEPwT0qqIpsTJp
486YXzuPSc+ef78cKSQf5992l7imySJ24I/5H73HkovGAFGZdwvl6V6Ta5YqO7RR
gVDOL1EIVUnMCqFBCE6RmyZqXBVrv4Cacdc6lZ4fj42SRtWZfe6rNCpJzTRtbOyW
DBmYpK6q/jddfqI1sX0PXIn9U+Rod5Z4uz82PAjhamqyr5fpAnoQxKppBvQ3tNfn
KQhmP73Hdpvl24pRyQLBIRUL86i7TPBBn7n3XZlQfXP7lp8+KJYLkL2/zCVDrwLX
kC9hRIxCU9bZbXlkRE2R/PrK53LZecjk2KcgINA4ZlguNgze/Qj8BXelUF4izbpV
bTSvniTM46AECvjDcICAOky9Ku4RnmUJxQVf3ahDEuso7/N7AgMBAAGjXTBbMA4G
A1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
VR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQbnVsbEBpMnBtYWlsLm9yZzANBgkqhkiG
9w0BAQsFAAOCAgEAEUfYJTdDH7uCojnpF0Gs2tXxPJ22UhdqEsXfqR7KhhmmApss
q5kiiPIYoy5T/4IM7NVyeeJAMYwQsdJjwZ4QyxLBb9EqMS2krREcPZNRfFzBr2Wj
EBhJEYTnbIn4docwJWyXsJVG0CqFXPF1qGd0Sc2u87yj2xZNTnloWKAEQAO7DE39
gWfDH6slM/3h3WD3Mjuk7JoYSYmBfvvm2hkBbC6lzD7XY7rdSmIUwJ050e9UrJaV
La51dd5r4q8d1cHrVUwLiACAaXJ15AEqUDLHQcvKvyfhkabwRy+v0wsodSMgSMEH
xA+kGhkIW7yV7o2exYOYypHCca3IA+pimMpEseNNrHSwbHOMfauiN7jiZLEPg6D6
a8XwK7qmMYUq7j6QWuIqI81o29WZRf4LZ0GFoVce+e5VxkVKSItKcJoedIAp1ML8
NhFwd9s/nqWidu/StscEEbGzz6ZuDXwshERXC0QR8HjHEPi4U8220juf4cxUahxK
heEU91l7VksSZYRUN98h28vovGcukLcnVoLj5H/+Z4r/BgxMrOUJKetxf8fU7FjO
j1U6XV36tGi+IOwYQb9D5fTVafC3hHkuUIjlOdUGYadse98ILhn9kaNtqkBtk/EU
vK+McnrEv7tcKrbvYEop/KaUayhjFiL+wGWnpxt7gLhIiavnIeUyD7acltw=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF7zCCA9egAwIBAgIRANVB/+wEuXS0Ttoh5teJt90wDQYJKoZIhvcNAQELBQAw
fTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxJjAkBgNVBAMM
HXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMB4XDTIzMDkyMTE4MDAyOVoX
DTMzMDkyMTE4MDAyOVowfTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYD
VQQJEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQL
EwNJMlAxJjAkBgNVBAMMHXJlaGVhdGVkYnVyZ2VyQHByb3Rvbm1haWwuY29tMIIC
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuNwmiIY3MLSBS5sL5PXRDVK6
MoSNw4qx0o8nDHvVBxNtzgc0/qjYvsuUggY0tZbPpxhML6GHd4qo7Z3Ip1x0MxhI
Ao5MJaflaEdm4+HeMy0IE3aU73KRUwp+nF3cUHZdlps+9mtYs4oncVEWkFQwGsgt
4yrLtXf6PmPWfFH28ffeaev90e+hdhQpTvr54Ewx6NTaMQr8mkhXL2utvPpjnPM5
UAhOeJCMgfhLzgS4rahG0O8CQMtH5gKZ+6zjoSRatnjj0j1mBO7+e1TL5O7dVS9k
P83tmkIDDl4tXBzXr9aXQMJstbM2CEvinVcCsR74GjPcg4iB0Ift71Dx7oGKI06t
3bSvll0GZm2mFhIba/4q6f4oAJ2aeq6ejt1Kcm8g5cxtwrRZnXv5JXHZqba3y8J5
zWaRHzhc9tyEqRBRkc6c7xMdZQ31iJ6TlxUT8vAJ1N7OnX87oHrCjwyikpyOen4r
Uvv1Ge054XPTeoHz+Jyt34t71ty1W13uPHpuvtPVR9MfgGrxd4Z9+LWvAjmMbFsZ
lC3Ll+94nUk+O0puU6KisuCGP4hCtdEtebkIqT8zo8LicLAYUMjX7KwnS7681Cu1
sY2mB2oZAytN9Zy42oOoNeY5x39kxfwuut/2E1kxKX75O0bwfIXr611abCKc3bbz
euMrIsaB/2VFp9nAah8CAwEAAaNqMGgwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQW
MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCYGA1UdDgQf
BB1yZWhlYXRlZGJ1cmdlckBwcm90b25tYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOC
AgEATuHi2Yz52OK7e+sKVdHu2KrSLCGm98BG1UIMHFi3WRBTOFyp+lZ519bJ1rFj
tmP9E1a+k/vlbc7FbV4PcV6HJYfGEv/ImtJsEnrzbhrQphC1zMFv7q6JCTUbAzl6
ySlJ++mVxQ6AzPNH3TQgL1wPKuLh76/Y4053fg+NI3PmzzhkTUheVDkg0/a9ENSf
xMnCa3fIm869735qHk67QlikFvAfWwc4zT1Ncwodh8G4+oX0GFzIl+OZaM1GTMuD
UCcFKoqwtjyLCr22xNk8CfyiExPJXQG1HzEvDcxyoxQtnh9occR9PgqXySz26/NM
XDyM+l4utLMGBcVY4x9fksRiaWEfxiygYOxY9zDl6clh6S10b3CLut4UMiS1RTtE
Mjx2BZN3p0nxpT2leJdGxtBPGrvxuiCOEmTbOMLc3DQtppXO97B3dVMtJ5Ee8Y6p
Tq/8eiHI6eQXat6dgFT5X16vzF7w7XO7fAxuqk4Kx1D1aTVyikdo+Fcdg44dWOjq
NZu8VcCzZij/Dfjlce6t6h8D+wvDD8AkiivaDljpvbNDx/QQlQXFgH98TZA8Rnvr
QcyNNATfz+1yQUiyO6Lrjaw64OJwXYX/llgnDC+qQpP6kqZabi2TsG0EVPukVvr9
0HyAUu4lnXtTIDq2yPNenegCloqDL1ZQdaYd2XIItnfZdTY=
-----END CERTIFICATE-----

View File

@@ -1,2 +1,5 @@
This forder contain systemd unit files.
To use systemd daemon control, place files from this directory to debian folder before building package.
This forder contain files required for building debian packages.
The trunk repository is contains the packaging files for the latest stable version of Debian (if we not forgot to update them).
Files in subdirectories contains fixes to make possible to build package on specific versions of Debian/Ubuntu. They are used when building the release package.

View File

@@ -0,0 +1 @@
11

View File

@@ -0,0 +1,18 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 11~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 4.2.0
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

View File

@@ -0,0 +1 @@
9

View File

@@ -0,0 +1,18 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 3.9.8
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

View File

@@ -0,0 +1,17 @@
Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -31,7 +31,7 @@ include filelist.mk
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
-USE_UPNP := $(or $(USE_UPNP),no)
+USE_UPNP := $(or $(USE_UPNP),yes)
DEBUG := $(or $(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string

View File

@@ -0,0 +1,19 @@
Description: Disable LogsDirectory and LogsDirectoryMode options in service
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2023-05-17
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
@@ -8,8 +8,8 @@ User=i2pd
Group=i2pd
RuntimeDirectory=i2pd
RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/sh -c "kill -HUP $MAINPID"

View File

@@ -0,0 +1,2 @@
01-upnp.patch
02-service.patch

18
contrib/debian/trusty/rules Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
include /usr/share/dpkg/architecture.mk
ifeq ($(DEB_HOST_ARCH),i386)
export DEB_BUILD_OPTIONS=parallel=1
endif
export DEB_CXXFLAGS_MAINT_APPEND=-Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND=
%:
dh $@ --parallel
override_dh_auto_install:

View File

@@ -0,0 +1 @@
9

View File

@@ -0,0 +1,18 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 3.9.8
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

View File

@@ -0,0 +1,17 @@
Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -31,7 +31,7 @@ include filelist.mk
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
-USE_UPNP := $(or $(USE_UPNP),no)
+USE_UPNP := $(or $(USE_UPNP),yes)
DEBUG := $(or $(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string

View File

@@ -0,0 +1,19 @@
Description: Disable LogsDirectory and LogsDirectoryMode options in service
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2023-05-17
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
@@ -8,8 +8,8 @@ User=i2pd
Group=i2pd
RuntimeDirectory=i2pd
RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/sh -c "kill -HUP $MAINPID"

View File

@@ -0,0 +1,2 @@
01-upnp.patch
02-service.patch

13
contrib/debian/xenial/rules Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
include /usr/share/dpkg/architecture.mk
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND =
%:
dh $@ --parallel
override_dh_auto_install:

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: i2pd\n"
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
"POT-Creation-Date: 2023-01-19 04:18\n"
"POT-Creation-Date: 2023-06-10 01:25\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -18,28 +18,28 @@ msgstr ""
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
#: daemon/HTTPServer.cpp:106
#: daemon/HTTPServer.cpp:107
#, c-format
msgid "%d day"
msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:110
#: daemon/HTTPServer.cpp:111
#, c-format
msgid "%d hour"
msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:114
#: daemon/HTTPServer.cpp:115
#, c-format
msgid "%d minute"
msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:117
#: daemon/HTTPServer.cpp:118
#, c-format
msgid "%d second"
msgid_plural "%d seconds"
@@ -47,560 +47,578 @@ msgstr[0] ""
msgstr[1] ""
#. tr: Kibibyte
#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153
#: daemon/HTTPServer.cpp:126
#, c-format
msgid "%.2f KiB"
msgstr ""
#. tr: Mebibyte
#: daemon/HTTPServer.cpp:127
#: daemon/HTTPServer.cpp:128
#, c-format
msgid "%.2f MiB"
msgstr ""
#. tr: Gibibyte
#: daemon/HTTPServer.cpp:129
#: daemon/HTTPServer.cpp:130
#, c-format
msgid "%.2f GiB"
msgstr ""
#: daemon/HTTPServer.cpp:146
#: daemon/HTTPServer.cpp:147
msgid "building"
msgstr ""
#: daemon/HTTPServer.cpp:147
#: daemon/HTTPServer.cpp:148
msgid "failed"
msgstr ""
#: daemon/HTTPServer.cpp:148
#: daemon/HTTPServer.cpp:149
msgid "expiring"
msgstr ""
#: daemon/HTTPServer.cpp:149
#: daemon/HTTPServer.cpp:150
msgid "established"
msgstr ""
#: daemon/HTTPServer.cpp:150
#: daemon/HTTPServer.cpp:151
msgid "unknown"
msgstr ""
#: daemon/HTTPServer.cpp:152
#: daemon/HTTPServer.cpp:153
msgid "exploratory"
msgstr ""
#. tr: Webconsole page title
#: daemon/HTTPServer.cpp:183
#: daemon/HTTPServer.cpp:185
msgid "Purple I2P Webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:188
#: daemon/HTTPServer.cpp:190
msgid "<b>i2pd</b> webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:191
#: daemon/HTTPServer.cpp:193
msgid "Main page"
msgstr ""
#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742
msgid "Router commands"
msgstr ""
#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387
#: daemon/HTTPServer.cpp:399
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395
#: daemon/HTTPServer.cpp:407
msgid "Local Destinations"
msgstr ""
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:357
#: daemon/HTTPServer.cpp:443 daemon/HTTPServer.cpp:449
#: daemon/HTTPServer.cpp:609 daemon/HTTPServer.cpp:652
#: daemon/HTTPServer.cpp:656
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:365
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:474
#: daemon/HTTPServer.cpp:636 daemon/HTTPServer.cpp:682
#: daemon/HTTPServer.cpp:686
msgid "LeaseSets"
msgstr ""
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692
msgid "Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364
#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830
msgid "Transit Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898
msgid "Transports"
msgstr ""
#: daemon/HTTPServer.cpp:202
#: daemon/HTTPServer.cpp:204
msgid "I2P tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884
#: daemon/HTTPServer.cpp:894
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927
#: daemon/HTTPServer.cpp:937
msgid "SAM sessions"
msgstr ""
#: daemon/HTTPServer.cpp:220 daemon/HTTPServer.cpp:1278
#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1284
#: daemon/HTTPServer.cpp:1298 daemon/HTTPServer.cpp:1343
#: daemon/HTTPServer.cpp:1346 daemon/HTTPServer.cpp:1349
#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1329
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1335
#: daemon/HTTPServer.cpp:1362 daemon/HTTPServer.cpp:1365
#: daemon/HTTPServer.cpp:1379 daemon/HTTPServer.cpp:1424
#: daemon/HTTPServer.cpp:1427 daemon/HTTPServer.cpp:1430
msgid "ERROR"
msgstr ""
#: daemon/HTTPServer.cpp:227
#: daemon/HTTPServer.cpp:229
msgid "OK"
msgstr ""
#: daemon/HTTPServer.cpp:228
#: daemon/HTTPServer.cpp:230
msgid "Testing"
msgstr ""
#: daemon/HTTPServer.cpp:229
#: daemon/HTTPServer.cpp:231
msgid "Firewalled"
msgstr ""
#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233
#: daemon/HTTPServer.cpp:329
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235
#: daemon/HTTPServer.cpp:336
msgid "Unknown"
msgstr ""
#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374
#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952
#: daemon/HTTPServer.cpp:961
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382
#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003
#: daemon/HTTPServer.cpp:1011
msgid "Proxy"
msgstr ""
#: daemon/HTTPServer.cpp:232
#: daemon/HTTPServer.cpp:234
msgid "Mesh"
msgstr ""
#: daemon/HTTPServer.cpp:240
#: daemon/HTTPServer.cpp:242
msgid "Clock skew"
msgstr ""
#: daemon/HTTPServer.cpp:243
#: daemon/HTTPServer.cpp:245
msgid "Offline"
msgstr ""
#: daemon/HTTPServer.cpp:246
#: daemon/HTTPServer.cpp:248
msgid "Symmetric NAT"
msgstr ""
#: daemon/HTTPServer.cpp:249
#: daemon/HTTPServer.cpp:251
msgid "Full cone NAT"
msgstr ""
#: daemon/HTTPServer.cpp:252
#: daemon/HTTPServer.cpp:254
msgid "No Descriptors"
msgstr ""
#: daemon/HTTPServer.cpp:261
#: daemon/HTTPServer.cpp:263
msgid "Uptime"
msgstr ""
#: daemon/HTTPServer.cpp:264
#: daemon/HTTPServer.cpp:266
msgid "Network status"
msgstr ""
#: daemon/HTTPServer.cpp:269
#: daemon/HTTPServer.cpp:271
msgid "Network status v6"
msgstr ""
#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282
#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284
msgid "Stopping in"
msgstr ""
#: daemon/HTTPServer.cpp:289
#: daemon/HTTPServer.cpp:291
msgid "Family"
msgstr ""
#: daemon/HTTPServer.cpp:290
#: daemon/HTTPServer.cpp:292
msgid "Tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:291
#: daemon/HTTPServer.cpp:296
msgid "Total tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:298
msgid "Received"
msgstr ""
#. tr: Kibibyte/s
#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296
#: daemon/HTTPServer.cpp:299
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303
#: daemon/HTTPServer.cpp:306
#, c-format
msgid "%.2f KiB/s"
msgstr ""
#: daemon/HTTPServer.cpp:294
#: daemon/HTTPServer.cpp:301
msgid "Sent"
msgstr ""
#: daemon/HTTPServer.cpp:297
#: daemon/HTTPServer.cpp:304
msgid "Transit"
msgstr ""
#: daemon/HTTPServer.cpp:300
#: daemon/HTTPServer.cpp:307
msgid "Data path"
msgstr ""
#: daemon/HTTPServer.cpp:303
#: daemon/HTTPServer.cpp:310
msgid "Hidden content. Press on text to see."
msgstr ""
#: daemon/HTTPServer.cpp:307
#: daemon/HTTPServer.cpp:314
msgid "Router Ident"
msgstr ""
#: daemon/HTTPServer.cpp:309
#: daemon/HTTPServer.cpp:316
msgid "Router Family"
msgstr ""
#: daemon/HTTPServer.cpp:310
#: daemon/HTTPServer.cpp:317
msgid "Router Caps"
msgstr ""
#: daemon/HTTPServer.cpp:311
#: daemon/HTTPServer.cpp:318
msgid "Version"
msgstr ""
#: daemon/HTTPServer.cpp:312
#: daemon/HTTPServer.cpp:319
msgid "Our external address"
msgstr ""
#. tr: Shown when router doesn't publish itself and have "Firewalled" state
#: daemon/HTTPServer.cpp:341
#: daemon/HTTPServer.cpp:349
msgid "supported"
msgstr ""
#: daemon/HTTPServer.cpp:355
#: daemon/HTTPServer.cpp:363
msgid "Routers"
msgstr ""
#: daemon/HTTPServer.cpp:356
#: daemon/HTTPServer.cpp:364
msgid "Floodfills"
msgstr ""
#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987
msgid "Client Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:373
#: daemon/HTTPServer.cpp:381
msgid "Services"
msgstr ""
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
msgid "Enabled"
msgstr ""
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
msgid "Disabled"
msgstr ""
#: daemon/HTTPServer.cpp:422
#: daemon/HTTPServer.cpp:434
msgid "Encrypted B33 address"
msgstr ""
#: daemon/HTTPServer.cpp:431
#: daemon/HTTPServer.cpp:442
msgid "Address registration line"
msgstr ""
#: daemon/HTTPServer.cpp:436
#: daemon/HTTPServer.cpp:447
msgid "Domain"
msgstr ""
#: daemon/HTTPServer.cpp:437
#: daemon/HTTPServer.cpp:448
msgid "Generate"
msgstr ""
#: daemon/HTTPServer.cpp:438
#: daemon/HTTPServer.cpp:449
msgid ""
"<b>Note:</b> result string can be used only for registering 2LD domains "
"(example.i2p). For registering subdomains please use i2pd-tools."
msgstr ""
#: daemon/HTTPServer.cpp:444
#: daemon/HTTPServer.cpp:457
msgid "Address"
msgstr ""
#: daemon/HTTPServer.cpp:444
#: daemon/HTTPServer.cpp:459
msgid "Type"
msgstr ""
#: daemon/HTTPServer.cpp:444
#: daemon/HTTPServer.cpp:460
msgid "EncType"
msgstr ""
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667
#: daemon/HTTPServer.cpp:467
msgid "Expire LeaseSet"
msgstr ""
#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:697
msgid "Inbound tunnels"
msgstr ""
#. tr: Milliseconds
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489
#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701
#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514
#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731
#, c-format
msgid "%dms"
msgstr ""
#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716
msgid "Outbound tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:496
#: daemon/HTTPServer.cpp:521
msgid "Tags"
msgstr ""
#: daemon/HTTPServer.cpp:497
#: daemon/HTTPServer.cpp:522
msgid "Incoming"
msgstr ""
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535
msgid "Outgoing"
msgstr ""
#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551
msgid "Destination"
msgstr ""
#: daemon/HTTPServer.cpp:507
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814
msgid "Amount"
msgstr ""
#: daemon/HTTPServer.cpp:515
#: daemon/HTTPServer.cpp:540
msgid "Incoming Tags"
msgstr ""
#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529
#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554
msgid "Tags sessions"
msgstr ""
#: daemon/HTTPServer.cpp:526
#: daemon/HTTPServer.cpp:551
msgid "Status"
msgstr ""
#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594
#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621
msgid "Local Destination"
msgstr ""
#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917
#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960
msgid "Streams"
msgstr ""
#: daemon/HTTPServer.cpp:570
#: daemon/HTTPServer.cpp:595
msgid "Close stream"
msgstr ""
#: daemon/HTTPServer.cpp:599
#: daemon/HTTPServer.cpp:613 daemon/HTTPServer.cpp:1430
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:626
msgid "I2CP session not found"
msgstr ""
#: daemon/HTTPServer.cpp:602
#: daemon/HTTPServer.cpp:629
msgid "I2CP is not enabled"
msgstr ""
#: daemon/HTTPServer.cpp:628
#: daemon/HTTPServer.cpp:658
msgid "Invalid"
msgstr ""
#: daemon/HTTPServer.cpp:631
#: daemon/HTTPServer.cpp:661
msgid "Store type"
msgstr ""
#: daemon/HTTPServer.cpp:632
#: daemon/HTTPServer.cpp:662
msgid "Expires"
msgstr ""
#: daemon/HTTPServer.cpp:637
#: daemon/HTTPServer.cpp:667
msgid "Non Expired Leases"
msgstr ""
#: daemon/HTTPServer.cpp:640
#: daemon/HTTPServer.cpp:670
msgid "Gateway"
msgstr ""
#: daemon/HTTPServer.cpp:641
#: daemon/HTTPServer.cpp:671
msgid "TunnelID"
msgstr ""
#: daemon/HTTPServer.cpp:642
#: daemon/HTTPServer.cpp:672
msgid "EndDate"
msgstr ""
#: daemon/HTTPServer.cpp:652
#: daemon/HTTPServer.cpp:682
msgid "floodfill mode is disabled"
msgstr ""
#: daemon/HTTPServer.cpp:663
#: daemon/HTTPServer.cpp:693
msgid "Queue size"
msgstr ""
#: daemon/HTTPServer.cpp:713
#: daemon/HTTPServer.cpp:743
msgid "Run peer test"
msgstr ""
#: daemon/HTTPServer.cpp:714
#: daemon/HTTPServer.cpp:744
msgid "Reload tunnels configuration"
msgstr ""
#: daemon/HTTPServer.cpp:717
#: daemon/HTTPServer.cpp:747
msgid "Decline transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:719
#: daemon/HTTPServer.cpp:749
msgid "Accept transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728
#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758
msgid "Cancel graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730
#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760
msgid "Start graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:733
#: daemon/HTTPServer.cpp:763
msgid "Force shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:734
#: daemon/HTTPServer.cpp:764
msgid "Reload external CSS styles"
msgstr ""
#: daemon/HTTPServer.cpp:737
#: daemon/HTTPServer.cpp:767
msgid ""
"<b>Note:</b> any action done here are not persistent and not changes your "
"config files."
msgstr ""
#: daemon/HTTPServer.cpp:739
#: daemon/HTTPServer.cpp:770
msgid "Logging level"
msgstr ""
#: daemon/HTTPServer.cpp:747
#: daemon/HTTPServer.cpp:779
msgid "Transit tunnels limit"
msgstr ""
#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771
#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803
msgid "Change"
msgstr ""
#: daemon/HTTPServer.cpp:759
#: daemon/HTTPServer.cpp:791
msgid "Change language"
msgstr ""
#: daemon/HTTPServer.cpp:797
#: daemon/HTTPServer.cpp:830
msgid "no transit tunnels currently built"
msgstr ""
#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901
#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944
msgid "SAM disabled"
msgstr ""
#: daemon/HTTPServer.cpp:894
#: daemon/HTTPServer.cpp:937
msgid "no sessions currently running"
msgstr ""
#: daemon/HTTPServer.cpp:907
#: daemon/HTTPServer.cpp:950
msgid "SAM session not found"
msgstr ""
#: daemon/HTTPServer.cpp:912
#: daemon/HTTPServer.cpp:955
msgid "SAM Session"
msgstr ""
#: daemon/HTTPServer.cpp:969
#: daemon/HTTPServer.cpp:1020
msgid "Server Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:985
#: daemon/HTTPServer.cpp:1036
msgid "Client Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:999
#: daemon/HTTPServer.cpp:1050
msgid "Server Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1199
#: daemon/HTTPServer.cpp:1250
msgid "Unknown page"
msgstr ""
#: daemon/HTTPServer.cpp:1218
#: daemon/HTTPServer.cpp:1269
msgid "Invalid token"
msgstr ""
#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333
#: daemon/HTTPServer.cpp:1373
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359
#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454
msgid "SUCCESS"
msgstr ""
#: daemon/HTTPServer.cpp:1276
#: daemon/HTTPServer.cpp:1327
msgid "Stream closed"
msgstr ""
#: daemon/HTTPServer.cpp:1278
#: daemon/HTTPServer.cpp:1329
msgid "Stream not found or already was closed"
msgstr ""
#: daemon/HTTPServer.cpp:1281
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365
msgid "Destination not found"
msgstr ""
#: daemon/HTTPServer.cpp:1284
#: daemon/HTTPServer.cpp:1335
msgid "StreamID can't be null"
msgstr ""
#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351
#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1432
msgid "Return to destination page"
msgstr ""
#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300
#: daemon/HTTPServer.cpp:1375
#: daemon/HTTPServer.cpp:1338 daemon/HTTPServer.cpp:1368
#: daemon/HTTPServer.cpp:1381 daemon/HTTPServer.cpp:1456
#, c-format
msgid "You will be redirected in %d seconds"
msgstr ""
#: daemon/HTTPServer.cpp:1298
#: daemon/HTTPServer.cpp:1359
msgid "LeaseSet expiration time updated"
msgstr ""
#: daemon/HTTPServer.cpp:1362
msgid "LeaseSet is not found or already expired"
msgstr ""
#: daemon/HTTPServer.cpp:1379
#, c-format
msgid "Transit tunnels count must not exceed %d"
msgstr ""
#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374
#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455
msgid "Back to commands list"
msgstr ""
#: daemon/HTTPServer.cpp:1335
#: daemon/HTTPServer.cpp:1416
msgid "Register at reg.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1336
#: daemon/HTTPServer.cpp:1417
msgid "Description"
msgstr ""
#: daemon/HTTPServer.cpp:1336
#: daemon/HTTPServer.cpp:1417
msgid "A bit information about service on domain"
msgstr ""
#: daemon/HTTPServer.cpp:1337
#: daemon/HTTPServer.cpp:1418
msgid "Submit"
msgstr ""
#: daemon/HTTPServer.cpp:1343
#: daemon/HTTPServer.cpp:1424
msgid "Domain can't end with .b32.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1346
#: daemon/HTTPServer.cpp:1427
msgid "Domain must end with .i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1349
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:1369
#: daemon/HTTPServer.cpp:1450
msgid "Unknown command"
msgstr ""
#: daemon/HTTPServer.cpp:1373
#: daemon/HTTPServer.cpp:1454
msgid "Command accepted"
msgstr ""
@@ -624,20 +642,20 @@ msgstr ""
msgid "You may try to find this host on jump services below"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324
#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435
#: libi2pd_client/HTTPProxy.cpp:333 libi2pd_client/HTTPProxy.cpp:348
#: libi2pd_client/HTTPProxy.cpp:417 libi2pd_client/HTTPProxy.cpp:460
msgid "Invalid request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:309
#: libi2pd_client/HTTPProxy.cpp:333
msgid "Proxy unable to parse your request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:324
#: libi2pd_client/HTTPProxy.cpp:348
msgid "Addresshelper is not supported"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:349
#: libi2pd_client/HTTPProxy.cpp:373
#, c-format
msgid ""
"Host %s is <font color=red>already in router's addressbook</font>. <b>Be "
@@ -645,121 +663,121 @@ msgid ""
"<a href=\"%s%s%s&update=true\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:351
#: libi2pd_client/HTTPProxy.cpp:375
msgid "Addresshelper forced update rejected"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:358
#: libi2pd_client/HTTPProxy.cpp:382
#, c-format
msgid ""
"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s"
"\">Continue</a>."
"To add host <b>%s</b> in router's addressbook, click here: <a "
"href=\"%s%s%s\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:360
#: libi2pd_client/HTTPProxy.cpp:384
msgid "Addresshelper request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:369
#: libi2pd_client/HTTPProxy.cpp:393
#, c-format
msgid ""
"Host %s added to router's addressbook from helper. Click here to proceed: <a "
"href=\"%s\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:370
#: libi2pd_client/HTTPProxy.cpp:395
msgid "Addresshelper adding"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:377
#: libi2pd_client/HTTPProxy.cpp:402
#, c-format
msgid ""
"Host %s is <font color=red>already in router's addressbook</font>. Click "
"here to update record: <a href=\"%s%s%s&update=true\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:379
#: libi2pd_client/HTTPProxy.cpp:404
msgid "Addresshelper update"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:392
#: libi2pd_client/HTTPProxy.cpp:417
msgid "Invalid request URI"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:435
#: libi2pd_client/HTTPProxy.cpp:460
msgid "Can't detect destination host from request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456
#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481
msgid "Outproxy failure"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:452
#: libi2pd_client/HTTPProxy.cpp:477
msgid "Bad outproxy settings"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:455
#: libi2pd_client/HTTPProxy.cpp:480
#, c-format
msgid "Host %s is not inside I2P network, but outproxy is not enabled"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:544
#: libi2pd_client/HTTPProxy.cpp:569
msgid "Unknown outproxy URL"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:550
#: libi2pd_client/HTTPProxy.cpp:575
msgid "Cannot resolve upstream proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:558
#: libi2pd_client/HTTPProxy.cpp:583
msgid "Hostname is too long"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:585
#: libi2pd_client/HTTPProxy.cpp:610
msgid "Cannot connect to upstream SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:591
#: libi2pd_client/HTTPProxy.cpp:616
msgid "Cannot negotiate with SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:633
#: libi2pd_client/HTTPProxy.cpp:658
msgid "CONNECT error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:633
#: libi2pd_client/HTTPProxy.cpp:658
msgid "Failed to connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670
#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695
msgid "SOCKS proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:652
#: libi2pd_client/HTTPProxy.cpp:677
msgid "Failed to send request to upstream"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:673
#: libi2pd_client/HTTPProxy.cpp:698
msgid "No reply from SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:680
#: libi2pd_client/HTTPProxy.cpp:705
msgid "Cannot connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:680
#: libi2pd_client/HTTPProxy.cpp:705
msgid "HTTP out proxy not implemented"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:681
#: libi2pd_client/HTTPProxy.cpp:706
msgid "Cannot connect to upstream HTTP proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:714
#: libi2pd_client/HTTPProxy.cpp:739
msgid "Host is down"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:714
#: libi2pd_client/HTTPProxy.cpp:739
msgid ""
"Can't create connection to requested host, it may be down. Please try again "
"later."

View File

@@ -2,12 +2,17 @@
---
```
xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
```
Regex for transforming gettext translations to our format:
---
```
in: ^(\"|#[:.,]|msgctxt)(.*)$\n
out: <to empty line>
```
```
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n
@@ -18,10 +23,6 @@ in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
out: {"$1", "$2"},\n
```
```
in: ^#[:.,](.*)$\n
out: <to empty line>
```
```
in: \n\n

View File

@@ -19,7 +19,7 @@
## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates
# certsdir = /var/lib/i2pd/certificates
## Where to write pidfile (default: i2pd.pid, not used in Windows)
## Where to write pidfile (default: /run/i2pd.pid, not used in Windows)
# pidfile = /run/i2pd.pid
## Logging configuration section
@@ -31,7 +31,7 @@
## * file - log entries to a file
## * syslog - use syslog, see man 3 syslog
# log = file
## Path to logfile (default - autodetect)
## Path to logfile (default: autodetect)
# logfile = /var/log/i2pd/i2pd.log
## Log messages above this level (debug, info, *warn, error, critical, none)
## If you set it to none, logging will be disabled
@@ -40,6 +40,7 @@
# logclftime = true
## Daemon mode. Router will go to background after start. Ignored on Windows
## (default: true)
# daemon = true
## Specify a family, router belongs to (default - none)
@@ -70,58 +71,60 @@
## don't just uncomment this
# port = 4567
## Enable communication through ipv4
## Enable communication through ipv4 (default: true)
ipv4 = true
## Enable communication through ipv6
## Enable communication through ipv6 (default: false)
ipv6 = false
## Enable SSU transport
ssu = false
## Bandwidth configuration
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec,
## X - unlimited
## Default is L (regular node) and X if floodfill mode enabled. If you want to
## share more bandwidth without floodfill mode, uncomment that line and adjust
## value to your possibilities
## Default is L (regular node) and X if floodfill mode enabled.
## If you want to share more bandwidth without floodfill mode, uncomment
## that line and adjust value to your possibilities. Value can be set to
## integer in kilobytes, it will apply that limit and flag will be used
## from next upper limit (example: if you set 4096 flag will be X, but real
## limit will be 4096 KB/s). Same can be done when floodfill mode is used,
## but keep in mind that low values may be negatively evaluated by Java
## router algorithms.
# bandwidth = L
## Max % of bandwidth limit for transit. 0-100. 100 by default
## Max % of bandwidth limit for transit. 0-100 (default: 100)
# share = 100
## Router will not accept transit tunnels, disabling transit traffic completely
## (default = false)
## (default: false)
# notransit = true
## Router will be floodfill
## Router will be floodfill (default: false)
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[ntcp2]
## Enable NTCP2 transport (default = true)
## Enable NTCP2 transport (default: true)
# enabled = true
## Publish address in RouterInfo (default = true)
## Publish address in RouterInfo (default: true)
# published = true
## Port for incoming connections (default is global port option value)
# port = 4567
[ssu2]
## Enable SSU2 transport
## Enable SSU2 transport (default: true)
# enabled = true
## Publish address in RouterInfo
## Publish address in RouterInfo (default: true)
# published = true
## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled)
## Port for incoming connections (default is global port option value)
# port = 4567
[http]
## Web Console settings
## Uncomment and set to 'false' to disable Web Console
## Enable the Web Console (default: true)
# enabled = true
## Address and port service will listen on
address = 127.0.0.1
port = 7070
## Path to web console, default "/"
## Address and port service will listen on (default: 127.0.0.1:7070)
# address = 127.0.0.1
# port = 7070
## Path to web console (default: /)
# webroot = /
## Uncomment following lines to enable Web Console authentication
## Enable Web Console authentication (default: false)
## You should not use Web Console via public networks without additional encryption.
## HTTP authentication is not encryption layer!
# auth = true
@@ -134,12 +137,12 @@ port = 7070
# lang = english
[httpproxy]
## Uncomment and set to 'false' to disable HTTP Proxy
## Enable the HTTP proxy (default: true)
# enabled = true
## Address and port service will listen on
address = 127.0.0.1
port = 4444
## Optional keys file for proxy local destination
## Address and port service will listen on (default: 127.0.0.1:4444)
# address = 127.0.0.1
# port = 4444
## Optional keys file for proxy local destination (default: http-proxy-keys.dat)
# keys = http-proxy-keys.dat
## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
## You should disable this feature if your i2pd HTTP Proxy is public,
@@ -150,15 +153,15 @@ port = 4444
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
[socksproxy]
## Uncomment and set to 'false' to disable SOCKS Proxy
## Enable the SOCKS proxy (default: true)
# enabled = true
## Address and port service will listen on
address = 127.0.0.1
port = 4447
## Optional keys file for proxy local destination
## Address and port service will listen on (default: 127.0.0.1:4447)
# address = 127.0.0.1
# port = 4447
## Optional keys file for proxy local destination (default: socks-proxy-keys.dat)
# keys = socks-proxy-keys.dat
## Socks outproxy. Example below is set to use Tor for all connections except i2p
## Uncomment and set to 'true' to enable using of SOCKS outproxy
## Enable using of SOCKS outproxy (works only with SOCKS4, default: false)
# outproxy.enabled = false
## Address and port of outproxy
# outproxy = 127.0.0.1
@@ -166,34 +169,34 @@ port = 4447
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
[sam]
## Comment or set to 'false' to disable SAM Bridge
enabled = true
## Address and ports service will listen on
## Enable the SAM bridge (default: true)
# enabled = false
## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655)
# address = 127.0.0.1
# port = 7656
# portudp = 7655
[bob]
## Uncomment and set to 'true' to enable BOB command channel
## Enable the BOB command channel (default: false)
# enabled = false
## Address and port service will listen on
## Address and port service will listen on (default: 127.0.0.1:2827)
# address = 127.0.0.1
# port = 2827
[i2cp]
## Uncomment and set to 'true' to enable I2CP protocol
## Enable the I2CP protocol (default: false)
# enabled = false
## Address and port service will listen on
## Address and port service will listen on (default: 127.0.0.1:7654)
# address = 127.0.0.1
# port = 7654
[i2pcontrol]
## Uncomment and set to 'true' to enable I2PControl protocol
## Enable the I2PControl protocol (default: false)
# enabled = false
## Address and port service will listen on
## Address and port service will listen on (default: 127.0.0.1:7650)
# address = 127.0.0.1
# port = 7650
## Authentication password. "itoopie" by default
## Authentication password (default: itoopie)
# password = itoopie
[precomputation]
@@ -204,11 +207,11 @@ enabled = true
[upnp]
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
# enabled = false
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
## Name i2pd appears in UPnP forwardings list (default: I2Pd)
# name = I2Pd
[meshnets]
## Enable connectivity over the Yggdrasil network
## Enable connectivity over the Yggdrasil network (default: false)
# yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface
@@ -216,13 +219,13 @@ enabled = true
[reseed]
## Options for bootstrapping into I2P network, aka reseeding
## Enable or disable reseed data verification.
## Enable reseed data verification (default: true)
verify = true
## URLs to request reseed data from, separated by comma
## Default: "mainline" I2P Network reseeds
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
## Reseed URLs through the Yggdrasil, separated by comma
# yggurls = http://[324:9de3:fea4:f6ac::ace]:7070/
# yggurls = http://[324:71e:281a:9ed3::ace]:7070/
## Path to local reseed data file (.su3) for manual reseeding
# file = /path/to/i2pseeds.su3
## or HTTPS URL to reseed from
@@ -232,7 +235,7 @@ verify = true
## If you run i2pd behind a proxy server, set proxy server for reseeding here
## Should be http://address:port or socks://address:port
# proxy = http://127.0.0.1:8118
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
## Minimum number of known routers, below which i2pd triggers reseeding (default: 25)
# threshold = 25
[addressbook]
@@ -252,13 +255,13 @@ verify = true
# coresize = 0
[trust]
## Enable explicit trust options. false by default
## Enable explicit trust options. (default: false)
# enabled = true
## Make direct I2P connections only to routers in specified Family.
# family = MyFamily
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
# routers =
## Should we hide our router from other routers? false by default
## Should we hide our router from other routers? (default: false)
# hidden = true
[exploratory]
@@ -277,8 +280,6 @@ verify = true
[cpuext]
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)
# aesni = true
## Use CPU AVX instructions set when work with cryptography when available (default: true)
# avx = true
## Force usage of CPU instructions set, even if they not found
## Force usage of CPU instructions set, even if they not found (default: false)
## DO NOT TOUCH that option if you really don't know what are you doing!
# force = false

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.47.0
Version: 2.50.2
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@@ -28,9 +28,11 @@ Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
%prep
%setup -q -n i2pd-openssl
@@ -38,72 +40,56 @@ C++ implementation of I2P.
%build
cd build
%if 0%{?rhel} == 7
%cmake3 \
%cmake3 \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
-DBUILD_SHARED_LIBS:BOOL=OFF
%else
%cmake \
%cmake \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%endif
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?mageia} > 7
pushd build
%if 0%{?mageia} > 7
pushd build
%endif
%endif
make %{?_smp_mflags}
%if 0%{?rhel} == 9
popd
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
popd
%endif
%if 0%{?fedora} >= 33
popd
%endif
%if 0%{?mageia} > 7
popd
%endif
%install
pushd build
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?mageia}
pushd build
%if 0%{?mageia}
pushd build
%endif
%endif
chrpath -d i2pd
@@ -158,6 +144,21 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
- update to 2.50.1
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
- update to 2.50.0
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
- update to 2.49.0
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
- update to 2.48.0
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
- update to 2.47.0

View File

@@ -1,5 +1,5 @@
Name: i2pd
Version: 2.47.0
Version: 2.50.2
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -26,9 +26,11 @@ Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
%prep
%setup -q
@@ -36,71 +38,56 @@ C++ implementation of I2P.
%build
cd build
%if 0%{?rhel} == 7
%cmake3 \
%cmake3 \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
-DBUILD_SHARED_LIBS:BOOL=OFF
%else
%cmake \
%cmake \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%endif
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?mageia} > 7
pushd build
%if 0%{?mageia} > 7
pushd build
%endif
%endif
make %{?_smp_mflags}
%if 0%{?rhel} == 9
popd
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
popd
%endif
%if 0%{?fedora} >= 33
popd
%endif
%if 0%{?mageia} > 7
popd
%endif
%install
pushd build
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?mageia}
pushd build
%if 0%{?mageia}
pushd build
%endif
%endif
chrpath -d i2pd
@@ -155,6 +142,21 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
- update to 2.50.1
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
- update to 2.50.0
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
- update to 2.49.0
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
- update to 2.48.0
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
- update to 2.47.0

View File

@@ -150,12 +150,11 @@ namespace util
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool avx; i2p::config::GetOption("cpuext.avx", avx);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces

View File

@@ -87,6 +87,7 @@ namespace http {
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
const char HTTP_COMMAND_EXPIRELEASE[] = "expirelease";
static std::string ConvertTime (uint64_t time)
{
@@ -221,18 +222,19 @@ namespace http {
s << "<b>" << tr("ERROR") << ":</b>&nbsp;" << string << "<br>\r\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
{
switch (status)
{
case eRouterStatusOK: s << tr("OK"); break;
case eRouterStatusTesting: s << tr("Testing"); break;
case eRouterStatusFirewalled: s << tr("Firewalled"); break;
case eRouterStatusUnknown: s << tr("Unknown"); break;
case eRouterStatusProxy: s << tr("Proxy"); break;
case eRouterStatusMesh: s << tr("Mesh"); break;
default: s << tr("Unknown");
}
if (testing)
s << " (" << tr("Testing") << ")";
if (error != eRouterErrorNone)
{
switch (error)
@@ -263,12 +265,12 @@ namespace http {
ShowUptime(s, i2p::context.GetUptime ());
s << "<br>\r\n";
s << "<b>" << tr("Network status") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ());
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
s << "<br>\r\n";
if (i2p::context.SupportsV6 ())
{
s << "<b>" << tr("Network status v6") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
s << "<br>\r\n";
}
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
@@ -421,8 +423,12 @@ namespace http {
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
{
s << "<b>Base32:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"1\">";
s << dest->GetIdentHash ().ToBase32 () << "</textarea><br>\r\n<br>\r\n";
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"8\">";
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
if (dest->IsEncryptedLeaseSet ())
{
i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
@@ -434,12 +440,11 @@ namespace http {
if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ())
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
auto base32 = dest->GetIdentHash ().ToBase32 ();
s << "<div class='slide'><label for='slide-regaddr'><b>" << tr("Address registration line") << "</b></label>\r\n<input type=\"checkbox\" id=\"slide-regaddr\" />\r\n<div class=\"slidecontent\">\r\n"
"<form method=\"get\" action=\"" << webroot << "\">\r\n"
" <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_GET_REG_STRING << "\">\r\n"
" <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
" <input type=\"hidden\" name=\"b32\" value=\"" << base32 << "\">\r\n"
" <input type=\"hidden\" name=\"b32\" value=\"" << dest->GetIdentHash ().ToBase32 () << "\">\r\n"
" <b>" << tr("Domain") << ":</b>\r\n<input type=\"text\" maxlength=\"67\" name=\"name\" placeholder=\"domain.i2p\" required>\r\n"
" <button type=\"submit\">" << tr("Generate") << "</button>\r\n"
"</form>\r\n<small>" << tr("<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "</small>\r\n</div>\r\n</div>\r\n<br>\r\n";
@@ -448,9 +453,23 @@ namespace http {
if (dest->GetNumRemoteLeaseSets())
{
s << "<div class='slide'><label for='slide-lease'><b>" << tr("LeaseSets") << ":</b> <i>" << dest->GetNumRemoteLeaseSets ()
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n<table><thead><th>"<< tr("Address") << "</th><th>" << tr("Type") << "</th><th>" << tr("EncType") << "</th></thead><tbody class=\"tableitem\">";
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n"
<< "<table><thead>"
<< "<th>" << tr("Address") << "</th>"
<< "<th style=\"width:5px;\">&nbsp;</th>" // LeaseSet expiration button column
<< "<th>" << tr("Type") << "</th>"
<< "<th>" << tr("EncType") << "</th>"
<< "</thead><tbody class=\"tableitem\">";
for(auto& it: dest->GetLeaseSets ())
s << "<tr><td>" << it.first.ToBase32 () << "</td><td>" << (int)it.second->GetStoreType () << "</td><td>" << (int)it.second->GetEncryptionType () <<"</td></tr>\r\n";
{
s << "<tr>"
<< "<td>" << it.first.ToBase32 () << "</td>"
<< "<td><a class=\"button\" href=\"/?cmd=" << HTTP_COMMAND_EXPIRELEASE<< "&b32=" << dest->GetIdentHash ().ToBase32 ()
<< "&lease=" << it.first.ToBase32 () << "&token=" << token << "\" title=\"" << tr("Expire LeaseSet") << "\"> &#10008; </a></td>"
<< "<td>" << (int)it.second->GetStoreType () << "</td>"
<< "<td>" << (int)it.second->GetEncryptionType () <<"</td>"
<< "</tr>\r\n";
}
s << "</tbody></table>\r\n</div>\r\n</div>\r\n<br>\r\n";
} else
s << "<b>" << tr("LeaseSets") << ":</b> <i>0</i><br>\r\n<br>\r\n";
@@ -591,6 +610,8 @@ namespace http {
}
s << "</tbody>\r\n</table>";
}
else
ShowError(s, tr("Such destination is not found"));
}
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
@@ -958,34 +979,42 @@ namespace http {
void ShowI2PTunnels (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
auto& clientTunnels = i2p::client::context.GetClientTunnels ();
auto httpProxy = i2p::client::context.GetHttpProxy ();
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (socksProxy)
if (!clientTunnels.empty () || httpProxy || socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
if (!clientTunnels.empty ())
{
for (auto& it: clientTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
}
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
s << "</div>\r\n";
}
s << "</div>\r\n";
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
if (!serverTunnels.empty ()) {
@@ -1312,6 +1341,36 @@ namespace http {
res.add_header("Refresh", redirect.c_str());
return;
}
else if (cmd == HTTP_COMMAND_EXPIRELEASE)
{
std::string b32 = params["b32"];
std::string lease = params["lease"];
i2p::data::IdentHash ident, leaseident;
ident.FromBase32 (b32);
leaseident.FromBase32 (lease);
auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest)
{
auto leaseset = dest->FindLeaseSet (leaseident);
if (leaseset)
{
leaseset->ExpireLease ();
s << "<b>" << tr("SUCCESS") << "</b>:&nbsp;" << tr("LeaseSet expiration time updated") << "<br>\r\n<br>\r\n";
}
else
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("LeaseSet is not found or already expired") << "<br>\r\n<br>\r\n";
}
else
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Destination not found") << "<br>\r\n<br>\r\n";
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">" << tr("Return to destination page") << "</a><br>\r\n";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32;
res.add_header("Refresh", redirect.c_str());
return;
}
else if (cmd == HTTP_COMMAND_LIMITTRANSIT)
{
uint32_t limit = std::stoul(params["limit"], nullptr);

30
debian/changelog vendored
View File

@@ -1,3 +1,33 @@
i2pd (2.50.2) unstable; urgency=medium
* updated to version 2.50.2/0.9.61
-- orignal <orignal@i2pmail.org> Sat, 06 Jan 2024 16:00:00 +0000
i2pd (2.50.1-1) unstable; urgency=medium
* updated to version 2.50.1/0.9.61
-- r4sas <r4sas@i2pmail.org> Sat, 23 Dec 2023 18:30:00 +0000
i2pd (2.50.0-1) unstable; urgency=medium
* updated to version 2.50.0/0.9.61
-- orignal <orignal@i2pmail.org> Mon, 18 Dec 2023 16:00:00 +0000
i2pd (2.49.0-1) unstable; urgency=medium
* updated to version 2.49.0/0.9.60
-- orignal <orignal@i2pmail.org> Mon, 18 Sep 2023 16:00:00 +0000
i2pd (2.48.0-1) unstable; urgency=high
* updated to version 2.48.0/0.9.59
-- orignal <orignal@i2pmail.org> Mon, 12 Jun 2023 16:00:00 +0000
i2pd (2.47.0-1) unstable; urgency=high
* updated to version 2.47.0/0.9.58

2
debian/control vendored
View File

@@ -2,7 +2,7 @@ Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 12~), clang, cmake, libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Build-Depends: debhelper (>= 12~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 4.3.0
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git

10
debian/copyright vendored
View File

@@ -1,19 +1,23 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: i2pd
Source: https://github.com/PurpleI2P/i2pd
Source: https://github.com/PurpleI2P
Files: *
Copyright: 2013-2023 The PurpleI2P Project
Copyright: 2013-2023 PurpleI2P
License: BSD-3-clause
Files: debian/*
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
2014-2016 hagen <hagen@i2pmail.org>
2016-2023 R4SAS <r4sas@i2pmail.org>
2017-2023 Yangfl <mmyangfl@gmail.com>
2017-2020 Yangfl <mmyangfl@gmail.com>
License: GPL-2+
License: BSD-3-clause
Copyright (c) 2013-2023, The PurpleI2P Project
.
All rights reserved.
.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
.

2
debian/i2pd.1 vendored
View File

@@ -64,7 +64,7 @@ The network interface to bind to for IPv4 connections
The network interface to bind to for IPv6 connections
.TP
\fB\-\-ipv4=\fR
Enable communication through ipv6 (\fIenabled\fR by default)
Enable communication through ipv4 (\fIenabled\fR by default)
.TP
\fB\-\-ipv6\fR
Enable communication through ipv6 (\fIdisabled\fR by default)

2
debian/i2pd.install vendored
View File

@@ -1,4 +1,4 @@
obj-*/i2pd usr/sbin/
i2pd usr/sbin/
contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/
contrib/certificates/ usr/share/i2pd/

17
debian/patches/01-upnp.patch vendored Normal file
View File

@@ -0,0 +1,17 @@
Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -31,7 +31,7 @@ include filelist.mk
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
-USE_UPNP := $(or $(USE_UPNP),no)
+USE_UPNP := $(or $(USE_UPNP),yes)
DEBUG := $(or $(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string

1
debian/patches/series vendored Normal file
View File

@@ -0,0 +1 @@
01-upnp.patch

15
debian/rules vendored
View File

@@ -7,20 +7,7 @@ include /usr/share/dpkg/architecture.mk
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND =
export CC=clang
export CXX=clang++
%:
dh $@ --buildsystem=cmake
override_dh_auto_clean:
dh_auto_clean --buildsystem=cmake --sourcedirectory=build/
override_dh_auto_configure:
dh_auto_configure --buildsystem=cmake --sourcedirectory=build/ -- \
-DWITH_UPNP=ON
override_dh_auto_build:
dh_auto_build --buildsystem=cmake
dh $@
override_dh_auto_install:

View File

@@ -109,6 +109,7 @@ namespace chinese // language namespace
{"Local Destination", "本地目标"},
{"Streams", ""},
{"Close stream", "断开流"},
{"Such destination is not found", "找不到此目标"},
{"I2CP session not found", "未找到 I2CP 会话"},
{"I2CP is not enabled", "I2CP 未启用"},
{"Invalid", "无效"},
@@ -158,7 +159,6 @@ namespace chinese // language namespace
{"Submit", "提交"},
{"Domain can't end with .b32.i2p", "域名不能以 .b32.i2p 结尾"},
{"Domain must end with .i2p", "域名必须以 .i2p 结尾"},
{"Such destination is not found", "找不到此目标"},
{"Unknown command", "未知指令"},
{"Command accepted", "已接受指令"},
{"Proxy error", "代理错误"},

View File

@@ -69,6 +69,7 @@ namespace french // language namespace
{"Stopping in", "Arrêt dans"},
{"Family", "Famille"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Total tunnel creation success rate", "Taux de réussite de création de tunnel"},
{"Received", "Reçu"},
{"%.2f KiB/s", "%.2f Kio/s"},
{"Sent", "Envoyé"},
@@ -91,10 +92,11 @@ namespace french // language namespace
{"Address registration line", "Ligne d'inscription de l'adresse"},
{"Domain", "Domaine"},
{"Generate", "Générer"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note :</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"Address", "Adresse"},
{"Type", "Type"},
{"EncType", "EncType"},
{"Expire LeaseSet", "Expirer le jeu de baux"},
{"Inbound tunnels", "Tunnels entrants"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnels sortants"},
@@ -109,6 +111,7 @@ namespace french // language namespace
{"Local Destination", "Destination locale"},
{"Streams", "Flux"},
{"Close stream", "Fermer le flux"},
{"Such destination is not found", "Cette destination est introuvable"},
{"I2CP session not found", "Session I2CP introuvable"},
{"I2CP is not enabled", "I2CP est désactivé"},
{"Invalid", "Invalide"},
@@ -128,7 +131,7 @@ namespace french // language namespace
{"Start graceful shutdown", "Démarrer l'arrêt gracieux"},
{"Force shutdown", "Forcer l'arrêt"},
{"Reload external CSS styles", "Rafraîchir les styles CSS externes"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note:</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note :</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
{"Logging level", "Niveau de journalisation"},
{"Transit tunnels limit", "Limite sur les tunnels transitoires"},
{"Change", "Changer"},
@@ -150,6 +153,8 @@ namespace french // language namespace
{"StreamID can't be null", "StreamID ne peut pas être vide"},
{"Return to destination page", "Retourner à la page de destination"},
{"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"},
{"LeaseSet expiration time updated", "Temps d'expiration du jeu de baux mis à jour"},
{"LeaseSet is not found or already expired", "Le jeu de baux est introuvable ou a déjà expiré"},
{"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"},
{"Back to commands list", "Retour à la liste des commandes"},
{"Register at reg.i2p", "Inscription à reg.i2p"},
@@ -158,24 +163,23 @@ namespace french // language namespace
{"Submit", "Soumettre"},
{"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"},
{"Domain must end with .i2p", "Le domaine doit terminer par .i2p"},
{"Such destination is not found", "Cette destination est introuvable"},
{"Unknown command", "Commande inconnue"},
{"Command accepted", "Commande acceptée"},
{"Proxy error", "Erreur de proxy"},
{"Proxy info", "Information sur le proxy"},
{"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"},
{"Proxy error: Host not found", "Erreur de proxy : Hôte introuvable"},
{"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"},
{"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"},
{"Invalid request", "Requête invalide"},
{"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"},
{"Addresshelper is not supported", "Assistant d'adresse non supporté"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
{"Addresshelper request", "Demande à l'assistant d'adresse"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "L'hôte %s a été ajouté au carnet d'adresses du routeur depuis l'assistant. Cliquez ici pour continuer : <a href=\"%s\">Continuer</a>."},
{"Addresshelper adding", "Ajout de l'assistant d'adresse"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Addresshelper update", "Mise à jour de l'assistant d'adresse"},
{"Invalid request URI", "URI de la requête invalide"},
{"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"},

View File

@@ -69,6 +69,7 @@ namespace italian // language namespace
{"Stopping in", "Arresto in"},
{"Family", "Famiglia"},
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
{"Total tunnel creation success rate", "Percentuale di successo totale nella creazione del tunnel"},
{"Received", "Ricevuti"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Inviati"},
@@ -95,6 +96,7 @@ namespace italian // language namespace
{"Address", "Indirizzo"},
{"Type", "Tipologia"},
{"EncType", "Tipo di crittografia"},
{"Expire LeaseSet", "Scadenza LeaseSet"},
{"Inbound tunnels", "Tunnel in entrata"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnel in uscita"},
@@ -109,6 +111,7 @@ namespace italian // language namespace
{"Local Destination", "Destinazione locale"},
{"Streams", "Flussi"},
{"Close stream", "Interrompi il flusso"},
{"Such destination is not found", "Questa destinazione non è stata trovata"},
{"I2CP session not found", "Sessione I2CP non trovata"},
{"I2CP is not enabled", "I2CP non è abilitato"},
{"Invalid", "Invalido"},
@@ -150,6 +153,8 @@ namespace italian // language namespace
{"StreamID can't be null", "Lo StreamID non può essere null"},
{"Return to destination page", "Ritorna alla pagina di destinazione"},
{"You will be redirected in %d seconds", "Sarai reindirizzato tra %d secondi"},
{"LeaseSet expiration time updated", "Tempo di scadenza LeaseSet aggiornato"},
{"LeaseSet is not found or already expired", "LeaseSet non trovato o già scaduto"},
{"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"},
{"Back to commands list", "Ritorna alla lista dei comandi"},
{"Register at reg.i2p", "Registra a reg.i2p"},
@@ -158,7 +163,6 @@ namespace italian // language namespace
{"Submit", "Invia"},
{"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"},
{"Domain must end with .i2p", "I domini devono terminare con .i2p"},
{"Such destination is not found", "Questa destinazione non è stata trovata"},
{"Unknown command", "Comando sconosciuto"},
{"Command accepted", "Comando accettato"},
{"Proxy error", "Errore del proxy"},

View File

@@ -69,6 +69,7 @@ namespace portuguese // language namespace
{"Stopping in", "Parando em"},
{"Family", "Família"},
{"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"},
{"Total tunnel creation success rate", "Taxa total de sucesso na criação de túneis"},
{"Received", "Recebido"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Enviado"},
@@ -95,6 +96,7 @@ namespace portuguese // language namespace
{"Address", "Endereço"},
{"Type", "Tipo"},
{"EncType", "Tipo de Criptografia"},
{"Expire LeaseSet", "Expirar LeaseSet"},
{"Inbound tunnels", "Túneis de Entrada"},
{"%dms", "%dms"},
{"Outbound tunnels", "Túneis de Saída"},
@@ -109,6 +111,7 @@ namespace portuguese // language namespace
{"Local Destination", "Destinos Locais"},
{"Streams", "Fluxos"},
{"Close stream", "Fechar fluxo"},
{"Such destination is not found", "Tal destino não foi encontrado"},
{"I2CP session not found", "Sessão do I2CP não encontrada"},
{"I2CP is not enabled", "I2CP não está ativado"},
{"Invalid", "Inválido"},
@@ -150,6 +153,8 @@ namespace portuguese // language namespace
{"StreamID can't be null", "StreamID não pode ser nulo"},
{"Return to destination page", "Retornar para à página de destino"},
{"You will be redirected in %d seconds", "Você será redirecionado em %d segundos"},
{"LeaseSet expiration time updated", "Tempo de validade do LeaseSet atualizado"},
{"LeaseSet is not found or already expired", "LeaseSet não foi encontrado ou já expirou"},
{"Transit tunnels count must not exceed %d", "A contagem de túneis de trânsito não deve exceder %d"},
{"Back to commands list", "Voltar para a lista de comandos"},
{"Register at reg.i2p", "Registrar na reg.i2p"},
@@ -158,7 +163,6 @@ namespace portuguese // language namespace
{"Submit", "Enviar"},
{"Domain can't end with .b32.i2p", "O domínio não pode terminar com .b32.i2p"},
{"Domain must end with .i2p", "O domínio não pode terminar com .i2p"},
{"Such destination is not found", "Tal destino não foi encontrado"},
{"Unknown command", "Comando desconhecido"},
{"Command accepted", "Comando aceito"},
{"Proxy error", "Erro no proxy"},

View File

@@ -69,6 +69,7 @@ namespace russian // language namespace
{"Stopping in", "Остановка через"},
{"Family", "Семейство"},
{"Tunnel creation success rate", "Успешно построенных туннелей"},
{"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"},
{"Received", "Получено"},
{"%.2f KiB/s", "%.2f КиБ/с"},
{"Sent", "Отправлено"},
@@ -95,6 +96,7 @@ namespace russian // language namespace
{"Address", "Адрес"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Просрочить Лизсет"},
{"Inbound tunnels", "Входящие туннели"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Исходящие туннели"},
@@ -109,6 +111,7 @@ namespace russian // language namespace
{"Local Destination", "Локальное назначение"},
{"Streams", "Стримы"},
{"Close stream", "Закрыть стрим"},
{"Such destination is not found", "Такая точка назначения не найдена"},
{"I2CP session not found", "I2CP сессия не найдена"},
{"I2CP is not enabled", "I2CP не включен"},
{"Invalid", "Некорректный"},
@@ -150,6 +153,8 @@ namespace russian // language namespace
{"StreamID can't be null", "StreamID не может быть пустым"},
{"Return to destination page", "Вернуться на страницу точки назначения"},
{"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"},
{"LeaseSet expiration time updated", "Время действия LeaseSet обновлено"},
{"LeaseSet is not found or already expired", "Лизсет не найден или время действия уже истекло"},
{"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"},
{"Back to commands list", "Вернуться к списку команд"},
{"Register at reg.i2p", "Зарегистрировать на reg.i2p"},
@@ -158,7 +163,6 @@ namespace russian // language namespace
{"Submit", "Отправить"},
{"Domain can't end with .b32.i2p", "Домен не может заканчиваться на .b32.i2p"},
{"Domain must end with .i2p", "Домен должен заканчиваться на .i2p"},
{"Such destination is not found", "Такая точка назначения не найдена"},
{"Unknown command", "Неизвестная команда"},
{"Command accepted", "Команда принята"},
{"Proxy error", "Ошибка прокси"},

View File

@@ -61,6 +61,8 @@ namespace swedish // language namespace
{"Clock skew", "Tidsförskjutning"},
{"Offline", "Nedkopplad"},
{"Symmetric NAT", "Symmetrisk NAT"},
{"Full cone NAT", "Full kon NAT"},
{"No Descriptors", "Inga Beskrivningar"},
{"Uptime", "Upptid"},
{"Network status", "Nätverkstillstånd"},
{"Network status v6", "Nätverkstillstånd v6"},
@@ -107,6 +109,7 @@ namespace swedish // language namespace
{"Local Destination", "Lokal Plats"},
{"Streams", "Strömmar"},
{"Close stream", "Stäng strömmen"},
{"Such destination is not found", "En sådan plats hittas ej"},
{"I2CP session not found", "I2CP-period hittades inte"},
{"I2CP is not enabled", "I2CP är inte påslaget"},
{"Invalid", "Ogiltig"},
@@ -116,8 +119,10 @@ namespace swedish // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "EndDate"},
{"floodfill mode is disabled", "Floodfill läget är inaktiverat"},
{"Queue size", "Köstorlek"},
{"Run peer test", "Utför utsiktstest"},
{"Reload tunnels configuration", "Ladda om tunnelkonfiguration"},
{"Decline transit tunnels", "Avvisa förmedlande tunnlar"},
{"Accept transit tunnels", "Tillåt förmedlande tunnlar"},
{"Cancel graceful shutdown", "Avbryt välvillig avstängning"},
@@ -154,7 +159,6 @@ namespace swedish // language namespace
{"Submit", "Skicka"},
{"Domain can't end with .b32.i2p", "Domänen får inte sluta med .b32.i2p"},
{"Domain must end with .i2p", "Domänen måste sluta med .i2p"},
{"Such destination is not found", "En sådan plats hittas ej"},
{"Unknown command", "Okänt kommando"},
{"Command accepted", "Kommando accepterades"},
{"Proxy error", "Proxyfel"},
@@ -165,6 +169,14 @@ namespace swedish // language namespace
{"Invalid request", "Ogiltig förfrågan"},
{"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"},
{"Addresshelper is not supported", "Adresshjälparen stöds ej"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. <b>Var försiktig: källan till denna URL kan vara skadlig!</b> Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
{"Addresshelper forced update rejected", "Tvingad uppdatering av adresshjälparen nekad"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "För att lägga till värd <b>%s</b> i routerns adressbok, klicka här: <a href=\"%s%s%s\">Fortsätt</a>."},
{"Addresshelper request", "Adresshjälpare förfrågan"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Värd %s tillagd i routerns adressbok från hjälparen. Klicka här för att fortsätta: <a href=\"%s\">Fortsätt</a>."},
{"Addresshelper adding", "Adresshjälpare tilläggning"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
{"Addresshelper update", "Adresshjälpare uppdatering"},
{"Invalid request URI", "Ogiltig förfrågnings-URI"},
{"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"},
{"Outproxy failure", "Utproxyfel"},

View File

@@ -69,6 +69,7 @@ namespace ukrainian // language namespace
{"Stopping in", "Зупинка через"},
{"Family", "Сімейство"},
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
{"Total tunnel creation success rate", "Загальна кількість створених тунелів"},
{"Received", "Отримано"},
{"%.2f KiB/s", "%.2f КіБ/с"},
{"Sent", "Відправлено"},
@@ -95,6 +96,7 @@ namespace ukrainian // language namespace
{"Address", "Адреса"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Завершити LeaseSet"},
{"Inbound tunnels", "Вхідні тунелі"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Вихідні тунелі"},
@@ -109,6 +111,7 @@ namespace ukrainian // language namespace
{"Local Destination", "Локальні Призначення"},
{"Streams", "Потоки"},
{"Close stream", "Закрити потік"},
{"Such destination is not found", "Така точка призначення не знайдена"},
{"I2CP session not found", "I2CP сесія не знайдена"},
{"I2CP is not enabled", "I2CP не увікнуто"},
{"Invalid", "Некоректний"},
@@ -150,6 +153,8 @@ namespace ukrainian // language namespace
{"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"},
{"Return to destination page", "Повернутися на сторінку точки призначення"},
{"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"},
{"LeaseSet expiration time updated", "Час закінчення LeaseSet оновлено"},
{"LeaseSet is not found or already expired", "LeaseSet не знайдено або вже закінчився"},
{"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"},
{"Back to commands list", "Повернутися до списку команд"},
{"Register at reg.i2p", "Зареєструвати на reg.i2p"},
@@ -158,7 +163,6 @@ namespace ukrainian // language namespace
{"Submit", "Надіслати"},
{"Domain can't end with .b32.i2p", "Домен не може закінчуватися на .b32.i2p"},
{"Domain must end with .i2p", "Домен повинен закінчуватися на .i2p"},
{"Such destination is not found", "Така точка призначення не знайдена"},
{"Unknown command", "Невідома команда"},
{"Command accepted", "Команда прийнята"},
{"Proxy error", "Помилка проксі"},

View File

@@ -69,6 +69,7 @@ namespace uzbek // language namespace
{"Stopping in", "Ichida to'xtatish"},
{"Family", "Oila"},
{"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"},
{"Total tunnel creation success rate", "Tunnel yaratishning umumiy muvaffaqiyat darajasi"},
{"Received", "Qabul qilindi"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Yuborilgan"},
@@ -95,6 +96,7 @@ namespace uzbek // language namespace
{"Address", "Manzil"},
{"Type", "Turi"},
{"EncType", "ShifrlashTuri"},
{"Expire LeaseSet", "LeaseSet muddati tugaydi"},
{"Inbound tunnels", "Kirish tunnellari"},
{"%dms", "%dms"},
{"Outbound tunnels", "Chiquvchi tunnellar"},
@@ -109,6 +111,7 @@ namespace uzbek // language namespace
{"Local Destination", "Mahalliy joylanish"},
{"Streams", "Strim"},
{"Close stream", "Strimni o'chirish"},
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
{"I2CP is not enabled", "I2CP yoqilmagan"},
{"Invalid", "Noto'g'ri"},
@@ -150,6 +153,8 @@ namespace uzbek // language namespace
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
{"Return to destination page", "Manzilgoh sahifasiga qaytish"},
{"You will be redirected in %d seconds", "Siz %d soniyadan song boshqa yonalishga yonaltirilasiz"},
{"LeaseSet expiration time updated", "LeaseSet amal qilish muddati yangilandi"},
{"LeaseSet is not found or already expired", "LeaseSet topilmadi yoki muddati tugagan"},
{"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"},
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
@@ -158,7 +163,6 @@ namespace uzbek // language namespace
{"Submit", "Yuborish"},
{"Domain can't end with .b32.i2p", "Domen .b32.i2p bilan tugashi mumkin emas"},
{"Domain must end with .i2p", "Domen .i2p bilan tugashi kerak"},
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
{"Unknown command", "Noma'lum buyruq"},
{"Command accepted", "Buyruq qabul qilindi"},
{"Proxy error", "Proksi xatosi"},

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -28,6 +28,11 @@ namespace data
return T32;
}
bool IsBase32 (char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
}
static void iT64Build(void);
/*
@@ -55,6 +60,11 @@ namespace data
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)
*/
@@ -187,6 +197,9 @@ namespace data
else
return 0;
if(*InBuffer == P64)
return 0;
ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 )
outCount--;
@@ -269,7 +282,7 @@ namespace data
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen)
{
int tmp = 0, bits = 0;
unsigned int tmp = 0, bits = 0;
size_t ret = 0;
for (size_t i = 0; i < len; i++)
{
@@ -298,7 +311,7 @@ namespace data
size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
{
size_t ret = 0, pos = 1;
int bits = 8, tmp = inBuf[0];
unsigned int bits = 8, tmp = inBuf[0];
while (ret < outLen && (bits > 0 || pos < len))
{
if (bits < 5)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,9 +19,11 @@ namespace data {
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
const char * GetBase32SubstitutionTable ();
const char * GetBase64SubstitutionTable ();
bool IsBase64 (char ch);
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
bool IsBase32 (char ch);
/**
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -7,52 +7,62 @@
*/
#include "CPU.h"
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
#endif
#include "Log.h"
#ifndef bit_AES
#define bit_AES (1 << 25)
#endif
#ifndef bit_AVX
#define bit_AVX (1 << 28)
#define bit_AES (1 << 25)
#endif
#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86
#include <cpuid.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace i2p
{
namespace cpu
{
bool aesni = false;
bool avx = false;
void Detect(bool AesSwitch, bool AvxSwitch, bool force)
inline bool cpu_support_aes()
{
#if defined(__x86_64__) || defined(__i386__)
int info[4];
__cpuid(0, info[0], info[1], info[2], info[3]);
if (info[0] >= 0x00000001) {
__cpuid(0x00000001, info[0], info[1], info[2], info[3]);
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
if (AesSwitch && force) { // only if forced
#else
if ((info[2] & bit_AES && AesSwitch) || (AesSwitch && force)) {
#endif
aesni = true;
}
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
if (AvxSwitch && force) { // only if forced
#else
if ((info[2] & bit_AVX && AvxSwitch) || (AvxSwitch && force)) {
#endif
avx = true;
}
#if IS_X86
#if defined(__clang__)
# if (__clang_major__ >= 6)
__builtin_cpu_init();
# endif
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ >= 6)
__builtin_cpu_init();
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ < 6)
int cpu_info[4];
bool flag = false;
__cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
if (cpu_info[0] >= 0x00000001) {
__cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
flag = ((cpu_info[2] & bit_AES) != 0);
}
return flag;
#elif defined(_MSC_VER)
int cpu_info[4];
__cpuid(cpu_info, 1);
return ((cpu_info[2] & bit_AES) != 0);
#endif
#endif
return false;
}
void Detect(bool AesSwitch, bool force)
{
if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) {
aesni = true;
}
#endif // defined(__x86_64__) || defined(__i386__)
LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled"));
LogPrint(eLogInfo, "AVX ", (avx ? "enabled" : "disabled"));
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -9,14 +9,31 @@
#ifndef LIBI2PD_CPU_H
#define LIBI2PD_CPU_H
#if defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
# define IS_X86 1
# if defined(_M_AMD64) || defined(__x86_64__)
# define IS_X86_64 1
# else
# define IS_X86_64 0
# endif
#else
# define IS_X86 0
# define IS_X86_64 0
#endif
#if defined(__AES__) && !defined(_MSC_VER) && IS_X86
# define SUPPORTS_AES 1
#else
# define SUPPORTS_AES 0
#endif
namespace i2p
{
namespace cpu
{
extern bool aesni;
extern bool avx;
void Detect(bool AesSwitch, bool AvxSwitch, bool force);
void Detect(bool AesSwitch, bool force);
}
}

View File

@@ -78,6 +78,7 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)")
("limits.zombies", value<double>()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
@@ -192,7 +193,7 @@ namespace config {
options_description precomputation("Precomputation options");
precomputation.add_options()
("precomputation.elgamal",
#if defined(__x86_64__)
#if (defined(_M_AMD64) || defined(__x86_64__))
value<bool>()->default_value(false),
#else
value<bool>()->default_value(true),
@@ -220,14 +221,17 @@ namespace config {
"https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/,"
"https://i2p.ghativega.in/,"
"https://i2p.novg.net/"
"https://i2p.novg.net/,"
"https://reseed.is.prestium.org/,"
"https://reseed.us.prestium.org/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/,"
"http://[301:65b9:c7cd:9a36::1]:18801/,"
"http://[320:8936:ec1a:31f1::216]/,"
"http://[306:3834:97b9:a00a::1]/,"
"http://[316:f9e0:f22e:a74f::216]/"
"http://[316:f9e0:f22e:a74f::216]/,"
"http://[300:eaff:7fab:181b::e621]:7170"
), "Reseed URLs through the Yggdrasil, separated by comma")
;
@@ -307,7 +311,7 @@ namespace config {
options_description cpuext("CPU encryption extensions options");
cpuext.add_options()
("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used")
("cpuext.avx", bool_switch()->default_value(true), "Use auto detection for AVX CPU extensions. If false, AVX will be not used")
("cpuext.avx", bool_switch()->default_value(false), "Deprecated option")
("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines")
;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -28,6 +28,7 @@
#include "I2PEndian.h"
#include "Log.h"
namespace i2p
{
namespace crypto
@@ -159,7 +160,7 @@ namespace crypto
// DH/ElGamal
#if !defined(__x86_64__)
#if !IS_X86_64
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
#endif
@@ -361,7 +362,7 @@ namespace crypto
BIGNUM * b1 = BN_CTX_get (ctx);
BIGNUM * b = BN_CTX_get (ctx);
// select random k
#if defined(__x86_64__)
#if IS_X86_64
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
#else
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
@@ -428,7 +429,7 @@ namespace crypto
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
{
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
#if IS_X86 || defined(_MSC_VER)
RAND_bytes (priv, 256);
#else
// lower 226 bits (28 bytes and 2 bits) only. short exponent
@@ -555,7 +556,7 @@ namespace crypto
}
// AES
#ifdef __AES__
#if SUPPORTS_AES
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
"movaps %%xmm1, %%xmm4 \n" \
@@ -580,7 +581,7 @@ namespace crypto
"movaps %%xmm3, "#round1"(%[sched]) \n"
#endif
#ifdef __AES__
#if SUPPORTS_AES
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{
__asm__
@@ -621,7 +622,7 @@ namespace crypto
#endif
#ifdef __AES__
#if SUPPORTS_AES
#define EncryptAES256(sched) \
"pxor (%["#sched"]), %%xmm0 \n" \
"aesenc 16(%["#sched"]), %%xmm0 \n" \
@@ -642,16 +643,18 @@ namespace crypto
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
}
else
#endif
@@ -660,7 +663,7 @@ namespace crypto
}
}
#ifdef __AES__
#if SUPPORTS_AES
#define DecryptAES256(sched) \
"pxor 224(%["#sched"]), %%xmm0 \n" \
"aesdec 208(%["#sched"]), %%xmm0 \n" \
@@ -681,16 +684,18 @@ namespace crypto
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
}
else
#endif
@@ -699,7 +704,7 @@ namespace crypto
}
}
#ifdef __AES__
#if SUPPORTS_AES
#define CallAESIMC(offset) \
"movaps "#offset"(%[shed]), %%xmm0 \n" \
"aesimc %%xmm0, %%xmm0 \n" \
@@ -708,7 +713,7 @@ namespace crypto
void ECBEncryption::SetKey (const AESKey& key)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
ExpandKey (key);
@@ -722,28 +727,30 @@ namespace crypto
void ECBDecryption::SetKey (const AESKey& key)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
ExpandKey (key); // expand encryption key first
// then invert it using aesimc
__asm__
(
CallAESIMC(16)
CallAESIMC(32)
CallAESIMC(48)
CallAESIMC(64)
CallAESIMC(80)
CallAESIMC(96)
CallAESIMC(112)
CallAESIMC(128)
CallAESIMC(144)
CallAESIMC(160)
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
);
(
CallAESIMC(16)
CallAESIMC(32)
CallAESIMC(48)
CallAESIMC(64)
CallAESIMC(80)
CallAESIMC(96)
CallAESIMC(112)
CallAESIMC(128)
CallAESIMC(144)
CallAESIMC(160)
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
:
: [shed]"r"(GetKeySchedule ())
: "%xmm0", "memory"
);
}
else
#endif
@@ -754,28 +761,28 @@ namespace crypto
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
}
else
#endif
@@ -799,22 +806,22 @@ namespace crypto
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
@@ -823,29 +830,29 @@ namespace crypto
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
@@ -869,22 +876,22 @@ namespace crypto
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
@@ -893,34 +900,34 @@ namespace crypto
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
(
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
}
else
#endif
@@ -934,35 +941,35 @@ namespace crypto
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{
#ifdef __AES__
#if SUPPORTS_AES
if(i2p::cpu::aesni)
{
__asm__
(
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
(
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
@@ -991,7 +998,7 @@ namespace crypto
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
EVP_EncryptFinal_ex(ctx, buf, &outlen);
EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
}
else
@@ -1285,9 +1292,9 @@ namespace crypto
}
}*/
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force)
void InitCrypto (bool precomputation, bool aesni, bool force)
{
i2p::cpu::Detect (aesni, avx, force);
i2p::cpu::Detect (aesni, force);
#if LEGACY_OPENSSL
SSL_library_init ();
#endif
@@ -1297,7 +1304,7 @@ namespace crypto
CRYPTO_set_locking_callback (OpensslLockingCallback);*/
if (precomputation)
{
#if defined(__x86_64__)
#if IS_X86_64
g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
#else
@@ -1312,7 +1319,7 @@ namespace crypto
if (g_ElggTable)
{
DestroyElggTable (g_ElggTable,
#if defined(__x86_64__)
#if IS_X86_64
ELGAMAL_FULL_EXPONENT_NUM_BYTES
#else
ELGAMAL_SHORT_EXPONENT_NUM_BYTES

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -150,7 +150,7 @@ namespace crypto
};
#ifdef __AES__
#if SUPPORTS_AES
class ECBCryptoAESNI
{
public:
@@ -167,7 +167,7 @@ namespace crypto
};
#endif
#ifdef __AES__
#if SUPPORTS_AES
class ECBEncryption: public ECBCryptoAESNI
#else
class ECBEncryption
@@ -183,7 +183,7 @@ namespace crypto
AES_KEY m_Key;
};
#ifdef __AES__
#if SUPPORTS_AES
class ECBDecryption: public ECBCryptoAESNI
#else
class ECBDecryption
@@ -307,7 +307,7 @@ namespace crypto
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
// init and terminate
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force);
void InitCrypto (bool precomputation, bool aesni, bool force);
void TerminateCrypto ();
}
}

View File

@@ -262,17 +262,6 @@ namespace client
return nullptr;
}
}
else
{
auto ls = i2p::data::netdb.FindLeaseSet (ident);
if (ls && !ls->IsExpired ())
{
ls->PopulateLeases (); // since we don't store them in netdb
std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ident] = ls;
return ls;
}
}
return nullptr;
}
@@ -1047,11 +1036,15 @@ namespace client
void ClientDestination::Stop ()
{
LogPrint(eLogDebug, "Destination: Stopping destination ", GetIdentHash().ToBase32(), ".b32.i2p");
LeaseSetDestination::Stop ();
m_ReadyChecker.cancel();
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination");
m_StreamingDestination->Stop ();
//m_StreamingDestination->SetOwner (nullptr);
m_StreamingDestination = nullptr;
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination by ports");
for (auto& it: m_StreamingDestinationsByPorts)
{
it.second->Stop ();
@@ -1059,11 +1052,14 @@ namespace client
}
m_StreamingDestinationsByPorts.clear ();
m_LastStreamingDestination = nullptr;
if (m_DatagramDestination)
{
LogPrint(eLogDebug, "Destination: -> Stopping Datagram Destination");
delete m_DatagramDestination;
m_DatagramDestination = nullptr;
}
LogPrint(eLogDebug, "Destination: -> Stopping done");
}
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
@@ -1086,10 +1082,10 @@ namespace client
if (toPort != m_LastPort || !m_LastStreamingDestination)
{
m_LastStreamingDestination = GetStreamingDestination (toPort);
if (!m_LastStreamingDestination)
if (!m_LastStreamingDestination)
m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default
m_LastPort = toPort;
}
}
if (m_LastStreamingDestination)
m_LastStreamingDestination->HandleDataMessagePayload (buf, length);
else
@@ -1115,7 +1111,7 @@ namespace client
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port)
{
if (!streamRequestComplete)
{
@@ -1145,7 +1141,7 @@ namespace client
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
{
if (!streamRequestComplete)
{
@@ -1164,7 +1160,7 @@ namespace client
}
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, uint16_t port)
{
volatile bool done = false;
std::shared_ptr<i2p::stream::Stream> stream;
@@ -1188,17 +1184,17 @@ namespace client
return stream;
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, uint16_t port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port)
{
if (m_StreamingDestination)
return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
@@ -1235,7 +1231,7 @@ namespace client
});
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (uint16_t port) const
{
if (port)
{
@@ -1273,7 +1269,7 @@ namespace client
m_StreamingDestination->AcceptOnce (acceptor);
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (uint16_t port, bool gzip)
{
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
if (port)
@@ -1283,7 +1279,7 @@ namespace client
return dest;
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (int port)
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (uint16_t port)
{
if (port)
{

View File

@@ -14,6 +14,7 @@
#include <mutex>
#include <memory>
#include <map>
#include <unordered_map>
#include <set>
#include <string>
#include <functional>
@@ -184,8 +185,8 @@ namespace client
boost::asio::io_service& m_Service;
mutable std::mutex m_RemoteLeaseSetsMutex;
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
std::mutex m_LeaseSetMutex;
@@ -241,15 +242,15 @@ namespace client
int GetRefCounter () const { return m_RefCounter; };
// streaming
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (int port);
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (uint16_t port, bool gzip = true); // additional
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (uint16_t port = 0) const;
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (uint16_t port);
// following methods operate with default streaming destination
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port = 0);
void SendPing (const i2p::data::IdentHash& to);
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
@@ -285,7 +286,7 @@ namespace client
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port);
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, uint16_t port);
private:

View File

@@ -136,6 +136,14 @@ namespace fs {
dataDir = (home != NULL && strlen(home) > 0) ? home : "";
dataDir += "/Library/Application Support/" + appName;
return;
#elif defined(__HAIKU__)
char *home = getenv("HOME");
if (home != NULL && strlen(home) > 0) {
dataDir = std::string(home) + "/config/settings/" + appName;
} else {
dataDir = "/tmp/" + appName;
}
return;
#else /* other unix */
#if defined(ANDROID)
const char * ext = getenv("EXTERNAL_STORAGE");

View File

@@ -588,7 +588,7 @@ namespace garlic
auto it = m_ECIESx25519Tags.find (tag);
if (it != m_ECIESx25519Tags.end ())
{
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index))
m_LastTagset = it->second.tagset;
else
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");

View File

@@ -40,7 +40,7 @@ namespace i2p
{
return std::make_shared<I2NPMessageBuffer<I2NP_MAX_MEDIUM_MESSAGE_SIZE> >();
}
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
{
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
@@ -51,7 +51,7 @@ namespace i2p
len += I2NP_HEADER_SIZE + 2;
if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage ();
if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage ();
return NewI2NPMessage ();
return NewI2NPMessage ();
}
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum)
@@ -424,6 +424,11 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num);
return;
}
if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len);
@@ -477,6 +482,11 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num);
return;
}
size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
if (len < num*recordSize + 1)
{
@@ -508,6 +518,11 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num);
return;
}
if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len);
@@ -733,46 +748,38 @@ namespace i2p
return l;
}
void HandleI2NPMessage (uint8_t * msg, size_t len)
void HandleTunnelBuildI2NPMessage (std::shared_ptr<I2NPMessage> msg)
{
if (len < I2NP_HEADER_SIZE)
if (msg)
{
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return;
}
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + I2NP_HEADER_SIZE;
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
len -= I2NP_HEADER_SIZE;
if (size > len)
{
LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
size = len;
}
switch (typeID)
{
case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size);
break;
case eI2NPTunnelBuildReply:
// TODO:
break;
default:
LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID);
uint8_t typeID = msg->GetTypeID();
uint32_t msgID = msg->GetMsgID();
LogPrint (eLogDebug, "I2NP: Handling tunnel build message with len=", msg->GetLength(),", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * payload = msg->GetPayload();
auto size = msg->GetPayloadLength();
switch (typeID)
{
case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, payload, size);
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, payload, size);
break;
case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, payload, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, payload, size, true);
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (payload, size);
break;
case eI2NPTunnelBuildReply:
// TODO:
break;
default:
LogPrint (eLogError, "I2NP: Unexpected message with type", (int)typeID, " during handling TBM; skipping");
}
}
}
@@ -785,10 +792,12 @@ namespace i2p
switch (typeID)
{
case eI2NPTunnelData:
i2p::tunnel::tunnels.PostTunnelData (msg);
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPTunnelGateway:
i2p::tunnel::tunnels.PostTunnelData (msg);
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPGarlic:
{
@@ -799,10 +808,16 @@ namespace i2p
break;
}
case eI2NPDatabaseStore:
case eI2NPDatabaseSearchReply:
case eI2NPDatabaseSearchReply:
// forward to netDb if came directly or through exploratory tunnel as response to our request
if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ())
i2p::data::netdb.PostI2NPMsg (msg);
break;
case eI2NPDatabaseLookup:
// forward to netDb
i2p::data::netdb.PostI2NPMsg (msg);
// forward to netDb if floodfill and came directly
if (!msg->from && i2p::context.IsFloodfill ())
i2p::data::netdb.PostI2NPMsg (msg);
break;
case eI2NPDeliveryStatus:
{
@@ -813,16 +828,20 @@ namespace i2p
break;
}
case eI2NPVariableTunnelBuild:
case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild:
// forward to tunnel thread
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuildReply:
// forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
default:
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
LogPrint(eLogError, "I2NP: Unexpected I2NP message with type ", int(typeID), " during handling; skipping");
}
}
}

View File

@@ -295,7 +295,7 @@ namespace tunnel
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg);
size_t GetI2NPMessageLength (const uint8_t * msg, size_t len);
void HandleI2NPMessage (uint8_t * msg, size_t len);
void HandleTunnelBuildI2NPMessage (std::shared_ptr<I2NPMessage> msg);
void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg);
class I2NPMessagesHandler

View File

@@ -14,7 +14,7 @@
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) || defined(__HAIKU__)
#include <endian.h>
#elif defined(__APPLE__) && defined(__MACH__)

View File

@@ -581,7 +581,7 @@ namespace data
if (keyType == SIGNING_KEY_TYPE_DSA_SHA1)
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey));
else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ())
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey + (sizeof(Identity::signingKey) - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH))); // TODO: remove public key check
else
{
// public key is not required
@@ -803,29 +803,12 @@ namespace data
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
{
XORMetric m;
#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600)
if(i2p::cpu::avx)
{
__asm__
(
"vmovups %1, %%ymm0 \n"
"vmovups %2, %%ymm1 \n"
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
"vmovups %%ymm1, %0 \n"
: "=m"(*m.metric)
: "m"(*key1), "m"(*key2)
: "memory", "%xmm0", "%xmm1" // should be replaced by %ymm0/1 once supported by compiler
);
}
else
#endif
{
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
m.metric_ll[0] = hash1[0] ^ hash2[0];
m.metric_ll[1] = hash1[1] ^ hash2[1];
m.metric_ll[2] = hash1[2] ^ hash2[2];
m.metric_ll[3] = hash1[3] ^ hash2[3];
}
const uint64_t * hash1 = key1.GetLL (), * hash2 = key2.GetLL ();
m.metric_ll[0] = hash1[0] ^ hash2[0];
m.metric_ll[1] = hash1[1] ^ hash2[1];
m.metric_ll[2] = hash1[2] ^ hash2[2];
m.metric_ll[3] = hash1[3] ^ hash2[3];
return m;
}

View File

@@ -96,6 +96,9 @@ namespace data
void Encrypt (const uint8_t * data, uint8_t * encrypted) const;
bool IsDestination () const { return true; };
// used in webconsole
void ExpireLease () { m_ExpirationTime = i2p::util::GetSecondsSinceEpoch (); };
protected:
void UpdateLeasesBegin ();

View File

@@ -374,8 +374,17 @@ namespace transport
transports.PeerDisconnected (shared_from_this ());
m_Server.RemoveNTCP2Session (shared_from_this ());
m_SendQueue.clear ();
m_SendQueueSize = 0;
LogPrint (eLogDebug, "NTCP2: Session terminated");
SetSendQueueSize (0);
auto remoteIdentity = GetRemoteIdentity ();
if (remoteIdentity)
{
LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
}
else
{
LogPrint (eLogDebug, "NTCP2: Session with ", GetRemoteEndpoint (), " terminated");
}
}
}
@@ -424,7 +433,7 @@ namespace transport
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
{
if (m_NextReceivedBuffer && !m_IsReceiving &&
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
ts > GetLastActivityTimestamp () + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
{
delete[] m_NextReceivedBuffer;
m_NextReceivedBuffer = nullptr;
@@ -566,7 +575,11 @@ namespace transport
SendSessionConfirmed ();
}
else
{
if (GetRemoteIdentity ())
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key
Terminate ();
}
}
}
@@ -687,16 +700,25 @@ namespace transport
i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag
if (ri.IsUnreachable ())
{
LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed");
LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ());
SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail);
return;
}
if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
LogPrint(eLogDebug, "NTCP2: SessionConfirmed from ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (ri.GetIdentHash ()), ")");
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (ts > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
{
LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed");
LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed for ", (ts - ri.GetTimestamp ())/1000LL, " seconds");
SendTerminationAndTerminate (eNTCP2Message3Error);
return;
}
if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri.GetTimestamp ()) // 2 minutes
{
LogPrint (eLogError, "NTCP2: RouterInfo is from future for ", (ri.GetTimestamp () - ts)/1000LL, " seconds");
SendTerminationAndTerminate (eNTCP2Message3Error);
return;
}
auto addr = m_RemoteEndpoint.address ().is_v4 () ? ri.GetNTCP2V4Address () :
(i2p::util::net::IsYggdrasilAddress (m_RemoteEndpoint.address ()) ? ri.GetYggdrasilAddress () : ri.GetNTCP2V6Address ());
if (!addr || memcmp (m_Establisher->m_RemoteStaticKey, addr->s, 32))
@@ -767,7 +789,7 @@ namespace transport
void NTCP2Session::ServerLogin ()
{
SetTerminationTimeout (NTCP2_ESTABLISH_TIMEOUT);
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
SetLastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ());
m_Establisher->CreateEphemeralKey ();
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
@@ -850,9 +872,8 @@ namespace transport
}
else
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumReceivedBytes += bytes_transferred + 2; // + length
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred);
UpdateNumReceivedBytes (bytes_transferred + 2);
i2p::transport::transports.UpdateReceivedBytes (bytes_transferred + 2);
uint8_t nonce[12];
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
@@ -880,7 +901,7 @@ namespace transport
auto size = bufbe16toh (frame + offset);
offset += 2;
LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size);
if (size > len)
if (offset + size > len)
{
LogPrint (eLogError, "NTCP2: Unexpected block length ", size);
break;
@@ -1073,11 +1094,10 @@ namespace transport
}
else
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumSentBytes += bytes_transferred;
UpdateNumSentBytes (bytes_transferred);
i2p::transport::transports.UpdateSentBytes (bytes_transferred);
LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred);
if (m_LastActivityTimestamp > m_NextRouterInfoResendTime)
if (GetLastActivityTimestamp () > m_NextRouterInfoResendTime)
{
m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL +
rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD;
@@ -1086,7 +1106,7 @@ namespace transport
else
{
SendQueue ();
m_SendQueueSize = m_SendQueue.size ();
SetSendQueueSize (m_SendQueue.size ());
}
}
}
@@ -1209,7 +1229,7 @@ namespace transport
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate ();
}
m_SendQueueSize = m_SendQueue.size ();
SetSendQueueSize (m_SendQueue.size ());
}
void NTCP2Session::SendLocalRouterInfo (bool update)
@@ -1398,7 +1418,8 @@ namespace transport
LogPrint (eLogError, "NTCP2: Can't connect to unspecified address");
return;
}
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ());
LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")");
GetService ().post([this, conn]()
{
if (this->AddNTCP2Session (conn))
@@ -1454,7 +1475,8 @@ namespace transport
}
else
{
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ());
LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (conn->GetRemoteIdentity ()->GetIdentHash ()), ")");
conn->ClientLogin ();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -59,7 +59,7 @@ namespace data
{
Reseed ();
}
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false))
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, false))
Reseed (); // we don't have a router we can connect to. Trying to reseed
auto it = m_RouterInfos.find (i2p::context.GetIdentHash ());
@@ -175,6 +175,7 @@ namespace data
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance) ||
ts + i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT < lastProfilesCleanup)
{
m_RouterProfilesPool.CleanUpMt ();
if (m_PersistProfiles) PersistProfiles ();
DeleteObsoleteProfiles ();
lastProfilesCleanup = ts;
@@ -245,19 +246,20 @@ namespace data
updated = false;
m_Requests.RequestComplete (ident, r);
return r;
}
if (r->IsUnreachable ())
}
if (r->IsUnreachable () ||
i2p::util::GetMillisecondsSinceEpoch () + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < r->GetTimestamp ())
{
// delete router as invalid after update
// delete router as invalid or from future after update
m_RouterInfos.erase (ident);
if (wasFloodfill)
{
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.Remove (r->GetIdentHash ());
}
}
m_Requests.RequestComplete (ident, nullptr);
return nullptr;
}
return nullptr;
}
}
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
@@ -267,7 +269,12 @@ namespace data
if (wasFloodfill)
m_Floodfills.Remove (r->GetIdentHash ());
else if (r->IsEligibleFloodfill ())
m_Floodfills.Insert (r);
{
if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD || r->GetProfile ()->IsReal ())
m_Floodfills.Insert (r);
else
r->ResetFlooldFill ();
}
}
}
else
@@ -292,8 +299,14 @@ namespace data
LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.Insert (r);
if (m_Floodfills.GetSize () < NETDB_NUM_FLOODFILLS_THRESHOLD ||
r->GetProfile ()->IsReal ()) // don't insert floodfill until it's known real if we have enough
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.Insert (r);
}
else
r->ResetFlooldFill ();
}
}
else
@@ -413,13 +426,10 @@ namespace data
if (r)
{
r->SetUnreachable (unreachable);
if (unreachable)
{
auto profile = r->GetProfile ();
if (profile)
profile->Unreachable ();
}
}
auto profile = r->GetProfile ();
if (profile)
profile->Unreachable (unreachable);
}
}
void NetDb::ExcludeReachableTransports (const IdentHash& ident, RouterInfo::CompatibleTransports transports)
@@ -429,9 +439,9 @@ namespace data
{
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
r->ExcludeReachableTransports (transports);
}
}
}
}
void NetDb::Reseed ()
{
if (!m_Reseeder)
@@ -607,7 +617,9 @@ namespace data
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
auto uptime = i2p::context.GetUptime ();
bool isLowRate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () < NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE;
double minTunnelCreationSuccessRate;
i2p::config::GetOption("limits.zombies", minTunnelCreationSuccessRate);
bool isLowRate = i2p::tunnel::tunnels.GetPreciseTunnelCreationSuccessRate () < minTunnelCreationSuccessRate;
// routers don't expire if less than 90 or uptime is less than 1 hour
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
if (checkForExpiration && uptime > 3600) // 1 hour
@@ -617,17 +629,17 @@ namespace data
auto own = i2p::context.GetSharedRouterInfo ();
for (auto& it: m_RouterInfos)
{
if (it.second == own) continue; // skip own
if (!it.second || it.second == own) continue; // skip own
std::string ident = it.second->GetIdentHashBase64();
if (it.second->IsUpdated ())
{
if (it.second->GetBuffer ())
{
{
// we have something to save
it.second->SaveToFile (m_Storage.Path(ident));
it.second->SetUnreachable (false);
it.second->DeleteBuffer ();
}
}
it.second->SetUpdated (false);
updatedCount++;
continue;
@@ -639,20 +651,28 @@ namespace data
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
it.second->SetUnreachable (false);
if (!it.second->IsUnreachable ())
{
{
// find & mark expired routers
if (!it.second->GetCompatibleTransports (true)) // non reachable by any transport
it.second->SetUnreachable (true);
else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout)
it.second->SetUnreachable (true);
else if (ts + NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < it.second->GetTimestamp ())
{
LogPrint (eLogWarning, "NetDb: RouterInfo is from future for ", (it.second->GetTimestamp () - ts)/1000LL, " seconds");
it.second->SetUnreachable (true);
}
else if (checkForExpiration)
{
if (ts > it.second->GetTimestamp () + expirationTimeout)
it.second->SetUnreachable (true);
else if ((ts > it.second->GetTimestamp () + expirationTimeout/2) && // more than half of expiration
total > NETDB_NUM_ROUTERS_THRESHOLD && !it.second->IsHighBandwidth() && // low bandwidth
!it.second->IsFloodfill() && (!i2p::context.IsFloodfill () || // non floodfill
(CreateRoutingKey (it.second->GetIdentHash ()) ^ i2p::context.GetIdentHash ()).metric[0] >= 0x02)) // different first 7 bits
it.second->SetUnreachable (true);
}
if (it.second->IsUnreachable () && i2p::transport::transports.IsConnected (it.second->GetIdentHash ()))
it.second->SetUnreachable (false); // don't expire connected router
}
}
if (it.second->IsUnreachable ())
{
@@ -667,7 +687,7 @@ namespace data
m_RouterInfoBuffersPool.CleanUpMt ();
m_RouterInfoAddressesPool.CleanUpMt ();
m_RouterInfoAddressVectorsPool.CleanUpMt ();
m_IdentitiesPool.CleanUpMt ();
m_IdentitiesPool.CleanUpMt ();
if (updatedCount > 0)
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
@@ -679,13 +699,13 @@ namespace data
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();)
{
if (it->second->IsUnreachable ())
if (!it->second || it->second->IsUnreachable ())
it = m_RouterInfos.erase (it);
else
{
{
it->second->DropProfile ();
it++;
}
}
}
}
// clean up expired floodfills or not floodfills anymore
@@ -722,7 +742,11 @@ namespace data
auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
if (outbound && inbound)
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
{
auto msg = dest->CreateRequestMessage (floodfill, inbound);
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
}
else
{
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
@@ -787,19 +811,22 @@ namespace data
LogPrint (eLogError, "NetDb: Database store msg with reply token is too short ", len, ". Dropped");
return;
}
auto deliveryStatus = CreateDeliveryStatusMsg (replyToken);
uint32_t tunnelID = bufbe32toh (buf + offset);
offset += 4;
if (!tunnelID) // send response directly
transports.SendMessage (buf + offset, deliveryStatus);
else
if (replyToken != 0xFFFFFFFFU) // if not caught on OBEP or IBGW
{
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
if (outbound)
outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus);
auto deliveryStatus = CreateDeliveryStatusMsg (replyToken);
if (!tunnelID) // send response directly
transports.SendMessage (buf + offset, deliveryStatus);
else
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
{
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
if (outbound)
outbound->SendTunnelDataMsgTo (buf + offset, tunnelID, deliveryStatus);
else
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
}
}
offset += 32;
}
@@ -820,7 +847,12 @@ namespace data
LogPrint (eLogError, "NetDb: Database store message is too long ", len);
return;
}
if (!m->from) // unsolicited LS must be received directly
if (!context.IsFloodfill ())
{
LogPrint (eLogInfo, "NetDb: Not Floodfill, LeaseSet store request ignored for ", ident.ToBase32());
return;
}
else if (!m->from) // unsolicited LS must be received directly
{
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
{
@@ -988,6 +1020,11 @@ namespace data
std::shared_ptr<I2NPMessage> replyMsg;
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
{
if (!context.IsFloodfill ())
{
LogPrint (eLogWarning, "NetDb: Exploratory lookup to non-floodfill dropped");
return;
}
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
std::set<IdentHash> excludedRouters;
const uint8_t * excluded_ident = excluded;
@@ -1013,6 +1050,7 @@ namespace data
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
{
// try to find router
auto router = FindRouter (ident);
if (router && !router->IsUnreachable ())
{
@@ -1025,17 +1063,26 @@ namespace data
if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
{
auto leaseSet = FindLeaseSet (ident);
if (!leaseSet)
// try to find leaseset
if (context.IsFloodfill ())
{
auto leaseSet = FindLeaseSet (ident);
if (!leaseSet)
{
// no leaseset found
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
}
else if (!leaseSet->IsExpired ()) // we don't send back expired leasesets
{
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
}
}
else if (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP)
{
// no lease set found
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
}
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
{
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
}
LogPrint (eLogWarning, "NetDb: Explicit LeaseSet lookup to non-floodfill dropped");
return;
}
}
if (!replyMsg)
@@ -1174,15 +1221,17 @@ namespace data
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith,
bool reverse, bool endpoint) const
{
return GetRandomRouter (
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
[compatibleWith, reverse, endpoint](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router != compatibleWith &&
(reverse ? compatibleWith->IsReachableFrom (*router) :
(reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)):
router->IsReachableFrom (*compatibleWith)) &&
router->IsECIES () && !router->IsHighCongestion (false);
router->IsECIES () && !router->IsHighCongestion (false) &&
(!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse)
});
}
@@ -1206,17 +1255,20 @@ namespace data
});
}
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith,
bool reverse, bool endpoint) const
{
return GetRandomRouter (
[compatibleWith, reverse](std::shared_ptr<const RouterInfo> router)->bool
[compatibleWith, reverse, endpoint](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router != compatibleWith &&
(reverse ? compatibleWith->IsReachableFrom (*router) :
(reverse ? (compatibleWith->IsReachableFrom (*router) && router->GetCompatibleTransports (true)) :
router->IsReachableFrom (*compatibleWith)) &&
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION &&
router->IsECIES () && !router->IsHighCongestion (true);
router->IsECIES () && !router->IsHighCongestion (true) &&
(!endpoint || (router->IsV4 () && (!reverse || router->IsPublished (true)))); // endpoint must be ipv4 and published if inbound(reverse)
});
}
@@ -1228,7 +1280,9 @@ namespace data
uint16_t inds[3];
RAND_bytes ((uint8_t *)inds, sizeof (inds));
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
inds[0] %= m_RouterInfos.size ();
auto count = m_RouterInfos.size ();
if(count == 0) return nullptr;
inds[0] %= count;
auto it = m_RouterInfos.begin ();
std::advance (it, inds[0]);
// try random router
@@ -1308,16 +1362,16 @@ namespace data
return r && !r->IsUnreachable () && !r->GetProfile ()->IsUnreachable () &&
!excluded.count (r->GetIdentHash ());
});
}
}
if (v.empty ()) return res;
XORMetric ourMetric;
if (closeThanUsOnly) ourMetric = destKey ^ i2p::context.GetIdentHash ();
for (auto& it: v)
{
if (closeThanUsOnly && ourMetric < (destKey ^ it->GetIdentHash ())) break;
res.push_back (it->GetIdentHash ());
}
}
return res;
}
@@ -1360,10 +1414,10 @@ namespace data
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
for (auto& it: m_RouterInfos)
it.second->UpdateIntroducers (ts);
}
}
SaveUpdated ();
}
}
void NetDb::ManageLeaseSets ()
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();

View File

@@ -38,7 +38,8 @@ namespace data
{
const int NETDB_MIN_ROUTERS = 90;
const int NETDB_MIN_FLOODFILLS = 5;
const int NETDB_MIN_TUNNEL_CREATION_SUCCESS_RATE = 8; // in percents
const int NETDB_NUM_FLOODFILLS_THRESHOLD = 1500;
const int NETDB_NUM_ROUTERS_THRESHOLD = 4*NETDB_NUM_FLOODFILLS_THRESHOLD;
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
@@ -84,8 +85,8 @@ namespace data
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse, bool endpoint) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
@@ -128,6 +129,7 @@ namespace data
};
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
std::shared_ptr<IdentityEx> NewIdentity (const uint8_t * buf, size_t len) { return m_IdentitiesPool.AcquireSharedMt (buf, len); };
std::shared_ptr<RouterProfile> NewRouterProfile () { return m_RouterProfilesPool.AcquireSharedMt (); };
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
@@ -185,6 +187,7 @@ namespace data
i2p::util::MemoryPoolMt<RouterInfo::Addresses> m_RouterInfoAddressVectorsPool;
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
i2p::util::MemoryPoolMt<IdentityEx> m_IdentitiesPool;
i2p::util::MemoryPoolMt<RouterProfile> m_RouterProfilesPool;
};
extern NetDb netdb;

View File

@@ -16,6 +16,7 @@
#include "FS.h"
#include "Log.h"
#include "Timestamp.h"
#include "NetDb.hpp"
#include "Profiling.h"
namespace i2p
@@ -30,12 +31,12 @@ namespace data
{
return boost::posix_time::second_clock::local_time();
}
RouterProfile::RouterProfile ():
m_LastUpdateTime (GetTime ()), m_IsUpdated (false),
m_LastDeclineTime (0), m_LastUnreachableTime (0),
m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
m_NumTimesTaken (0), m_NumTimesRejected (0)
m_NumTimesTaken (0), m_NumTimesRejected (0), m_HasConnected (false)
{
}
@@ -55,6 +56,7 @@ namespace data
boost::property_tree::ptree usage;
usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken);
usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected);
usage.put (PEER_PROFILE_USAGE_CONNECTED, m_HasConnected);
// fill property tree
boost::property_tree::ptree pt;
pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime));
@@ -123,6 +125,7 @@ namespace data
auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE);
m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0);
m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0);
m_HasConnected = usage.get (PEER_PROFILE_USAGE_CONNECTED, false);
}
catch (boost::property_tree::ptree_bad_path& ex)
{
@@ -148,22 +151,30 @@ namespace data
}
else
{
m_NumTunnelsAgreed++;
m_NumTunnelsAgreed++;
m_LastDeclineTime = 0;
}
}
void RouterProfile::TunnelNonReplied ()
{
m_NumTunnelsNonReplied++;
m_NumTunnelsNonReplied++;
UpdateTime ();
if (m_NumTunnelsNonReplied > 2*m_NumTunnelsAgreed && m_NumTunnelsNonReplied > 3)
{
m_LastDeclineTime = i2p::util::GetSecondsSinceEpoch ();
}
}
void RouterProfile::Unreachable ()
void RouterProfile::Unreachable (bool unreachable)
{
m_LastUnreachableTime = i2p::util::GetSecondsSinceEpoch ();
m_LastUnreachableTime = unreachable ? i2p::util::GetSecondsSinceEpoch () : 0;
UpdateTime ();
}
void RouterProfile::Connected ()
{
m_HasConnected = true;
UpdateTime ();
}
@@ -214,6 +225,11 @@ namespace data
return (bool)m_LastUnreachableTime;
}
bool RouterProfile::IsUseful() const
{
return IsReal () || m_NumTunnelsNonReplied >= PEER_PROFILE_USEFUL_THRESHOLD;
}
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash)
{
{
@@ -221,8 +237,8 @@ namespace data
auto it = g_Profiles.find (identHash);
if (it != g_Profiles.end ())
return it->second;
}
auto profile = std::make_shared<RouterProfile> ();
}
auto profile = netdb.NewRouterProfile ();
profile->Load (identHash); // if possible
std::unique_lock<std::mutex> l(g_ProfilesMutex);
g_Profiles.emplace (identHash, profile);
@@ -242,7 +258,7 @@ namespace data
{
std::unique_lock<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{
{
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () > PEER_PROFILE_PERSIST_INTERVAL)
{
if (it->second->IsUpdated ())
@@ -251,11 +267,11 @@ namespace data
}
else
it++;
}
}
}
for (auto& it: tmp)
if (it.second) it.second->Save (it.first);
}
}
void SaveProfiles ()
{
@@ -267,24 +283,24 @@ namespace data
}
auto ts = GetTime ();
for (auto& it: tmp)
if (it.second->IsUpdated () && (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
if (it.second->IsUseful() && (it.second->IsUpdated () || (ts - it.second->GetLastUpdateTime ()).total_seconds () < PEER_PROFILE_EXPIRATION_TIMEOUT*3600))
it.second->Save (it.first);
}
}
void DeleteObsoleteProfiles ()
{
{
auto ts = GetTime ();
std::unique_lock<std::mutex> l(g_ProfilesMutex);
for (auto it = g_Profiles.begin (); it != g_Profiles.end ();)
{
{
if ((ts - it->second->GetLastUpdateTime ()).total_seconds () >= PEER_PROFILE_EXPIRATION_TIMEOUT*3600)
it = g_Profiles.erase (it);
else
it++;
}
}
struct stat st;
std::time_t now = std::time(nullptr);

View File

@@ -28,35 +28,40 @@ namespace data
const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied";
const char PEER_PROFILE_USAGE_TAKEN[] = "taken";
const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
const char PEER_PROFILE_USAGE_CONNECTED[] = "connected";
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 36; // in hours (1.5 days)
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 6 * 3600; // in seconds (6 hours)
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 3 * 3600; // in seconds (3 hours)
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3600; // in seconds (1 hour)
const int PEER_PROFILE_DECLINED_RECENTLY_INTERVAL = 150; // in seconds (2.5 minutes)
const int PEER_PROFILE_PERSIST_INTERVAL = 3300; // in seconds (55 minutes)
const int PEER_PROFILE_UNREACHABLE_INTERVAL = 2*3600; // on seconds (2 hours)
const int PEER_PROFILE_USEFUL_THRESHOLD = 3;
class RouterProfile
{
public:
RouterProfile ();
RouterProfile& operator= (const RouterProfile& ) = default;
void Save (const IdentHash& identHash);
void Load (const IdentHash& identHash);
bool IsBad ();
bool IsUnreachable ();
bool IsReal () const { return m_HasConnected || m_NumTunnelsAgreed > 0 || m_NumTunnelsDeclined > 0; }
void TunnelBuildResponse (uint8_t ret);
void TunnelNonReplied ();
void Unreachable ();
void Unreachable (bool unreachable);
void Connected ();
boost::posix_time::ptime GetLastUpdateTime () const { return m_LastUpdateTime; };
bool IsUpdated () const { return m_IsUpdated; };
bool IsUseful() const;
private:
void UpdateTime ();
@@ -78,6 +83,7 @@ namespace data
// usage
uint32_t m_NumTimesTaken;
uint32_t m_NumTimesRejected;
bool m_HasConnected; // successful trusted(incoming or NTCP2) connection
};
std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);

View File

@@ -31,7 +31,8 @@ namespace i2p
RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID),
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone),
m_Testing (false), m_TestingV6 (false), m_NetID (I2PD_NET_ID),
m_PublishReplyToken (0), m_IsHiddenMode (false)
{
}
@@ -277,8 +278,29 @@ namespace i2p
fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
}
void RouterContext::SetTesting (bool testing)
{
if (testing != m_Testing)
{
m_Testing = testing;
if (m_Testing)
m_Error = eRouterErrorNone;
}
}
void RouterContext::SetTestingV6 (bool testing)
{
if (testing != m_TestingV6)
{
m_TestingV6 = testing;
if (m_TestingV6)
m_ErrorV6 = eRouterErrorNone;
}
}
void RouterContext::SetStatus (RouterStatus status)
{
SetTesting (false);
if (status != m_Status)
{
m_Status = status;
@@ -290,9 +312,6 @@ namespace i2p
case eRouterStatusFirewalled:
SetUnreachable (true, false); // ipv4
break;
case eRouterStatusTesting:
m_Error = eRouterErrorNone;
break;
default:
;
}
@@ -301,6 +320,7 @@ namespace i2p
void RouterContext::SetStatusV6 (RouterStatus status)
{
SetTestingV6 (false);
if (status != m_StatusV6)
{
m_StatusV6 = status;
@@ -312,9 +332,6 @@ namespace i2p
case eRouterStatusFirewalled:
SetUnreachable (false, true); // ipv6
break;
case eRouterStatusTesting:
m_ErrorV6 = eRouterErrorNone;
break;
default:
;
}
@@ -577,15 +594,15 @@ namespace i2p
/* detect parameters */
switch (L)
{
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = 48; type = low; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; break; // 48
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH1 : limit = 64; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = i2p::data::HIGH_BANDWIDTH_LIMIT; type = high; break; // 256
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = i2p::data::EXTRA_BANDWIDTH_LIMIT; type = extra; break; // 2048
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
default:
limit = 48; type = low;
limit = i2p::data::LOW_BANDWIDTH_LIMIT; type = low; // 48
}
/* update caps & flags in RI */
auto caps = m_RouterInfo.GetCaps ();
@@ -1348,8 +1365,12 @@ namespace i2p
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
if (inbound && outbound)
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
{
// encrypt for floodfill
auto msg = CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound);
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0,
i2p::garlic::WrapECIESX25519MessageForRouter (msg, floodfill->GetIdentity ()->GetEncryptionPublicKey ()));
}
else
LogPrint (eLogInfo, "Router: Can't publish our RouterInfo. No tunnles. Try again in ", ROUTER_INFO_CONFIRMATION_TIMEOUT, " seconds");
}

View File

@@ -42,11 +42,10 @@ namespace garlic
enum RouterStatus
{
eRouterStatusOK = 0,
eRouterStatusTesting = 1,
eRouterStatusFirewalled = 2,
eRouterStatusUnknown = 3,
eRouterStatusProxy = 4,
eRouterStatusMesh = 5
eRouterStatusFirewalled = 1,
eRouterStatusUnknown = 2,
eRouterStatusProxy = 3,
eRouterStatusMesh = 4
};
enum RouterError
@@ -121,10 +120,14 @@ namespace garlic
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; };
uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; };
bool GetTesting () const { return m_Testing; };
void SetTesting (bool testing);
RouterStatus GetStatus () const { return m_Status; };
void SetStatus (RouterStatus status);
RouterError GetError () const { return m_Error; };
void SetError (RouterError error) { m_Error = error; };
bool GetTestingV6 () const { return m_TestingV6; };
void SetTestingV6 (bool testing);
RouterStatus GetStatusV6 () const { return m_StatusV6; };
void SetStatusV6 (RouterStatus status);
RouterError GetErrorV6 () const { return m_ErrorV6; };
@@ -231,6 +234,7 @@ namespace garlic
int m_ShareRatio;
RouterStatus m_Status, m_StatusV6;
RouterError m_Error, m_ErrorV6;
bool m_Testing, m_TestingV6;
int m_NetID;
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;
std::unique_ptr<SSU2PrivateKeys> m_SSU2Keys;

View File

@@ -293,7 +293,8 @@ namespace data
else if (!strcmp (key, "s")) // ntcp2 or ssu2 static key
{
Base64ToByteStream (value, strlen (value), address->s, 32);
isStaticKey = true;
if (!(address->s[31] & 0x80)) // check if x25519 public key
isStaticKey = true;
}
else if (!strcmp (key, "i")) // ntcp2 iv or ssu2 intro
{
@@ -362,6 +363,7 @@ namespace data
}
if (!s) return;
}
if (address->transportStyle == eTransportNTCP2)
{
if (isStaticKey)
@@ -387,7 +389,7 @@ namespace data
}
}
}
else if (address->transportStyle == eTransportSSU2 && isV2)
else if (address->transportStyle == eTransportSSU2 && isV2 && isStaticKey)
{
if (address->IsV4 ()) supportedTransports |= eSSU2V4;
if (address->IsV6 ()) supportedTransports |= eSSU2V6;
@@ -483,7 +485,10 @@ namespace data
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value))
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
else
{
LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed");
SetUnreachable (true);
}
}
if (!s) return;
@@ -574,7 +579,7 @@ namespace data
int numValid = 0;
for (auto& it: address->ssu->introducers)
{
if (it.iTag && ts < it.iExp)
if (it.iTag && ts < it.iExp && !it.iH.IsZero ())
numValid++;
else
it.iTag = 0;
@@ -990,6 +995,7 @@ namespace data
bool RouterInfo::IsPublished (bool v4) const
{
if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addreses are not published
auto addr = GetAddresses ();
if (v4)
return ((*addr)[eNTCP2V4Idx] && ((*addr)[eNTCP2V4Idx])->published) ||
@@ -1315,6 +1321,7 @@ namespace data
int i = 0;
for (const auto& introducer: address.ssu->introducers)
{
if (!introducer.iTag) continue;
if (introducer.iExp) // expiration is specified
{
WriteString ("iexp" + boost::lexical_cast<std::string>(i), properties);
@@ -1327,6 +1334,7 @@ namespace data
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
if (!introducer.iTag) continue;
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
char value[64];
@@ -1339,6 +1347,7 @@ namespace data
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
if (!introducer.iTag) continue;
WriteString ("itag" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
WriteString (boost::lexical_cast<std::string>(introducer.iTag), properties);

View File

@@ -42,8 +42,12 @@ namespace data
const char CAPS_FLAG_HIGH_BANDWIDTH1 = 'M'; /* 48-64 KBps */
const char CAPS_FLAG_HIGH_BANDWIDTH2 = 'N'; /* 64-128 KBps */
const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2048 KBps */
const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2048 KBps */
// bandwidth limits in kBps
const uint32_t LOW_BANDWIDTH_LIMIT = 48;
const uint32_t HIGH_BANDWIDTH_LIMIT = 256;
const uint32_t EXTRA_BANDWIDTH_LIMIT = 2048;
// congesion flags
const char CAPS_FLAG_MEDIUM_CONGESTION = 'D';
const char CAPS_FLAG_HIGH_CONGESTION = 'E';
@@ -125,7 +129,7 @@ namespace data
struct Introducer
{
Introducer (): iTag (0), iExp (0) {};
Introducer (): iTag (0), iExp (0) { iH.Fill(0); };
IdentHash iH;
uint32_t iTag;
uint32_t iExp;
@@ -224,6 +228,7 @@ namespace data
void UpdateSupportedTransports ();
void UpdateIntroducers (uint64_t ts); // ts in seconds
bool IsFloodfill () const { return m_Caps & Caps::eFloodfill; };
void ResetFlooldFill () { m_Caps &= ~Caps::eFloodfill; };
bool IsECIES () const { return m_RouterIdentity->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; };
bool IsNTCP2 (bool v4only = true) const;
bool IsNTCP2V6 () const { return m_SupportedTransports & eNTCP2V6; };

View File

@@ -24,7 +24,8 @@ namespace transport
m_AddressV4 (boost::asio::ip::address_v4()), m_AddressV6 (boost::asio::ip::address_v6()),
m_TerminationTimer (GetService ()), m_CleanupTimer (GetService ()), m_ResendTimer (GetService ()),
m_IntroducersUpdateTimer (GetService ()), m_IntroducersUpdateTimerV6 (GetService ()),
m_IsPublished (true), m_IsSyncClockFromPeers (true), m_IsThroughProxy (false)
m_IsPublished (true), m_IsSyncClockFromPeers (true), m_PendingTimeOffset (0),
m_IsThroughProxy (false)
{
}
@@ -78,6 +79,7 @@ namespace transport
if (address->IsV4 ())
{
found = true;
LogPrint (eLogDebug, "SSU2: Opening IPv4 socket at Start");
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV4, port));
m_ReceiveService.GetService ().post(
[this]()
@@ -89,6 +91,7 @@ namespace transport
if (address->IsV6 ())
{
found = true;
LogPrint (eLogDebug, "SSU2: Opening IPv6 socket at Start");
OpenSocket (boost::asio::ip::udp::endpoint (m_AddressV6, port));
m_ReceiveService.GetService ().post(
[this]()
@@ -207,6 +210,29 @@ namespace transport
return ep.port ();
}
void SSU2Server::AdjustTimeOffset (int64_t offset)
{
if (offset)
{
if (m_PendingTimeOffset) // one more
{
if (std::abs (m_PendingTimeOffset - offset) < SSU2_CLOCK_SKEW)
{
offset = (m_PendingTimeOffset + offset)/2; // average
LogPrint (eLogWarning, "SSU2: Clock adjusted by ", offset, " seconds");
i2p::util::AdjustTimeOffset (offset);
}
else
LogPrint (eLogWarning, "SSU2: Time offsets are too different. Clock not adjusted");
m_PendingTimeOffset = 0;
}
else
m_PendingTimeOffset = offset; // first
}
else
m_PendingTimeOffset = 0; // reset
}
boost::asio::ip::udp::socket& SSU2Server::OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint)
{
boost::asio::ip::udp::socket& socket = localEndpoint.address ().is_v6 () ? m_SocketV6 : m_SocketV4;
@@ -243,10 +269,12 @@ namespace transport
if (!ecode
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::WSAENETRESET_ // 10052
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
#endif
@@ -303,7 +331,7 @@ namespace transport
else
{
auto ep = socket.local_endpoint ();
socket.close ();
LogPrint (eLogCritical, "SSU2: Reopening socket in HandleReceivedFrom: code ", ecode.value(), ": ", ecode.message ());
OpenSocket (ep);
Receive (socket);
}
@@ -558,16 +586,25 @@ namespace transport
SendThroughProxy (header, headerLen, nullptr, 0, payload, payloadLen, to);
return;
}
std::vector<boost::asio::const_buffer> bufs
{
boost::asio::buffer (header, headerLen),
boost::asio::buffer (payload, payloadLen)
};
boost::system::error_code ec;
if (to.address ().is_v6 ())
{
if (!m_SocketV6.is_open ()) return;
m_SocketV6.send_to (bufs, to, 0, ec);
}
else
{
if (!m_SocketV4.is_open ()) return;
m_SocketV4.send_to (bufs, to, 0, ec);
}
if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + payloadLen);
else
@@ -582,17 +619,25 @@ namespace transport
SendThroughProxy (header, headerLen, headerX, headerXLen, payload, payloadLen, to);
return;
}
std::vector<boost::asio::const_buffer> bufs
{
boost::asio::buffer (header, headerLen),
boost::asio::buffer (headerX, headerXLen),
boost::asio::buffer (payload, payloadLen)
};
boost::system::error_code ec;
if (to.address ().is_v6 ())
{
if (!m_SocketV6.is_open ()) return;
m_SocketV6.send_to (bufs, to, 0, ec);
}
else
{
if (!m_SocketV4.is_open ()) return;
m_SocketV4.send_to (bufs, to, 0, ec);
}
if (!ec)
i2p::transport::transports.UpdateSentBytes (headerLen + headerXLen + payloadLen);
@@ -962,7 +1007,7 @@ namespace transport
void SSU2Server::UpdateIntroducers (bool v4)
{
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
std::list<i2p::data::IdentHash> newList;
std::list<i2p::data::IdentHash> newList, impliedList;
auto& introducers = v4 ? m_Introducers : m_IntroducersV6;
std::set<i2p::data::IdentHash> excluded;
for (const auto& it : introducers)
@@ -974,12 +1019,19 @@ namespace transport
session = it1->second;
excluded.insert (it);
}
if (session && session->IsEstablished ())
if (session && session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ()) // still session with introducer?
{
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION)
{
session->SendKeepAlive ();
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION)
newList.push_back (it);
if (ts < session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION)
newList.push_back (it);
else
{
impliedList.push_back (it); // keep in introducers list, but not publish
session = nullptr;
}
}
else
session = nullptr;
}
@@ -993,20 +1045,18 @@ namespace transport
{
// bump creation time for previous introducers if no new sessions found
LogPrint (eLogDebug, "SSU2: No new introducers found. Trying to reuse existing");
impliedList.clear ();
for (auto& it : introducers)
{
auto it1 = m_SessionsByRouterHash.find (it);
if (it1 != m_SessionsByRouterHash.end ())
{
auto session = it1->second;
if (session->IsEstablished ())
if (session->IsEstablished () && session->GetRelayTag () && session->IsOutgoing ())
{
session->SetCreationTime (session->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_DURATION);
if (std::find (newList.begin (), newList.end (), it) == newList.end ())
{
newList.push_back (it);
sessions.push_back (session);
}
}
}
}
@@ -1014,10 +1064,14 @@ namespace transport
for (const auto& it : sessions)
{
uint32_t tag = it->GetRelayTag ();
uint32_t exp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION;
if (!tag || ts + SSU2_TO_INTRODUCER_SESSION_DURATION/2 > exp)
continue; // don't pick too old session for introducer
i2p::data::RouterInfo::Introducer introducer;
introducer.iTag = it->GetRelayTag ();
introducer.iTag = tag;
introducer.iH = it->GetRemoteIdentity ()->GetIdentHash ();
introducer.iExp = it->GetCreationTime () + SSU2_TO_INTRODUCER_SESSION_EXPIRATION;
introducer.iExp = exp;
excluded.insert (it->GetRemoteIdentity ()->GetIdentHash ());
if (i2p::context.AddSSU2Introducer (introducer, v4))
{
@@ -1051,13 +1105,15 @@ namespace transport
}
}
}
introducers.splice (introducers.end (), impliedList); // insert non-published, but non-expired introducers back
}
void SSU2Server::ScheduleIntroducersUpdateTimer ()
{
if (m_IsPublished)
{
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(
SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, true));
}
@@ -1070,7 +1126,8 @@ namespace transport
m_IntroducersUpdateTimer.cancel ();
i2p::context.ClearSSU2Introducers (true);
m_Introducers.clear ();
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(
(SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2));
m_IntroducersUpdateTimer.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, true));
}
@@ -1080,7 +1137,8 @@ namespace transport
{
if (m_IsPublished)
{
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL));
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(
SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false));
}
@@ -1093,7 +1151,8 @@ namespace transport
m_IntroducersUpdateTimerV6.cancel ();
i2p::context.ClearSSU2Introducers (false);
m_IntroducersV6.clear ();
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(SSU2_KEEP_ALIVE_INTERVAL/2));
m_IntroducersUpdateTimerV6.expires_from_now (boost::posix_time::seconds(
(SSU2_KEEP_ALIVE_INTERVAL + rand () % SSU2_KEEP_ALIVE_INTERVAL_VARIANCE)/2));
m_IntroducersUpdateTimerV6.async_wait (std::bind (&SSU2Server::HandleIntroducersUpdateTimer,
this, std::placeholders::_1, false));
}
@@ -1106,7 +1165,7 @@ namespace transport
// timeout expired
if (v4)
{
if (i2p::context.GetStatus () == eRouterStatusTesting)
if (i2p::context.GetTesting ())
{
// we still don't know if we need introducers
ScheduleIntroducersUpdateTimer ();
@@ -1129,7 +1188,7 @@ namespace transport
}
else
{
if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
if (i2p::context.GetTestingV6 ())
{
// we still don't know if we need introducers
ScheduleIntroducersUpdateTimerV6 ();

View File

@@ -29,7 +29,8 @@ namespace transport
const size_t SSU2_MAX_NUM_INTRODUCERS = 3;
const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds
const int SSU2_KEEP_ALIVE_INTERVAL = 15; // in seconds
const int SSU2_KEEP_ALIVE_INTERVAL_VARIANCE = 4; // in seconds
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
class SSU2Server: private i2p::util::RunnableServiceWithWork
@@ -65,6 +66,7 @@ namespace transport
bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const;
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
void AdjustTimeOffset (int64_t offset);
void AddSession (std::shared_ptr<SSU2Session> session);
void RemoveSession (uint64_t connID);
@@ -160,6 +162,7 @@ namespace transport
std::shared_ptr<SSU2Session> m_LastSession;
bool m_IsPublished; // if we maintain introducers
bool m_IsSyncClockFromPeers;
int64_t m_PendingTimeOffset; // during peer test
// proxy
bool m_IsThroughProxy;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2023, The PurpleI2P Project
* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -114,6 +114,8 @@ namespace transport
{
if (m_State == eSSU2SessionStateUnknown || m_State == eSSU2SessionStateTokenReceived)
{
LogPrint(eLogDebug, "SSU2: Connecting to ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ")");
ScheduleConnectTimer ();
auto token = m_Server.FindOutgoingToken (m_RemoteEndpoint);
if (token)
@@ -243,7 +245,7 @@ namespace transport
if (IsEstablished ())
{
uint8_t payload[20];
size_t payloadSize = CreatePaddingBlock (payload, 20, 5);
size_t payloadSize = CreatePaddingBlock (payload, 20, 8);
SendData (payload, payloadSize);
}
}
@@ -261,7 +263,7 @@ namespace transport
m_SessionConfirmedFragment.reset (nullptr);
m_PathChallenge.reset (nullptr);
m_SendQueue.clear ();
m_SendQueueSize = 0;
SetSendQueueSize (0);
m_SentPackets.clear ();
m_IncompleteMessages.clear ();
m_RelaySessions.clear ();
@@ -269,7 +271,16 @@ namespace transport
m_ReceivedI2NPMsgIDs.clear ();
m_Server.RemoveSession (m_SourceConnID);
transports.PeerDisconnected (shared_from_this ());
LogPrint (eLogDebug, "SSU2: Session terminated");
auto remoteIdentity = GetRemoteIdentity ();
if (remoteIdentity)
{
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") terminated");
}
else
{
LogPrint (eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (), " terminated");
}
}
}
@@ -298,6 +309,8 @@ namespace transport
m_OnEstablished ();
m_OnEstablished = nullptr;
}
LogPrint(eLogDebug, "SSU2: Session with ", GetRemoteEndpoint (),
" (", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()), ") established");
}
void SSU2Session::Done ()
@@ -351,7 +364,7 @@ namespace transport
RequestTermination (eSSU2TerminationReasonTimeout);
}
}
m_SendQueueSize = m_SendQueue.size ();
SetSendQueueSize (m_SendQueue.size ());
}
bool SSU2Session::SendQueue ()
@@ -511,7 +524,7 @@ namespace transport
LogPrint (eLogInfo, "SSU2: Packet was not Acked after ", it->second->numResends, " attempts. Terminate session");
m_SentPackets.clear ();
m_SendQueue.clear ();
m_SendQueueSize = 0;
SetSendQueueSize (0);
RequestTermination (eSSU2TerminationReasonTimeout);
return resentPackets.size ();
}
@@ -809,6 +822,8 @@ namespace transport
m_NoiseState->m_CK + 32, nonce, decryptedPayload.data (), decryptedPayload.size (), false))
{
LogPrint (eLogWarning, "SSU2: SessionCreated AEAD verification failed ");
if (GetRemoteIdentity ())
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true); // assume wrong s key
return false;
}
m_NoiseState->MixHash (payload, len - 64); // h = SHA256(h || encrypted payload from SessionCreated) for SessionConfirmed
@@ -1051,6 +1066,17 @@ namespace transport
LogPrint (eLogError, "SSU2: SessionConfirmed malformed RouterInfo block");
return false;
}
auto ts = i2p::util::GetMillisecondsSinceEpoch();
if (ts > ri->GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes
{
LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is too old for ", (ts - ri->GetTimestamp ())/1000LL, " seconds");
return false;
}
if (ts + i2p::data::NETDB_EXPIRATION_TIMEOUT_THRESHOLD*1000LL < ri->GetTimestamp ()) // 2 minutes
{
LogPrint (eLogError, "SSU2: RouterInfo in SessionConfirmed is from future for ", (ri->GetTimestamp () - ts)/1000LL, " seconds");
return false;
}
m_Address = m_RemoteEndpoint.address ().is_v6 () ? ri->GetSSU2V6Address () : ri->GetSSU2V4Address ();
if (!m_Address || memcmp (S, m_Address->s, 32))
{
@@ -1426,8 +1452,7 @@ namespace transport
header.ll[1] ^= CreateHeaderMask (m_KeyDataSend + 32, payload + (len + 4));
m_Server.Send (header.buf, 16, payload, len + 16, m_RemoteEndpoint);
m_SendPacketNum++;
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumSentBytes += len + 32;
UpdateNumSentBytes (len + 32);
return m_SendPacketNum - 1;
}
@@ -1468,8 +1493,7 @@ namespace transport
LogPrint (eLogWarning, "SSU2: Data AEAD verification failed ");
return;
}
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumReceivedBytes += len;
UpdateNumReceivedBytes (len);
if (!packetNum || UpdateReceivePacketNum (packetNum))
HandlePayload (payload, payloadSize);
}
@@ -1484,7 +1508,7 @@ namespace transport
auto size = bufbe16toh (buf + offset);
offset += 2;
LogPrint (eLogDebug, "SSU2: Block type ", (int)blk, " of size ", size);
if (size > len)
if (offset + size > len)
{
LogPrint (eLogError, "SSU2: Unexpected block length ", size);
break;
@@ -1530,16 +1554,21 @@ namespace transport
break;
case eSSU2BlkTermination:
{
uint8_t rsn = buf[11]; // reason
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
RequestTermination (eSSU2TerminationReasonTerminationReceived);
else if (m_State != eSSU2SessionStateTerminated)
if (size >= 9)
{
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
m_State = eSSU2SessionStateClosingConfirmed;
Done ();
uint8_t rsn = buf[offset + 8]; // reason
LogPrint (eLogDebug, "SSU2: Termination reason=", (int)rsn);
if (IsEstablished () && rsn != eSSU2TerminationReasonTerminationReceived)
RequestTermination (eSSU2TerminationReasonTerminationReceived);
else if (m_State != eSSU2SessionStateTerminated)
{
if (m_State == eSSU2SessionStateClosing && rsn == eSSU2TerminationReasonTerminationReceived)
m_State = eSSU2SessionStateClosingConfirmed;
Done ();
}
}
else
LogPrint(eLogWarning, "SSU2: Unexpected termination block size ", size);
break;
}
case eSSU2BlkRelayRequest:
@@ -1633,16 +1662,18 @@ namespace transport
break;
case eSSU2SessionStateSessionCreatedReceived:
case eSSU2SessionStateTokenReceived:
if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetStatus () == eRouterStatusTesting) ||
(m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusTesting))
if ((m_RemoteEndpoint.address ().is_v4 () && i2p::context.GetTesting ()) ||
(m_RemoteEndpoint.address ().is_v6 () && i2p::context.GetTestingV6 ()))
{
if (m_Server.IsSyncClockFromPeers ())
{
if (std::abs (offset) > SSU2_CLOCK_THRESHOLD)
{
LogPrint (eLogWarning, "SSU2: Clock adjusted by ", -offset, " seconds");
i2p::util::AdjustTimeOffset (-offset);
}
{
LogPrint (eLogWarning, "SSU2: Time offset ", offset, " from ", m_RemoteEndpoint);
m_Server.AdjustTimeOffset (-offset);
}
else
m_Server.AdjustTimeOffset (0);
}
else if (std::abs (offset) > SSU2_CLOCK_SKEW)
{
@@ -1732,14 +1763,14 @@ namespace transport
LogPrint (eLogInfo, "SSU2: Our port ", ep.port (), " received from ", m_RemoteEndpoint, " is different from ", m_Server.GetPort (isV4));
if (isV4)
{
if (i2p::context.GetStatus () == eRouterStatusTesting)
if (i2p::context.GetTesting ())
i2p::context.SetError (eRouterErrorSymmetricNAT);
else if (m_State == eSSU2SessionStatePeerTest)
i2p::context.SetError (eRouterErrorFullConeNAT);
}
else
{
if (i2p::context.GetStatusV6 () == eRouterStatusTesting)
if (i2p::context.GetTestingV6 ())
i2p::context.SetErrorV6 (eRouterErrorSymmetricNAT);
else if (m_State == eSSU2SessionStatePeerTest)
i2p::context.SetErrorV6 (eRouterErrorFullConeNAT);
@@ -2212,7 +2243,7 @@ namespace transport
if (buf[1] == eSSU2PeerTestCodeAccept)
{
if (GetRouterStatus () == eRouterStatusUnknown)
SetRouterStatus (eRouterStatusTesting);
SetTestingState (true);
auto r = i2p::data::netdb.FindRouter (buf + 3); // find Charlie
if (r && it->second.first)
{
@@ -2238,13 +2269,17 @@ namespace transport
}
else
{
if (GetRouterStatus () == eRouterStatusTesting)
if (GetTestingState ())
{
SetRouterStatus (eRouterStatusFirewalled);
if (m_Address->IsV4 ())
m_Server.RescheduleIntroducersUpdateTimer ();
else
m_Server.RescheduleIntroducersUpdateTimerV6 ();
SetTestingState (false);
if (GetRouterStatus () != eRouterStatusFirewalled)
{
SetRouterStatus (eRouterStatusFirewalled);
if (m_Address->IsV4 ())
m_Server.RescheduleIntroducersUpdateTimer ();
else
m_Server.RescheduleIntroducersUpdateTimerV6 ();
}
}
}
LogPrint (eLogDebug, "SSU2: Peer test 4 received from ", i2p::data::GetIdentHashAbbreviation (GetRemoteIdentity ()->GetIdentHash ()),
@@ -2273,7 +2308,7 @@ namespace transport
{
LogPrint (eLogInfo, "SSU2: Peer test 4 error code ", (int)buf[1], " from ",
i2p::data::GetIdentHashAbbreviation (buf[1] < 64 ? GetRemoteIdentity ()->GetIdentHash () : i2p::data::IdentHash (buf + 3)));
if (GetRouterStatus () == eRouterStatusTesting)
if (GetTestingState ())
SetRouterStatus (eRouterStatusUnknown);
it->second.first->Done ();
}
@@ -2322,7 +2357,7 @@ namespace transport
if (!msg->IsExpired ())
{
// m_LastActivityTimestamp is updated in ProcessData before
if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)m_LastActivityTimestamp).second)
if (m_ReceivedI2NPMsgIDs.emplace (msgID, (uint32_t)GetLastActivityTimestamp ()).second)
m_Handler.PutNextMessage (std::move (msg));
else
LogPrint (eLogDebug, "SSU2: Message ", msgID, " already received");
@@ -2427,6 +2462,31 @@ namespace transport
}
}
bool SSU2Session::GetTestingState () const
{
if (m_Address)
{
if (m_Address->IsV4 ())
return i2p::context.GetTesting ();
if (m_Address->IsV6 ())
return i2p::context.GetTestingV6 ();
}
return false;
}
void SSU2Session::SetTestingState (bool testing) const
{
if (m_Address)
{
if (m_Address->IsV4 ())
i2p::context.SetTesting (testing);
else if (m_Address->IsV6 ())
i2p::context.SetTestingV6 (testing);
}
if (!testing)
m_Server.AdjustTimeOffset (0); // reset time offset when testing is over
}
size_t SSU2Session::CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep)
{
if (len < 9) return 0;
@@ -2839,7 +2899,7 @@ namespace transport
void SSU2Session::SendPathResponse (const uint8_t * data, size_t len)
{
if (len < 8 || len > m_MaxPayloadSize - 3)
if (len > m_MaxPayloadSize - 3)
{
LogPrint (eLogWarning, "SSU2: Incorrect data size for path response ", len);
return;
@@ -2848,7 +2908,10 @@ namespace transport
payload[0] = eSSU2BlkPathResponse;
htobe16buf (payload + 1, len);
memcpy (payload + 3, data, len);
SendData (payload, len + 3);
size_t payloadSize = len + 3;
if (payloadSize < m_MaxPayloadSize)
payloadSize += CreatePaddingBlock (payload + payloadSize, m_MaxPayloadSize - payloadSize, payloadSize < 8 ? 8 : 0);
SendData (payload, payloadSize);
}
void SSU2Session::SendPathChallenge ()
@@ -2866,7 +2929,7 @@ namespace transport
}
len += 3;
if (len < m_MaxPayloadSize)
len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len);
len += CreatePaddingBlock (payload + len, m_MaxPayloadSize - len, len < 8 ? 8 : 0);
SendData (payload, len);
}
@@ -2882,7 +2945,7 @@ namespace transport
else
++it;
}
if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > m_LastActivityTimestamp + SSU2_DECAY_INTERVAL)
if (m_ReceivedI2NPMsgIDs.size () > SSU2_MAX_NUM_RECEIVED_I2NP_MSGIDS || ts > GetLastActivityTimestamp () + SSU2_DECAY_INTERVAL)
// decay
m_ReceivedI2NPMsgIDs.clear ();
else
@@ -2954,7 +3017,7 @@ namespace transport
{
bool sent = SendQueue (); // if we have something to send
if (sent)
m_SendQueueSize = m_SendQueue.size ();
SetSendQueueSize (m_SendQueue.size ());
if (m_IsDataReceived)
{
if (!sent) SendQuickAck ();

View File

@@ -308,6 +308,8 @@ namespace transport
void AdjustMaxPayloadSize ();
RouterStatus GetRouterStatus () const;
void SetRouterStatus (RouterStatus status) const;
bool GetTestingState () const;
void SetTestingState(bool testing) const;
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -15,26 +15,35 @@ namespace i2p
namespace crypto
{
#if OPENSSL_EDDSA
EDDSA25519Verifier::EDDSA25519Verifier ()
EDDSA25519Verifier::EDDSA25519Verifier ():
m_Pkey (nullptr)
{
m_MDCtx = EVP_MD_CTX_create ();
}
EDDSA25519Verifier::~EDDSA25519Verifier ()
{
EVP_MD_CTX_destroy (m_MDCtx);
EVP_PKEY_free (m_Pkey);
}
void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey)
{
EVP_PKEY * pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, pkey);
EVP_PKEY_free (pkey);
if (m_Pkey) EVP_PKEY_free (m_Pkey);
m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
}
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{
return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len);
if (m_Pkey)
{
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
EVP_DigestVerifyInit (ctx, NULL, NULL, NULL, m_Pkey);
auto ret = EVP_DigestVerify (ctx, signature, 64, buf, len);
EVP_MD_CTX_destroy (ctx);
return ret;
}
else
LogPrint (eLogError, "EdDSA verification key is not set");
return false;
}
#else
@@ -99,41 +108,45 @@ namespace crypto
#if OPENSSL_EDDSA
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
m_MDCtx (nullptr), m_Fallback (nullptr)
m_Pkey (nullptr), m_Fallback (nullptr)
{
EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
EVP_PKEY_get_raw_public_key (pkey, publicKey, &len);
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
{
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
EVP_PKEY_free (m_Pkey);
m_Pkey = nullptr;
}
else
{
m_MDCtx = EVP_MD_CTX_create ();
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, pkey);
}
EVP_PKEY_free (pkey);
}
EDDSA25519Signer::~EDDSA25519Signer ()
{
if (m_Fallback) delete m_Fallback;
EVP_MD_CTX_destroy (m_MDCtx);
if (m_Pkey) EVP_PKEY_free (m_Pkey);
}
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
{
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
else
if (m_Fallback)
return m_Fallback->Sign (buf, len, signature);
else if (m_Pkey)
{
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
size_t l = 64;
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
EVP_DigestSignInit (ctx, NULL, NULL, NULL, m_Pkey);
if (!EVP_DigestSign (ctx, sig, &l, buf, len))
LogPrint (eLogError, "EdDSA signing failed");
memcpy (signature, sig, 64);
EVP_MD_CTX_destroy (ctx);
}
else
LogPrint (eLogError, "EdDSA signing key is not set");
}
#endif
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -304,7 +304,7 @@ namespace crypto
private:
#if OPENSSL_EDDSA
EVP_MD_CTX * m_MDCtx;
EVP_PKEY * m_Pkey;
#else
EDDSAPoint m_PublicKey;
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
@@ -341,7 +341,7 @@ namespace crypto
private:
EVP_MD_CTX * m_MDCtx;
EVP_PKEY * m_Pkey;
EDDSA25519SignerCompat * m_Fallback;
};
#else

View File

@@ -19,11 +19,6 @@ namespace i2p
{
namespace stream
{
void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler)
{
Add (std::make_shared<SendBuffer>(buf, len, handler));
}
void SendBufferQueue::Add (std::shared_ptr<SendBuffer> buf)
{
if (buf)
@@ -115,10 +110,7 @@ namespace stream
void Stream::CleanUp ()
{
{
std::unique_lock<std::mutex> l(m_SendBufferMutex);
m_SendBuffer.CleanUp ();
}
m_SendBuffer.CleanUp ();
while (!m_ReceiveQueue.empty ())
{
auto packet = m_ReceiveQueue.front ();
@@ -532,14 +524,18 @@ namespace stream
void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler)
{
std::shared_ptr<i2p::stream::SendBuffer> buffer;
if (len > 0 && buf)
{
std::unique_lock<std::mutex> l(m_SendBufferMutex);
m_SendBuffer.Add (buf, len, handler);
}
buffer = std::make_shared<i2p::stream::SendBuffer>(buf, len, handler);
else if (handler)
handler(boost::system::error_code ());
m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
auto s = shared_from_this ();
m_Service.post ([s, buffer]()
{
if (buffer)
s->m_SendBuffer.Add (buffer);
s->SendBuffer ();
});
}
void Stream::SendBuffer ()
@@ -549,91 +545,88 @@ namespace stream
bool isNoAck = m_LastReceivedSequenceNumber < 0; // first packet
std::vector<Packet *> packets;
while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0))
{
std::unique_lock<std::mutex> l(m_SendBufferMutex);
while ((m_Status == eStreamStatusNew) || (IsEstablished () && !m_SendBuffer.IsEmpty () && numMsgs > 0))
Packet * p = m_LocalDestination.NewPacket ();
uint8_t * packet = p->GetBuffer ();
// TODO: implement setters
size_t size = 0;
htobe32buf (packet + size, m_SendStreamID);
size += 4; // sendStreamID
htobe32buf (packet + size, m_RecvStreamID);
size += 4; // receiveStreamID
htobe32buf (packet + size, m_SequenceNumber++);
size += 4; // sequenceNum
if (isNoAck)
htobuf32 (packet + size, 0);
else
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
size += 4; // ack Through
if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity)
{
Packet * p = m_LocalDestination.NewPacket ();
uint8_t * packet = p->GetBuffer ();
// TODO: implement setters
size_t size = 0;
htobe32buf (packet + size, m_SendStreamID);
size += 4; // sendStreamID
htobe32buf (packet + size, m_RecvStreamID);
size += 4; // receiveStreamID
htobe32buf (packet + size, m_SequenceNumber++);
size += 4; // sequenceNum
if (isNoAck)
htobuf32 (packet + size, 0);
else
htobe32buf (packet + size, m_LastReceivedSequenceNumber);
size += 4; // ack Through
if (m_Status == eStreamStatusNew && !m_SendStreamID && m_RemoteIdentity)
{
// first SYN packet
packet[size] = 8;
size++; // NACK count
memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32);
size += 32;
}
else
{
packet[size] = 0;
size++; // NACK count
}
packet[size] = m_RTO/1000;
size++; // resend delay
if (m_Status == eStreamStatusNew)
{
// initial packet
m_Status = eStreamStatusOpen;
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
if (m_RemoteLeaseSet)
{
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
}
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature ();
if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE;
htobe16buf (packet + size, flags);
size += 2; // flags
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
uint8_t * optionsSize = packet + size; // set options size later
size += 2; // options size
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
size += identityLen; // from
htobe16buf (packet + size, m_MTU);
size += 2; // max packet size
if (isOfflineSignature)
{
const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature ();
memcpy (packet + size, offlineSignature.data (), offlineSignature.size ());
size += offlineSignature.size (); // offline signature
}
uint8_t * signature = packet + size; // set it later
memset (signature, 0, signatureLen); // zeroes for now
size += signatureLen; // signature
htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size
size += m_SendBuffer.Get (packet + size, m_MTU); // payload
m_LocalDestination.GetOwner ()->Sign (packet, size, signature);
}
else
{
// follow on packet
htobuf16 (packet + size, 0);
size += 2; // flags
htobuf16 (packet + size, 0); // no options
size += 2; // options size
size += m_SendBuffer.Get(packet + size, m_MTU); // payload
}
p->len = size;
packets.push_back (p);
numMsgs--;
// first SYN packet
packet[size] = 8;
size++; // NACK count
memcpy (packet + size, m_RemoteIdentity->GetIdentHash (), 32);
size += 32;
}
else
{
packet[size] = 0;
size++; // NACK count
}
packet[size] = m_RTO/1000;
size++; // resend delay
if (m_Status == eStreamStatusNew)
{
// initial packet
m_Status = eStreamStatusOpen;
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
if (m_RemoteLeaseSet)
{
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
}
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
bool isOfflineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().IsOfflineSignature ();
if (isOfflineSignature) flags |= PACKET_FLAG_OFFLINE_SIGNATURE;
htobe16buf (packet + size, flags);
size += 2; // flags
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
uint8_t * optionsSize = packet + size; // set options size later
size += 2; // options size
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
size += identityLen; // from
htobe16buf (packet + size, m_MTU);
size += 2; // max packet size
if (isOfflineSignature)
{
const auto& offlineSignature = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetOfflineSignature ();
memcpy (packet + size, offlineSignature.data (), offlineSignature.size ());
size += offlineSignature.size (); // offline signature
}
uint8_t * signature = packet + size; // set it later
memset (signature, 0, signatureLen); // zeroes for now
size += signatureLen; // signature
htobe16buf (optionsSize, packet + size - 2 - optionsSize); // actual options size
size += m_SendBuffer.Get (packet + size, m_MTU); // payload
m_LocalDestination.GetOwner ()->Sign (packet, size, signature);
}
else
{
// follow on packet
htobuf16 (packet + size, 0);
size += 2; // flags
htobuf16 (packet + size, 0); // no options
size += 2; // options size
size += m_SendBuffer.Get(packet + size, m_MTU); // payload
}
p->len = size;
packets.push_back (p);
numMsgs--;
}
if (packets.size () > 0)
{

View File

@@ -135,7 +135,6 @@ namespace stream
SendBufferQueue (): m_Size (0) {};
~SendBufferQueue () { CleanUp (); };
void Add (const uint8_t * buf, size_t len, SendHandler handler);
void Add (std::shared_ptr<SendBuffer> buf);
size_t Get (uint8_t * buf, size_t len);
size_t GetSize () const { return m_Size; };
@@ -251,7 +250,6 @@ namespace stream
size_t m_NumSentBytes, m_NumReceivedBytes;
uint16_t m_Port;
std::mutex m_SendBufferMutex;
SendBufferQueue m_SendBuffer;
int m_WindowSize, m_RTT, m_RTO, m_AckDelay;
uint64_t m_LastWindowSizeIncreaseTime;

View File

@@ -71,15 +71,17 @@ namespace transport
const int64_t TRANSPORT_SESSION_SLOWNESS_THRESHOLD = 500; // in milliseconds
const int64_t TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL = 10000; // in milliseconds
const uint64_t TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL = 5; // in seconds
class TransportSession
{
public:
TransportSession (std::shared_ptr<const i2p::data::RouterInfo> router, int terminationTimeout):
m_NumSentBytes (0), m_NumReceivedBytes (0), m_SendQueueSize (0),
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout),
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()),
m_HandshakeInterval (0)
m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_HandshakeInterval (0),
m_SendQueueSize (0), m_NumSentBytes (0), m_NumReceivedBytes (0),
m_LastBandWidthUpdateNumSentBytes (0), m_LastBandWidthUpdateNumReceivedBytes (0),
m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()),
m_LastBandwidthUpdateTimestamp (m_LastActivityTimestamp), m_InBandwidth (0), m_OutBandwidth (0)
{
if (router)
m_RemoteIdentity = router->GetRouterIdentity ();
@@ -103,11 +105,29 @@ namespace transport
}
size_t GetNumSentBytes () const { return m_NumSentBytes; };
void UpdateNumSentBytes (size_t len)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumSentBytes += len;
UpdateBandwidth ();
}
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
void UpdateNumReceivedBytes (size_t len)
{
m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch ();
m_NumReceivedBytes += len;
UpdateBandwidth ();
}
size_t GetSendQueueSize () const { return m_SendQueueSize; };
void SetSendQueueSize (size_t s) { m_SendQueueSize = s; };
bool IsOutgoing () const { return m_IsOutgoing; };
bool IsSlow () const { return m_HandshakeInterval > TRANSPORT_SESSION_SLOWNESS_THRESHOLD &&
m_HandshakeInterval < TRANSPORT_SESSION_MAX_HANDSHAKE_INTERVAL; };
bool IsBandwidthExceeded (bool isHighBandwidth) const
{
auto limit = isHighBandwidth ? i2p::data::HIGH_BANDWIDTH_LIMIT*1024 : i2p::data::LOW_BANDWIDTH_LIMIT*1024; // convert to bytes
return std::max (m_InBandwidth, m_OutBandwidth) > limit;
}
int GetTerminationTimeout () const { return m_TerminationTimeout; };
void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; };
@@ -120,21 +140,52 @@ namespace transport
uint32_t GetCreationTime () const { return m_CreationTime; };
void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
void SetLastActivityTimestamp (uint64_t ts) { m_LastActivityTimestamp = ts; };
virtual uint32_t GetRelayTag () const { return 0; };
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
virtual bool IsEstablished () const = 0;
private:
void UpdateBandwidth ()
{
int64_t interval = m_LastActivityTimestamp - m_LastBandwidthUpdateTimestamp;
if (interval < 0 || interval > 60*10) // 10 minutes
{
// clock was adjusted, copy new values
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
return;
}
if ((uint64_t)interval > TRANSPORT_SESSION_BANDWIDTH_UPDATE_MIN_INTERVAL)
{
m_OutBandwidth = (m_NumSentBytes - m_LastBandWidthUpdateNumSentBytes)/interval;
m_LastBandWidthUpdateNumSentBytes = m_NumSentBytes;
m_InBandwidth = (m_NumReceivedBytes - m_LastBandWidthUpdateNumReceivedBytes)/interval;
m_LastBandWidthUpdateNumReceivedBytes = m_NumReceivedBytes;
m_LastBandwidthUpdateTimestamp = m_LastActivityTimestamp;
}
}
protected:
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
mutable std::mutex m_RemoteIdentityMutex;
size_t m_NumSentBytes, m_NumReceivedBytes, m_SendQueueSize;
bool m_IsOutgoing;
int m_TerminationTimeout;
uint64_t m_LastActivityTimestamp;
uint32_t m_CreationTime; // seconds since epoch
int64_t m_HandshakeInterval; // in milliseconds between SessionRequest->SessionCreated or SessionCreated->SessionConfirmed
private:
size_t m_SendQueueSize, m_NumSentBytes, m_NumReceivedBytes,
m_LastBandWidthUpdateNumSentBytes, m_LastBandWidthUpdateNumReceivedBytes;
uint64_t m_LastActivityTimestamp, m_LastBandwidthUpdateTimestamp;
uint32_t m_InBandwidth, m_OutBandwidth;
};
// SOCKS5 proxy

View File

@@ -591,7 +591,7 @@ namespace transport
peer.router->GetCompatibleTransports (true);
peer.numAttempts = 0;
peer.priority.clear ();
bool ssu2 = rand () & 1;
bool ssu2 = peer.router->GetProfile ()->IsReal () ? (rand () & 1) : false; // try NTCP2 if router is not confirmed real
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
for (auto transport: priority)
if (transport & compatibleTransports)
@@ -645,14 +645,33 @@ namespace transport
LogPrint (eLogInfo, "Transports: Started peer test IPv4");
std::set<i2p::data::IdentHash> excluded;
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
int testDelay = 0;
for (int i = 0; i < 5; i++)
{
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4
if (router)
{
if (i2p::context.GetStatus () != eRouterStatusTesting)
i2p::context.SetStatus (eRouterStatusTesting);
m_SSU2Server->StartPeerTest (router, true);
if (!i2p::context.GetTesting ())
{
i2p::context.SetTesting (true);
// send first peer test immediately
m_SSU2Server->StartPeerTest (router, true);
}
else
{
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service)
{
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay));
delayTimer->async_wait (
[this, router, delayTimer](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
m_SSU2Server->StartPeerTest (router, true);
});
}
}
excluded.insert (router->GetIdentHash ());
}
}
@@ -664,14 +683,33 @@ namespace transport
LogPrint (eLogInfo, "Transports: Started peer test IPv6");
std::set<i2p::data::IdentHash> excluded;
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
int testDelay = 0;
for (int i = 0; i < 5; i++)
{
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6
if (router)
{
if (i2p::context.GetStatusV6 () != eRouterStatusTesting)
i2p::context.SetStatusV6 (eRouterStatusTesting);
m_SSU2Server->StartPeerTest (router, false);
if (!i2p::context.GetTestingV6 ())
{
i2p::context.SetTestingV6 (true);
// send first peer test immediately
m_SSU2Server->StartPeerTest (router, false);
}
else
{
testDelay += PEER_TEST_DELAY_INTERVAL + rand() % PEER_TEST_DELAY_INTERVAL_VARIANCE;
if (m_Service)
{
auto delayTimer = std::make_shared<boost::asio::deadline_timer>(*m_Service);
delayTimer->expires_from_now (boost::posix_time::milliseconds (testDelay));
delayTimer->async_wait (
[this, router, delayTimer](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
m_SSU2Server->StartPeerTest (router, false);
});
}
}
excluded.insert (router->GetIdentHash ());
}
}
@@ -709,6 +747,14 @@ namespace transport
for (int i = 0; i < numExcluded; i++)
transports |= it->second.priority[i];
i2p::data::netdb.ExcludeReachableTransports (ident, transports);
}
if (it->second.router && it->second.numAttempts)
{
auto transport = it->second.priority[it->second.numAttempts-1];
if (transport == i2p::data::RouterInfo::eNTCP2V4 ||
transport == i2p::data::RouterInfo::eNTCP2V6 || transport == i2p::data::RouterInfo::eNTCP2V6Mesh)
it->second.router->GetProfile ()->Connected (); // outgoing NTCP2 connection if always real
i2p::data::netdb.SetUnreachable (ident, false); // clear unreachable
}
it->second.numAttempts = 0;
it->second.router = nullptr; // we don't need RouterInfo after successive connect
@@ -729,7 +775,7 @@ namespace transport
session->SendI2NPMessages (it->second.delayedMessages);
it->second.delayedMessages.clear ();
}
else // incoming connection
else // incoming connection or peer test
{
if(RoutesRestricted() && ! IsRestrictedPeer(ident)) {
// not trusted
@@ -737,11 +783,15 @@ namespace transport
session->Done();
return;
}
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
if (!session->IsOutgoing ()) // incoming
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
auto r = i2p::data::netdb.FindRouter (ident); // router should be in netdb after SessionConfirmed
if (r) r->GetProfile ()->Connected ();
auto ts = i2p::util::GetSecondsSinceEpoch ();
std::unique_lock<std::mutex> l(m_PeersMutex);
auto it = m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts })).first;
auto it = m_Peers.insert (std::make_pair (ident, Peer{ r, ts })).first;
it->second.sessions.push_back (session);
it->second.router = nullptr;
}
});
}
@@ -798,12 +848,12 @@ namespace transport
if (it->second.sessions.empty () && ts > it->second.creationTime + SESSION_CREATION_TIMEOUT)
{
LogPrint (eLogWarning, "Transports: Session to peer ", it->first.ToBase64 (), " has not been created in ", SESSION_CREATION_TIMEOUT, " seconds");
if (!it->second.router)
/* if (!it->second.router)
{
// if router for ident not found mark it unreachable
auto profile = i2p::data::GetRouterProfile (it->first);
if (profile) profile->Unreachable ();
}
} */
std::unique_lock<std::mutex> l(m_PeersMutex);
it = m_Peers.erase (it);
}
@@ -820,9 +870,13 @@ namespace transport
++it;
}
}
bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting;
bool ipv6Testing = i2p::context.GetStatusV6 () == eRouterStatusTesting;
// if still testing, repeat peer test
bool ipv4Testing = i2p::context.GetTesting ();
if (!ipv4Testing)
ipv4Testing = i2p::context.GetRouterInfo ().IsSSU2V4 () && (i2p::context.GetStatus() == eRouterStatusUnknown);
bool ipv6Testing = i2p::context.GetTestingV6 ();
if (!ipv6Testing)
ipv6Testing = i2p::context.GetRouterInfo ().IsSSU2V6 () && (i2p::context.GetStatusV6() == eRouterStatusUnknown);
// if still testing or unknown, repeat peer test
if (ipv4Testing || ipv6Testing)
PeerTest (ipv4Testing, ipv6Testing);
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(3 * SESSION_CREATION_TIMEOUT));
@@ -850,7 +904,9 @@ namespace transport
uint16_t inds[3];
RAND_bytes ((uint8_t *)inds, sizeof (inds));
std::unique_lock<std::mutex> l(m_PeersMutex);
inds[0] %= m_Peers.size ();
auto count = m_Peers.size ();
if(count == 0) return nullptr;
inds[0] %= count;
auto it = m_Peers.begin ();
std::advance (it, inds[0]);
// try random peer
@@ -933,7 +989,7 @@ namespace transport
// connected, not overloaded and not slow
return !peer.router && !peer.sessions.empty () && peer.isReachable &&
peer.sessions.front ()->GetSendQueueSize () <= PEER_ROUTER_INFO_OVERLOAD_QUEUE_SIZE &&
!peer.sessions.front ()->IsSlow () &&
!peer.sessions.front ()->IsSlow () && !peer.sessions.front ()->IsBandwidthExceeded (peer.isHighBandwidth) &&
(!isHighBandwidth || peer.isHighBandwidth);
});
}

View File

@@ -105,6 +105,8 @@ namespace transport
const uint64_t SESSION_CREATION_TIMEOUT = 15; // in seconds
const int PEER_TEST_INTERVAL = 71; // in minutes
const int PEER_TEST_DELAY_INTERVAL = 20; // in milliseconds
const int PEER_TEST_DELAY_INTERVAL_VARIANCE = 30; // in milliseconds
const int MAX_NUM_DELAYED_MESSAGES = 150;
const int CHECK_PROFILE_NUM_DELAYED_MESSAGES = 15; // check profile after
class Transports

View File

@@ -516,7 +516,7 @@ namespace tunnel
case eI2NPShortTunnelBuildReply:
case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply:
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
HandleTunnelBuildI2NPMessage (msg);
break;
default:
LogPrint (eLogWarning, "Tunnel: Unexpected message type ", (int) typeID);
@@ -586,10 +586,17 @@ namespace tunnel
auto typeID = msg->GetTypeID ();
LogPrint (eLogDebug, "Tunnel: Gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID);
if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply)
// transit DatabaseStore my contain new/updated RI
// or DatabaseSearchReply with new routers
if (typeID == eI2NPDatabaseSearchReply)
// DatabaseSearchReply with new routers
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg));
else if (IsRouterInfoMsg (msg))
{
// transit DatabaseStore might contain new/updated RI
auto m = CopyI2NPMessage (msg);
if (bufbe32toh (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET))
memset (m->GetPayload () + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0xFF, 4); // fake replyToken meaning no reply
i2p::data::netdb.PostI2NPMsg (m);
}
tunnel->SendTunnelDataMsg (msg);
}
@@ -702,7 +709,7 @@ namespace tunnel
auto inboundTunnel = GetNextInboundTunnel ();
auto router = i2p::transport::transports.RoutesRestricted() ?
i2p::transport::transports.GetRestrictedPeer() :
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false); // reachable by us
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true); // reachable by us
if (!inboundTunnel || !router) return;
LogPrint (eLogDebug, "Tunnel: Creating one hop outbound tunnel");
CreateTunnel<OutboundTunnel> (
@@ -774,7 +781,7 @@ namespace tunnel
auto router = i2p::transport::transports.RoutesRestricted() ?
i2p::transport::transports.GetRestrictedPeer() :
// should be reachable by us because we send build request directly
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false);
i2p::data::netdb.GetRandomRouter (i2p::context.GetSharedRouterInfo (), false, true);
if (!router) {
LogPrint (eLogWarning, "Tunnel: Can't find any router, skip creating tunnel");
return;
@@ -979,6 +986,6 @@ namespace tunnel
LogPrint (eLogDebug, "Tunnel: Max number of transit tunnels set to ", maxNumTransitTunnels);
m_MaxNumTransitTunnels = maxNumTransitTunnels;
}
}
}
}
}

View File

@@ -45,7 +45,7 @@ namespace tunnel
const int TUNNEL_MANAGE_INTERVAL = 15; // in seconds
const int TUNNEL_POOLS_MANAGE_INTERVAL = 5; // in seconds
const int TUNNEL_MEMORY_POOL_MANAGE_INTERVAL = 120; // in seconds
const size_t I2NP_TUNNEL_MESSAGE_SIZE = TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34; // reserved for alignment and NTCP 16 + 6 + 12
const size_t I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE = 2*TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28; // reserved for alignment and NTCP 16 + 6 + 6
@@ -232,8 +232,8 @@ namespace tunnel
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
uint16_t GetMaxNumTransitTunnels () const { return m_MaxNumTransitTunnels; };
bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
bool IsTooManyTransitTunnels () const { return m_TransitTunnels.size () >= m_MaxNumTransitTunnels; };
private:
template<class TTunnel>
@@ -292,7 +292,7 @@ namespace tunnel
i2p::util::Queue<std::shared_ptr<I2NPMessage> > m_Queue;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_ENPOINT_MESSAGE_SIZE> > m_I2NPTunnelEndpointMessagesMemoryPool;
i2p::util::MemoryPoolMt<I2NPMessageBuffer<I2NP_TUNNEL_MESSAGE_SIZE> > m_I2NPTunnelMessagesMemoryPool;
uint16_t m_MaxNumTransitTunnels;
uint16_t m_MaxNumTransitTunnels;
// count of tunnels for total TCSR algorithm
int m_TotalNumSuccesiveTunnelCreations, m_TotalNumFailedTunnelCreations;
double m_TunnelCreationSuccessRate;
@@ -311,6 +311,7 @@ namespace tunnel
int GetQueueSize () { return m_Queue.GetSize (); };
int GetTunnelCreationSuccessRate () const { return std::round(m_TunnelCreationSuccessRate * 100); } // in percents
double GetPreciseTunnelCreationSuccessRate () const { return m_TunnelCreationSuccessRate * 100; } // in percents
int GetTotalTunnelCreationSuccessRate () const // in percents
{
int totalNum = m_TotalNumSuccesiveTunnelCreations + m_TotalNumFailedTunnelCreations;

View File

@@ -323,11 +323,7 @@ namespace tunnel
}
uint8_t typeID = msg.data->GetTypeID ();
LogPrint (eLogDebug, "TunnelMessage: Handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID);
// catch RI or reply with new list of routers
if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) &&
!m_IsInbound && msg.deliveryType != eDeliveryTypeLocal)
i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data));
switch (msg.deliveryType)
{
case eDeliveryTypeLocal:

View File

@@ -296,10 +296,12 @@ namespace tunnel
for (const auto& it : m_InboundTunnels)
if (it->IsEstablished ()) num++;
}
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0)
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0 &&
m_NumInboundHops == m_NumOutboundHops)
{
for (auto it: m_OutboundTunnels)
{
// try to create inbound tunnel through the same path as succesive outbound
CreatePairedInboundTunnel (it);
num++;
if (num >= m_NumInboundTunnels) break;
@@ -470,13 +472,14 @@ namespace tunnel
return i2p::tunnel::tunnels.GetExploratoryPool () == shared_from_this ();
}
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const
std::shared_ptr<const i2p::data::RouterInfo> TunnelPool::SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop,
bool reverse, bool endpoint) const
{
auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse):
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse);
auto hop = IsExploratory () ? i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint):
i2p::data::netdb.GetHighBandwidthRandomRouter (prevHop, reverse, endpoint);
if (!hop || hop->GetProfile ()->IsBad ())
hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse);
hop = i2p::data::netdb.GetRandomRouter (prevHop, reverse, endpoint);
return hop;
}
@@ -508,7 +511,7 @@ namespace tunnel
for(int i = start; i < numHops; i++ )
{
auto hop = nextHop (prevHop, inbound);
auto hop = nextHop (prevHop, inbound, i == numHops - 1);
if (!hop && !i) // if no suitable peer found for first hop, try already connected
{
LogPrint (eLogInfo, "Tunnels: Can't select first hop for a tunnel. Trying already connected");
@@ -520,11 +523,6 @@ namespace tunnel
LogPrint (eLogError, "Tunnels: Can't select next hop for ", prevHop->GetIdentHashBase64 ());
return false;
}
if ((i == numHops - 1) && (!hop->IsV4 () || (inbound && !hop->IsPublished (true)))) // IBGW is not published ipv4
{
auto hop1 = nextHop (prevHop, true);
if (hop1) hop = hop1;
}
prevHop = hop;
path.Add (hop);
}
@@ -566,14 +564,15 @@ namespace tunnel
if (m_CustomPeerSelector)
return m_CustomPeerSelector->SelectPeers(path, numHops, isInbound);
}
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this, std::placeholders::_1, std::placeholders::_2));
return StandardSelectPeers(path, numHops, isInbound, std::bind(&TunnelPool::SelectNextHop, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
}
bool TunnelPool::SelectExplicitPeers (Path& path, bool isInbound)
{
if (!m_ExplicitPeers->size ()) return false;
int numHops = isInbound ? m_NumInboundHops : m_NumOutboundHops;
if (numHops > (int)m_ExplicitPeers->size ()) numHops = m_ExplicitPeers->size ();
if (!numHops) return false;
for (int i = 0; i < numHops; i++)
{
auto& ident = (*m_ExplicitPeers)[i];

View File

@@ -56,7 +56,7 @@ namespace tunnel
class TunnelPool: public std::enable_shared_from_this<TunnelPool> // per local destination
{
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool)> SelectHopFunc;
typedef std::function<std::shared_ptr<const i2p::data::RouterInfo>(std::shared_ptr<const i2p::data::RouterInfo>, bool, bool)> SelectHopFunc;
public:
TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels,
@@ -112,7 +112,7 @@ namespace tunnel
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
// for overriding tunnel peer selection
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse) const;
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop, bool reverse, bool endpoint) const;
bool StandardSelectPeers(Path & path, int numHops, bool inbound, SelectHopFunc nextHop);
private:

View File

@@ -38,9 +38,8 @@ namespace api
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool avx; i2p::config::GetOption("cpuext.avx", avx);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -27,6 +27,17 @@
# include <AvailabilityMacros.h>
#endif
#if defined(__HAIKU__)
#include <gnu/pthread.h>
#include <posix/pthread.h>
#include <posix/sys/sockio.h>
#include <posix/sys/ioctl.h>
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#include <bsd/ifaddrs.h>
#endif
#endif
#ifdef _WIN32
#include <stdlib.h>
#include <string.h>
@@ -201,7 +212,7 @@ namespace net
int GetMTUWindowsIpv4 (sockaddr_in inputAddress, int fallback)
{
typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size);
IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found
ULONG outBufLen = 0;
@@ -262,7 +273,7 @@ namespace net
int GetMTUWindowsIpv6 (sockaddr_in6 inputAddress, int fallback)
{
typedef const char *(* IPN)(int af, const void *src, char *dst, socklen_t size);
IPN inetntop = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
IPN inetntop = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetNtop");
if (!inetntop) inetntop = inet_ntop_xp; // use own implementation if not found
ULONG outBufLen = 0;
@@ -341,7 +352,7 @@ namespace net
#endif
typedef int (* IPN)(int af, const char *src, void *dst);
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
IPN inetpton = (IPN)(void*)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
if (localAddress.is_v4())
@@ -654,6 +665,7 @@ namespace net
if (host.is_v6())
{
static const std::vector< std::pair<boost::asio::ip::address_v6::bytes_type, boost::asio::ip::address_v6::bytes_type> > reservedIPv6Ranges {
address_pair_v6("64:ff9b::", "64:ff9b:ffff:ffff:ffff:ffff:ffff:ffff"), // NAT64
address_pair_v6("2001:db8::", "2001:db8:ffff:ffff:ffff:ffff:ffff:ffff"),
address_pair_v6("fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
address_pair_v6("fe80::", "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -18,8 +18,8 @@
#define MAKE_VERSION_NUMBER(a,b,c) ((a*100+b)*100+c)
#define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 47
#define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_MINOR 50
#define I2PD_VERSION_MICRO 2
#define I2PD_VERSION_PATCH 0
#ifdef GITVER
#define I2PD_VERSION XSTRINGIZE(GITVER)
@@ -33,7 +33,7 @@
#define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 58
#define I2P_VERSION_MICRO 61
#define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
#define I2P_VERSION_NUMBER MAKE_VERSION_NUMBER(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

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