Compare commits

...

706 Commits

Author SHA1 Message Date
Stefan Strogin 697d831441 Support miniupnp-2.2.8 (fixes #2071)
Use UPNP_GetValidIGD for getting external IP.
4 days ago
orignal 457b64f92d try to connect to introducer through any available address 2 weeks ago
orignal 6caec6b551 check if updated router is still introducer. Remove non-introducer sessions from introducers list 2 weeks ago
orignal 362edc68ad removed ls's reseed 2 weeks ago
orignal 29872fc003 check if local address exists 2 weeks ago
orignal 81d383c99e don't pick routers older that 0.9.58 for client tunnels 2 weeks ago
orignal 12653f2fe4 don't try introducer with invalid address. Terminate session immediately if appropriate introducer not found 2 weeks ago
orignal 43f5ba286c update congestion caps before initial publishing 2 weeks ago
orignal f990a2f69f don't reply with relay tag if we are not on introducer on that address 2 weeks ago
orignal 0b97b4294c don't request relay tag for every session if we have enough introducers 2 weeks ago
orignal 4178ac8eac select newest introducers to publish 2 weeks ago
orignal 6a590bf970 use std::mt19937 instead rand() 3 weeks ago
orignal 2f847d62bb fixed typo 3 weeks ago
orignal df6d48dbae request only not found routers from introducers 3 weeks ago
orignal bacce7dc60 fixed introducer's index 3 weeks ago
orignal b3314380cc don't use expired introducer even if we a session with it 3 weeks ago
orignal d4eea61b82 use mt19937 instead rand 3 weeks ago
orignal a1995c13cd flood to 2 next day closest floodfills before UTC midnight 3 weeks ago
orignal bc8adf1433 move unsent I2NP messages to new session if replaced 3 weeks ago
orignal a1322d4667 move unsent I2NP messages to new session if replaced 3 weeks ago
orignal 4100249313 removed bootstrap from floodfill. Removed requested destinations mutex 4 weeks ago
orignal acbd3f897b fixed race condition between local buffer creation and sending it through the transports 1 month ago
orignal 7dc5a04b8d update timestamp for non-reachable router 1 month ago
orignal 03635f4444 publish through tunnels in case of restricted routes 1 month ago
orignal 0fae04f96a update local RouterInfo timestamp by timer even in hidden mode 1 month ago
orignal bb531a878d request newly discovered routers with random intervals after exploratory 1 month ago
orignal 0f7db8e418 list of request callbacks 1 month ago
orignal 9a724b2af9 separate timer for netdb requests cleanup 1 month ago
orignal f4ea6138e8 removed non longer used mutex 1 month ago
orignal e74272781f moved exploratory to netdb requests thread 1 month ago
orignal b75e418879 request destination in netdb requests thread 1 month ago
orignal 927123188c handle onDrop for request message in nedb requests thread 1 month ago
orignal c00eb8cf44 handle requests completions in netdb requests thread 1 month ago
orignal 265bb8b779 handle DatabaseSearchReply in netdb requests thread 1 month ago
orignal e3be409945 moved netdb requests to separate thread 1 month ago
orignal d8707ceb57
Merge pull request #2066 from EKCKABATOP54/fix
Fixed checking the bandwidth flag in the config
1 month ago
orignal 39e16824b9 reset routing path if duplicated SYN received 1 month ago
orignal 285e693a4e fixed deadlock 1 month ago
orignal 940628bf36 update LeaseSet if inbond tunnel failed 1 month ago
orignal b5994e058a increment num attempts if no reply tunnel specified 1 month ago
orignal 22dabfd79e use unordered_map for excluded routers. don't request to self 1 month ago
orignal 0e41c3fa36 resend more interval variance 1 month ago
orignal 124698854f skip resent recently sessions during resend 1 month ago
EKCKABATOP54 f223e668ce Fixed checking the bandwidth flag in the config 1 month ago
orignal f5b823a712 common code for sending netdb lookup 1 month ago
r4sas 4163542125
[gha] short commit hashes for deb packages
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 month ago
r4sas 6921c8391e
[FS] boost 1.85.0 support
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 month ago
r4sas 47a2020472
[i18n] update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 month ago
orignal 9d38facf3b 2.52.0 2 months ago
r4sas a1be1aa9ec
[gha] cache packages on winxp build
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
r4sas c4bbe2bb4a
[win32] fix warning in NetState
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
r4sas 601695dede [gha] winxp: rebuild boost
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
r4sas cdc81e19a0 [gha] update winxp build
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
orignal b98b3a87b0 fixed race codition between RouterInfo's buffer persist and update 2 months ago
orignal 425ef2cfe5 persist routers in separate thread 2 months ago
orignal c454685605 exclude addresses with wrong keys 2 months ago
orignal c98926abf2 use mt19937 instead rand() 2 months ago
orignal 7aacc97351 initialize requests before reseeds 2 months ago
orignal c49e17ad40 use timestamp to reset rng 2 months ago
orignal 296b721929 shared_ptr for NetdbRequests 2 months ago
orignal d0cf385f4b memory pool for requested destination. Reduced request attaempts to 5 2 months ago
orignal b91f5a7430 fixed race condition on stop 2 months ago
orignal 4d8431907d use std::sample for exploratory selection if C++17 2 months ago
orignal b0cf5130a2 don't try another flloofill if request already exists 2 months ago
orignal 396aa6944d cache complete request for a while and not send the same request again 2 months ago
orignal 8a20d3219b don't build exploratory selection on each request 2 months ago
orignal 13a746162a reduce exploratory selection size 2 months ago
orignal 7e5370fbe5 check for excluded routers during exploratory 2 months ago
orignal ec59308fad return up to 16 hash in expolatory reply 2 months ago
orignal 5ed76b997c log initial destination request 2 months ago
orignal 535fbdb4c9 don't check exporatory too often 2 months ago
orignal 034332a0ef changed minimal exploratory interval to 55 seconds. added variance 2 months ago
orignal a1eac6f28e drop unsolicited database serach replies 2 months ago
orignal ba22a940f1 30 seconds timeout for exploratory requests 2 months ago
orignal 8439f6dc57 don't reply with close than us only floodfills for lookup 2 months ago
orignal a21bec0ed8 check if router if real only if tunnel build rate is low and router's profile is presented when handle exploratory request 2 months ago
orignal 5adbc2c3fe don't stop lookup if number of attempts < 3 2 months ago
orignal c515f49903 removed dependency from boost::thread 2 months ago
orignal 845b14f581 removed dependency from boost::thread 2 months ago
orignal cdfdfc9e24 don't manage netdb is transports are not running 2 months ago
orignal 62d279e1b0 don't return routers with 'f' cap to exploratory request 2 months ago
orignal a1fcd8af39 don't accept too old RouterInfo 2 months ago
orignal 8c6c954ea2 enable previously disabled floodfill 2 months ago
orignal 77bb7432bc insert previously ecluded floodfill back when connected 2 months ago
orignal 720ffa8a31 move traverse thrugh profiles files to deleting thread 2 months ago
orignal c1c69258c3 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2 months ago
orignal 733a4a2869 moved save/delete profile disk oprations to separate threads 2 months ago
r4sas ca3ac8c11d
[gha] update actions
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
r4sas d4e3991257
[gha] fix osx build
Signed-off-by: r4sas <r4sas@i2pmail.org>
2 months ago
orignal 648a884a18 use copy of excluded peers 2 months ago
orignal 8fe989050e use share_ptr to store peers 2 months ago
orignal bb6212ccc1 fixed typo 2 months ago
orignal 5f39f65540 mutex for request's excluded peers 2 months ago
orignal 146b3f52c0 check if pool is ready before sending next request 2 months ago
orignal cc75ccd070 don't manage requests if exploratory pool is not ready. use monotonic timer and milliseconds 2 months ago
orignal 0ddc514221 don't send next request if requested destination is over 2 months ago
orignal d3b699d7cd
Merge pull request #2059 from Vort/manage_interval
manage netDb requests more frequently
2 months ago
Vort 6592fab41c manage netDb requests more frequently 2 months ago
orignal 02895d4cf5 respond with confirmied router to exploratory lookup 2 months ago
orignal 8b7941c4ce fixed typo 2 months ago
orignal de673464d1 don't try to connect directy by SSU2 to unnconfirmed router if direct NTCP2 is presented 2 months ago
orignal 6ce2c30522 build client tunnels through confimed routers only if low rate 2 months ago
orignal c5a1e8cac8 give preference to direct connection 2 months ago
orignal f67c38d8d2 fixed typo 2 months ago
orignal 1f1a3270f7 fixed IsPublished for ipv6 2 months ago
orignal ffee29272f avoid two firewalled routers in the row 2 months ago
orignal 2d2469c23d
Merge pull request #2052 from nonlin-lin-chaos-order-etc-etal/openssl
Add fcntl to actually lock pidfile on Android
3 months ago
nonlin-lin-chaos-order-etc-etal 8e80a8b06f Add fcntl to actually lock pidfile on Android 3 months ago
orignal 26fac94d05 delete unused varibale 3 months ago
orignal 9a30068ae5 don't compare OBEP hash twice to check if it's a fresh tunnel 3 months ago
orignal 04bccedd9b
Merge pull request #2048 from Vort/stream_resends
Reset stream RTO if outbound tunnel was changed
3 months ago
Vort b2e21a4f12 increase maximum stream resend attempts to 9 3 months ago
Vort 57e46ba0cf reset stream RTO if outbound tunnel was changed 3 months ago
Vort df3dc1f574 change tunnels during stream resend attempts 5 and 6 3 months ago
r4sas 1b5f67e185
[FS] misc: bump year
Signed-off-by: r4sas <r4sas@i2pmail.org>
3 months ago
r4sas 89064b6fb4
2.51.0
Signed-off-by: r4sas <r4sas@i2pmail.org>
3 months ago
orignal c49dd712de 2.51.0 3 months ago
orignal 4f1cb74f75 request choking delay if too many NACKs. Drop window size to 1 if choking delay received 3 months ago
orignal 75df8d3c7b drop ack Through to last packet if Number of NACKs exceeds 255 3 months ago
orignal 85be76b01a check if LeaseSet was submitted recently. Fixed typo 3 months ago
orignal 835c480269
Merge pull request #2047 from Vort/ssu2_lag
select maximum SSU2 queue size depending on RTT value
3 months ago
Vort ac9d92c681 select maximum SSU2 queue size depending on RTT value 3 months ago
r4sas a30d1972e5
[win] update status code
Signed-off-by: r4sas <r4sas@i2pmail.org>
3 months ago
orignal 0c2330bf14
Merge pull request #2045 from Vort/rtt_sample
streaming improvements
3 months ago
Vort a703d31893 don't double initial RTO 3 months ago
Vort 4f8f3a386f restart stream resend timer after updating initial RTO 3 months ago
Vort 83f0b9c041 extract single RTT sample from stream ACK 3 months ago
Vort cf77be0eeb add lower limit for stream RTO 3 months ago
orignal b2aa34baa6 use C++17 for newer versions of clang for BSD 3 months ago
orignal 4def0b6ea5 use C++17 for newer versions of clang for BSD 3 months ago
orignal 25592a00b6 use C++17 for newer versions of clang for BSD 3 months ago
orignal edaf162f9c
Merge pull request #2044 from Vort/stream_resend_rtt
exclude resent stream packets from RTT calculations
3 months ago
Vort e7ff15c573 exclude resent stream packets from RTT calculations 3 months ago
orignal 161ff3579b don't delete new session with same router hash from sessions-by-hash table 3 months ago
orignal f2085ecc8d fixed warning 3 months ago
orignal 0c5dee69ba
Merge pull request #2043 from Vort/rtt_tune
tune RTT calculations
3 months ago
Vort d74033dd2b tune RTT calculations 3 months ago
orignal 5412e29ff5
Merge pull request #2042 from Vort/ssu2_spikes
lower SSU2 resend traffic spikes
3 months ago
Vort 0236769134 lower SSU2 resend traffic spikes 3 months ago
orignal 530a078535 don't request temination if session was not established 3 months ago
orignal fbca27fe73
Merge pull request #2041 from Vort/i2np_typo
fix typo in message expiration check
3 months ago
Vort 08cc256c54 fix typo in message expiration check 3 months ago
orignal 6432963294
Merge pull request #2037 from vovasty/fs_ios_simulator_fix
fix HashedStorage::Init exceptions in ios simulator.
4 months ago
Vlad Solomenchuk 59beb5e4e4 fix TARGET_OS_SIMULATOR check 4 months ago
orignal 217aa0c882 fixed #2038. don't add comma for missing param 4 months ago
orignal e889dc1508
Merge pull request #2039 from Vort/ssu2_expiration
add expiration for messages in SSU2 send queue
4 months ago
Vort 2d06c0cbe6 add expiration for messages in SSU2 send queue 4 months ago
Vlad Solomenchuk 51446f0324 fix FS::HashedStorage::Init exceptions in ios simulator. 4 months ago
orignal 66d0b7aec4 correct publication verification for encrypted LeaseSet 4 months ago
orignal 92b49fb969 clear excluded floodfills after successive publishing 4 months ago
orignal 17dd5c1285 publish encrypted leaset on floodfill closest to store hash 4 months ago
orignal ce97ec1534
Merge pull request #2036 from Vort/stream_ewma2
changes in stream RTT estimation and window size drop percent
4 months ago
Vort 3ceb64db2e 1. Use EWMA for stream RTT estimation;
2. Drop window size by 10% instead of 50% in case of resend.

Change is based on code by onon.
4 months ago
orignal bb702700f7 don't check session for single tag 4 months ago
orignal ff3fec9a00 remove tag immediately after use 4 months ago
orignal 3873e60cbb try to send database store reply directly to IBGW 4 months ago
orignal 2dbf094433 try to send lookup reply directly to IBGW 4 months ago
orignal e85e96bc35
Merge pull request #2035 from Vort/high_latency_fix
fix high latency threshold
4 months ago
Vort 98543af92b fix high latency threshold 4 months ago
orignal af0d853ccd some cleanup 4 months ago
orignal 20a5e19ea1 don't request banned router 4 months ago
orignal f1058410fb don't request banned router 4 months ago
orignal 6ba42a0912 check if established peer test session has the same address type 4 months ago
orignal 1292ec67c0 check if remote router supports peer test 4 months ago
orignal 2f2f14e3a7 try publishing again after 5 seconds if no tunnels in the pool 4 months ago
orignal edd9dd2c39 try to publish again after 5 seconds if destination is not ready 4 months ago
orignal f8722f17c6 pick peer test session only if Charlie's address supports peer testing 4 months ago
orignal 38cc01e13d check own peer test cap for peer test msg 2 4 months ago
orignal 6ca266ff3b reject peer test msg 2 if peer testing is not supported 4 months ago
orignal b9773c88e4 don't set test failed state to expiring tunnels 4 months ago
orignal 3311fe62bb fixed potential race condition with tunnel tests 4 months ago
orignal a284c85153
Merge pull request #2033 from Vort/ssu2_dynamic_buffer
derive SSU2 socket buffer size from bandwidth limit
4 months ago
Vort e5f75eb61c log would_block error at info level 4 months ago
Vort 89f9bec49a derive SSU2 socket buffer size from bandwidth limit 4 months ago
orignal dbc3952654
Merge pull request #2031 from Vort/buf_size_log
write SSU2 socket buffer sizes to log
4 months ago
Vort f3c052ed0c write SSU2 socket buffer sizes to log 4 months ago
orignal 692f495adc
Merge pull request #2030 from Vort/non_block
enable non-blocking mode for UDP sockets
4 months ago
Vort aa1de7fe94 enable non-blocking mode for UDP sockets 4 months ago
orignal ca45fe73e9 never delete conneted router from netdb 4 months ago
orignal a8af683643 renamed steady to monotonic 4 months ago
orignal b86c83a068 encrypt tunnel tests for ElGamal-only destinations 4 months ago
orignal 6656ef3c8d correct clock for non-encrypted tunnel tests 4 months ago
orignal 6898d04a1d send tunnel test mesaage only if encrypted 4 months ago
orignal 3215125950
Merge pull request #2029 from Vort/tunnel_test_msg
add tunnel test message
4 months ago
Vort 3d03732555 add tunnel test message 4 months ago
Vort d6d440ba8a allow 0ms latency for tunnel 4 months ago
orignal 821a76a7c5 flush IBGW if tunnel build request OBEP is on the same router 4 months ago
r4sas 34154596f2
[gha] build only when related to app and runner itself files are changed, disable temporary msvc
Signed-off-by: r4sas <r4sas@i2pmail.org>
4 months ago
orignal a1dce017f4 allow tunnel endpoint to send tunnel build reply to itself 4 months ago
orignal 78af34237e reduce session termination timeout 4 months ago
orignal 8874ea8033 fixed typo 4 months ago
orignal 6bd1ee36f7 fixed typo 4 months ago
orignal f07c4bd1dd drop transit tunnel if next ident is ours 4 months ago
orignal 8524a67895 fail last tunnel if tunnel quantity is 1 4 months ago
orignal 43d880752e Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 4 months ago
orignal d4246edb82 don't fail last tunnel 4 months ago
orignal ee8449fa05
Merge pull request #2024 from Vort/congestion_zero_check
add zero check to congestion level calculations
4 months ago
Vort 5415598f60 add zero check to congestion level calculations 4 months ago
orignal 7d73c304b5 Extend transit tunnels limit to 4 bytes. Bump default value to 10K 4 months ago
orignal d25206abce encrypted tunnel test messages 4 months ago
r4sas 5d7c6fb0b3
[gha] msvc: copy openssl libraries to fix build
Signed-off-by: r4sas <r4sas@i2pmail.org>
4 months ago
orignal 36a060d50f Consider 'M' routers as low bandwidth 4 months ago
orignal 577ed56af0 store HTTP and SOCKS proxy as pointer to I2PService 4 months ago
orignal 695dc96a83 common ServiceAcceptor for all stream protocols 4 months ago
orignal e5251bf3c3
Merge pull request #2022 from Vort/bw_time_jumps3
skip bandwidth updates in case of time going backwards
4 months ago
R4SAS 2692aef53d
[gha] update windows msvc action 4 months ago
Vort d524105727 skip bandwidth updates in case of time going backwards 4 months ago
orignal 26463c50fc
Merge pull request #2020 from Vort/select_next_hop2
make more attempts to select not bad hop
4 months ago
Vort b092e712ec make more attempts to select not bad hop 4 months ago
orignal cb8fbb0135
Merge pull request #2018 from Vort/congestion_consts
add constants for congestion levels
4 months ago
Vort 19e23b34da add constants for congestion levels 4 months ago
orignal a4a3f8e96b support upstream proxy through local sockets 4 months ago
orignal f2b720617c
Merge pull request #2016 from Vort/medium_congestion2
implement medium congestion indication
4 months ago
Vort d677d67676 implement medium congestion indication 4 months ago
orignal 7e3157b162 don't process packet in terminated stream 4 months ago
orignal 2b6a95cbee don't check session for symmetric key tagset. re-create tags hash if too many used tags 4 months ago
orignal 900153765a move router's tags cleanup to router's thread 4 months ago
orignal 441e847de8 don't try to decrypt dulpicate message 4 months ago
orignal 6439e227f6 consider test failed state as established. Delete failed tunnels sooner 4 months ago
orignal def404b61a skip failed and expiring tunnels for peer tests 4 months ago
orignal d8be5b8ce1 fixed warning 4 months ago
orignal dddbca6ffb common rng for random shuffle 4 months ago
orignal 56619caa71 random shuffle of tunnels for peer test pairs 4 months ago
orignal 0e502c49b5 show correct tunnel status. restore tunnel if delivery status or data for inbound tunnel received 4 months ago
orignal 710b27688b generic SocketsPipe for different socket types 4 months ago
orignal a9ad6fc31e renamed TCPIPPipe to SocketsPipe 4 months ago
orignal 967627e58a read correct reply length and handle reply codes 4 months ago
orignal 7691a5b4a9 use common SOCK5 code for reseed 4 months ago
orignal d9b6262a6e removed unused field 4 months ago
orignal 075f80aea2 use SOCK5 proxy for upstream 5 months ago
orignal b07530a8a1 don't print error message if operation cancelled 5 months ago
orignal 0ae7931a6f replaced SOCKS4 outproxy by SOCKS5 5 months ago
orignal 158160f5c0 common code for SOCKS5 proxy connectivity 5 months ago
orignal 4cb2ad48be
Merge pull request #2014 from Vort/log_fixes
Logging fixes
5 months ago
Vort adba3987f8 logging fixes 5 months ago
orignal 36dbc15bca keep SSU2 socket open even if failed to bind 5 months ago
orignal d96803a290 always request through tunnels in case of restricted routes 5 months ago
orignal 592d6ae4f4 check log level before calculating base32 or base64 of ident 5 months ago
orignal 7dd9a7a0af added CheckLogLevel 5 months ago
orignal 1b23aa2d7b increase request timeout 5 months ago
orignal f980277552 don't flood failed router 5 months ago
orignal 586695673b correct log message for next netdb request 5 months ago
orignal c158bbe90a send frame when it exceeds 16K 5 months ago
orignal c01fd3299f handle drop of destination publish msg 5 months ago
orignal f64b136f5a remove prestium reseeds 5 months ago
orignal 37e67cbcaa
Merge pull request #2013 from WaxySteelWorm/openssl
reseed.stormycloud.org reseed added
5 months ago
orignal be815804e6 expire transit tunnel is not sent further 5 months ago
orignal ce35637866 handle drop of tunnel build message 5 months ago
StormyCloudInc de2b0f6e09
Update Config.cpp 5 months ago
StormyCloudInc 7b776666a3
Add files via upload 5 months ago
orignal 47578b69c6 handle drop of tunnel test message 5 months ago
orignal 8f28cee32f drop earlier if delayed queue is semi-full 5 months ago
orignal 96cf6ca531 drop earlier if outgoing queue is semi-full 5 months ago
orignal 83cb3a1820 reduce router unreachable interval 5 months ago
orignal ffdd5935e9 Handle drop of own RouterInfo publishing message 5 months ago
orignal 2e9f2d4a3b Drop for LeaseSet request 5 months ago
orignal 0ca782ed71 drop unsent messages if session disconnects 5 months ago
orignal e40b656ecf Drop for tunnel and encrypted messages 5 months ago
orignal 85f5f5b91e fixed potential deadlock 5 months ago
orignal f008478505 handle I2NP messages drops 5 months ago
orignal d926a31064 fixed warning 5 months ago
orignal 822cb35efe limit send Ack timeout by Ack delay interval 5 months ago
orignal faaa8115d9
Merge pull request #2011 from Vort/net_status
log changes of network status
5 months ago
Vort 81015a5228 log changes of network status 5 months ago
orignal a3246cd9dc doen't send Ack packet too often if missing packets 5 months ago
orignal 530c353b00 don't send Ack with NACK immediately but after 2 milliseconds 5 months ago
orignal 75c2cb751f lock mutex before deleting RouterInfo's buffer 5 months ago
orignal 67c4d4bcaa fixed VS build error 5 months ago
orignal 25e82105b2
Merge pull request #2010 from wekoq/udp-tunnels-dest
Add support for multiple udp server tunnels on one destionation
5 months ago
weko 4b167fdbaf Update copyright year 5 months ago
weko 5b93558bd0 Add support for multiple udp server tunnels on one destionation 5 months ago
orignal 70639f1139 don't adjust clock if offsets came from same router 5 months ago
orignal c5a1806528 fixed possible deadlock 5 months ago
orignal a2249f0a82 identify server tunnel session but from ant to ports 5 months ago
orignal 9f217f8a11 don't send expired I2NP messages 5 months ago
orignal 5e19e361e7 check max frame sizebefore sending 5 months ago
orignal 0b47f65b06 don't remove another NTCP2 session with same address 5 months ago
orignal 140146e433 limit mininal received packet size to 40 bytes 5 months ago
R4SAS b4484c8e8f
[gha] msvc: switch back to boost 1.81.0 5 months ago
orignal 1e5604ed43 check if peer is connected before trying to connect 5 months ago
orignal 39e378a03d check received data size 5 months ago
orignal 7cfcb12c7b don't create peer for unreachable router 5 months ago
orignal 49f4dc53ad try next floodfill for router request on demand 5 months ago
orignal 4afdca090d support multiple RouterInfo request callbacks 5 months ago
orignal d8f6c4a93d correct encryption and path for follow on lookup request 5 months ago
orignal d724948d03
Merge pull request #2007 from Vort/reservedrange2
handle 'reservedrange' param properly
6 months ago
Vort 34d75b08dd handle 'reservedrange' param properly 6 months ago
orignal ca9782dd0d handle 'reservedrange' param properly 6 months ago
orignal 2ad26dd4c9 fixed race condition in ECIESx25519 tags table 6 months ago
orignal 828facab57
Merge pull request #2003 from rex4539/typos
Fix typos
6 months ago
orignal cd087568b5 reply with CANT_REACH_PEER if connect to outselves 6 months ago
R4SAS dfe8b25e5e
[gha] MSVC: remove deletion of installation files 6 months ago
R4SAS 1e9bcd6b8b
[gha] MSVC: Switch to direct Boost and OpenSSL installation 6 months ago
orignal 8bc58daa5a fixed #2004. Check supported crypto 6 months ago
orignal 3b97feb89f 2.50.2 6 months ago
orignal a8135b8d18 2.50.2 6 months ago
orignal 5cf1961fa4 drop updated routers from future 6 months ago
Dimitris Apostolou 577c71b930
Fix typos 6 months ago
orignal c5cab05a6b reset peding time offset if correct time was received 6 months ago
orignal b855c71891 don't adjust clock if time offsets are too different 6 months ago
orignal 21f41a2b2a correct time offset direction 6 months ago
orignal 8319dd6b25 drop exploratory and leaseset lookups for non-floodfill router 6 months ago
orignal d4c47d90cb adjust time offset after second time discrepancy 6 months ago
orignal 302af823a3 fixed race condition with openssl 3.2.0 6 months ago
r4sas 69ee6112b3
[changelog] fix version
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
r4sas 816a58f292
2.50.1
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
orignal 43e130ee34 reinitialize context before each Sign/Verify call to make it working with openssl 3.2 6 months ago
orignal 8ffc1486a4 test-eddsa added 6 months ago
orignal 0e98dd5c70 use fallback EdDSA implementation with openssl 3.2.0 due to regression in EVP_DigestSign (#23075) 6 months ago
r4sas beffdb9fe1
[apparmor] add profile for docker container
Author: corona@mail.i2p

Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
r4sas 05eda2bc9e
[gha] build docker containers only on specific paths changes
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
r4sas c3429bb1a9
[gha] return freebsd build back
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
r4sas 53c6b10177
[make] get the mistakenly deleted pthread back
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
r4sas c2d7133174
[make] fix windows msys2 build
Signed-off-by: r4sas <r4sas@i2pmail.org>
6 months ago
orignal 9b82265cd8 2.50.0 6 months ago
orignal c802c2deb0 update yggdrasil ressed address 7 months ago
orignal c215f2e8d1 check router for null pointer 7 months ago
orignal d327533b56 close unclaimed acceptors after 3 seconds 7 months ago
orignal 94255ebaf4 STREAM ACCEPT queue 7 months ago
orignal 21259204b1 eliminate send buffer mutex completely 7 months ago
orignal 8d6eb5b6b2 don't lock mutex in AsyncSend 8 months ago
orignal 9632e7ba03 exclude NAT64 ipv6 addresses 8 months ago
Dimitris Apostolou 1a02819187 Remove deprecated bind_at_load from macOS 8 months ago
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>
8 months ago
orignal 083034fa35 send peer tests with random delays 8 months ago
R4SAS 0021501d75
[gha] disable FreeBSD build
Additional info: https://github.com/vmactions/freebsd-vm/issues/74
8 months ago
R4SAS 379be2a29e
[gha] Update FreeBSD build action 8 months ago
orignal a3f62e1d71 check actual distance with router to reduce expiration time 8 months ago
orignal a6ee1e648e recognize trailing padding as part of base64 address 8 months ago
orignal 575268d360 reduce expiration time for low bandwidth and far routers 8 months ago
orignal 69b0bef206 fixed possible invalid pointer when send error response 8 months ago
orignal e1b4feb618 correct base64 check 8 months ago
orignal 3286bdb4a7 verify jump link for valid characters 8 months ago
orignal c8ae15041f
Merge pull request #1980 from freeacetone/openssl
Yggdrasil reseed address replaced by address for 4.X+ version
8 months ago
acetone e090b9052a
Yggdrasil reseed address replaced by address for 4.X+ version 8 months ago
Dex 0ef9c08326 fix manpage typo for ipv4 flag 8 months ago
orignal d04b19d77c don't recalculate badwidth if clock was adjusted too much 8 months ago
orignal 04adc14b76 ls@mail.i2p yggdrasil reseed added 8 months ago
orignal 0dee0609ea
Merge pull request #1972 from Vort/nominmax
Fix MSVC compilation for std::max
8 months ago
Vort 0a519d8072 Fix MSVC compilation for std::max 8 months ago
orignal 0cc91dd2d2 don't pick too active peer 8 months ago
orignal 606e35eec1 reseed.us.prestium.org reseed added 9 months ago
orignal e926b0392f reseed.is.prestium.org reseed added 9 months ago
orignal 9980bfa0e7
Update README.md 9 months ago
orignal efdbe26755 try peer test again if Unknown 9 months ago
orignal bb3ae8f5e4 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 9 months ago
orignal 1e6edf06a2 send already accepting error response 9 months ago
hfsfox 0cf656cd76
Add Haiku OS support (#1970) 9 months ago
r4sas fb420bb563
[cpu] more builtin version check changes
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
r4sas 3da5061426
[cpu] Increase GCC version for use of builtin CPU extensions checker
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
orignal dd32f1ed6d
Merge pull request #1968 from PurpleI2P/cpu
[cpu] use short defines instead of long checks
9 months ago
r4sas 1857f14be8
[cpu] use short defines instead of long checks
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
r4sas 9c25a88707
[i18n] update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
r4sas c599d65307
[i18n] update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
r4sas 4d573f6655
2.49.0
Signed-off-by: r4sas <r4sas@i2pmail.org>
9 months ago
orignal 3a4238729a 2.49.0 9 months ago
orignal df6bb6d9b8 2.49.0 9 months ago
orignal 918aa556ef fixed non-x86 build 9 months ago
r4sas 1e7feae0df
[rpm] remove BuildRequires tabulation
Signed-off-by: r4sas <r4sas@i2pmail.org>
10 months ago
r4sas 70829ee79e
[rpm] add Fedora ELN support
Signed-off-by: r4sas <r4sas@i2pmail.org>
10 months ago
r4sas 4ed19c05f6
[cpu] split AES detect for GNU C < 5
Signed-off-by: r4sas <r4sas@i2pmail.org>
10 months ago
r4sas 4a5e16b994
[cpu] tests with preprocessor
Signed-off-by: r4sas <r4sas@i2pmail.org>
10 months ago
r4sas c53ad2012c
[cpu] use cpuid on gcc < 5
Signed-off-by: r4sas <r4sas@i2pmail.org>
10 months ago
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
10 months ago
జిందం వాఐి 32c5ff23a6
Differentiate cryptocurrency & its associated address (#1951) 10 months ago
orignal c112276eea memory poll for RouterProfile 10 months ago
Chad Fraleigh 662a59d0fd Eliminate additional undefined behavior of bit shifting signed int. 10 months ago
orignal 72919ec076
Merge pull request #1960 from chadf/chacha20-buf-outlen
Fixed buf offset EVP_EncryptFinal_ex() to include outlen.
11 months ago
Chad Fraleigh 627b8dca83
Fixed buf offset EVP_EncryptFinal_ex() to include outlen. 11 months ago
orignal 7bcc905f05 exclude SSU1 introducers 11 months ago
orignal 8447822c35 don't publish intrducers with zero tag 11 months ago
orignal 411063e3b5
Merge pull request #1958 from Vort/session_log
improve transport session logging
11 months ago
Vort 9bac680f2a improve transport session logging 11 months ago
orignal 38795a41cb don't publish introducers with zero iTag 11 months ago
orignal e170c39dfc
Merge pull request #1957 from Vort/peer_test
Separate test status from network status
11 months ago
Vort 68f4961f1a separate test status from network status 11 months ago
orignal ae5239de43 remove introducer from RouterInfo after 60 minutes 11 months ago
orignal 2064504cce fixed send keepalive for existing session 11 months ago
orignal 4aa631c33f clear implied list if no more introducers found 11 months ago
orignal d6834d6a9a keep non-published, but not-expired introducers in the introducers list 11 months ago
orignal 413e25f20e don't pick too old session for introducer 11 months ago
orignal b8e19bf5f1 reduced peer test interval and added peer test interval variance 11 months ago
orignal c7efd465fa padding for path response 11 months ago
orignal 6e9a3422e9 correct min size for keepalive 11 months ago
orignal d3cd8517b7
Merge pull request #1952 from Vort/explicit0hops
allow 0 hops with explicitPeers
11 months ago
Vort f13cc0b862 allow 0 hops with explicitPeers 11 months ago
orignal 0754255c1f drop incoming session from too old or from future routers 11 months ago
orignal 902899ae24 don't pick completely unreachable peers 11 months ago
orignal c620fc1232 clear unreachable flag upon succesive connect 11 months ago
orignal e7157cf15e don't create paired inbound tunnel if length is different 11 months ago
r4sas 940a97db11
[gha] fix msvc build
Signed-off-by: r4sas <r4sas@i2pmail.org>
12 months ago
orignal 8e63f8f333 consider all addresses non published for U and H routers 12 months ago
orignal 5e97b54d1b
Merge pull request #1950 from Vort/term_fix
fix termination block processing and size check
12 months ago
Vort ea7cf1cf69 fix termination block processing and size check 12 months ago
orignal 17c4038c60 select router with ipv4 for endpoint 12 months ago
orignal 5022a9c610
Merge pull request #1948 from chadf/fuzzing-5
Use offset from Identity::signingKey instead of Identity::certificate for key.
12 months ago
orignal ca8ec6286a
Merge pull request #1947 from chadf/fuzzing-4
Eliminate undefined behavior of bit shifting signed int.
12 months ago
orignal 5142459e12
Merge pull request #1945 from chadf/fuzzing-2
Fixed division by zero due to thread race condition.
12 months ago
orignal 8590dbd3d3
Merge pull request #1946 from chadf/fuzzing-3
Fixed crash when Base64ToByteStream() is only given '=' characters.
12 months ago
Chad Fraleigh c4be5f7fdb
Use offset from Identity::signingKey instead of Identity::certificate for key. 12 months ago
Chad Fraleigh 47dc5591b9
Eliminate undefined behavior of bit shifting signed int. 12 months ago
Chad Fraleigh 2bb48b4546
Fixed crash when Base64ToByteStream() is only given '=' characters. 12 months ago
Chad Fraleigh 638e9b4d7f
Fixed division by zero due to thread race condition. 12 months ago
orignal b8f998f76a don't delete BOBDestination if used by another BOBSession 12 months ago
orignal 5f43026986 check if local destination is not null 12 months ago
orignal 13f263b791 correct transport comptibility for OBEP in second attempt 1 year ago
orignal 07c529173e send current version of the subnegotiation in user/password response 1 year ago
orignal fee940238a handle SOCK5 authrosation with empty user/password 1 year ago
R4SAS ca02b5d860
debian: add compat patches for previous releases
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
r4sas fba23a4528
i18n: update translations
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas a0795d8534
set server tunnel inport in ClientContext from port (#1936)
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas 03cc6e0524
use uint16_t for ports
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas 3af1f4bc76
Use of 'server' type tunnel port as inport (#1936)
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
orignal 52b2d6c393 2.48.0 1 year ago
orignal bb52056aec correct index for connected transport 1 year ago
r4sas 75aa9f2c0c
i18n: update translation file
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
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>
1 year ago
r4sas 09f233dbfb
NetDB: ignore LeaseSet store request if not floodfill
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas dfe5df29e1
suppress build warnings on windows
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
AsciiMoth d5ee1f602f
Update dates in license (#1934)
Update copyright timestamp in LICENSE file from 2020 to actual 2023
1 year ago
orignal 86173400d5 don't drop profile of real router too early 1 year ago
r4sas ae439b5385
SSU2: check if socket is opened before sending data, handle network_reset error
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas dc6a42c26f
[contrib] update example config file comments, remove ssu option
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas fdf38f45d9
more debug messages at destinations stop
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas a2726cf206
[cmake] print commit-based version if option is used
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
r4sas e56d243c3f
[win32] suppress fallthrough warning
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
orignal e95fb3ab89 allow user/password authentication 1 year ago
orignal c984f89dfb don't handle unecnrypted DatabaseSearchReply msg if came throug client tunnel 1 year ago
orignal 5a09c11e90
Merge pull request #1927 from wekoq/refactor_TBM_handling
refactor TBM hadling
1 year ago
weko d44be2fd73 fix typo 1 year ago
weko a158647153 refactor TBM hadling 1 year ago
orignal 623c3f4605 check for max number of records in tunnel build and tunnel build reply messages 1 year ago
orignal 8a52295882 make router real upon successive outgoing NTCP2 session. Eliminate static keys table 1 year ago
orignal f2bc2598dc
Merge pull request #1925 from wekoq/openssl
Do not save useless peer profiles
1 year ago
weko 1d8a91c5cc redo no save useless profiles 1 year ago
orignal 3bc56ba423 store 'connected' in 'usage' section 1 year ago
orignal e068a3cf22 store 'connected' in 'usage' section 1 year ago
weko 2e2cbe7803 save profile if has connected 1 year ago
weko 1c1452e06b Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 1 year ago
orignal c757b6d020 reset floodfill cap for unknown floodfills 1 year ago
weko 8fcab7b0c1 fix incorrect merge conflict resolve 1 year ago
weko 7646147ed2 save only non-default peer profile 1 year ago
orignal b6de474fda don't include unconfirmed floodfill to the list if we have enough floodfills already 1 year ago
orignal 2f74e670a5 invalidate routers with incorrect family signature 1 year ago
orignal c1168c2aa0 don't catch RouterInfo at OBEP 1 year ago
orignal 1bd6390f78 check if s is x25519 public key 1 year ago
orignal a9e9e14c42
Merge pull request #1921 from contextswap/openssl
limit aes-ni assembly to x86
1 year ago
orignal 19471dbb90
Merge pull request #1922 from SidorKozlov/zombie-config
Configurable minimum successful tunnels
1 year ago
SidorKozlov 3b13a3f2a1 Configurable minimum successful tunnels 1 year ago
orignal 4ce2ef1d83 make router unreachable if AEAD fails in SessionCreated 1 year ago
contextswap 12d0abda55
[
Signed-off-by: contextswap <ctxswp@proton.me>
1 year ago
contextswap 7418f11651
limit aesni inline asm to x86
Signed-off-by: contextswap <ctxswp@proton.me>
1 year ago
orignal fb83ca42f4
Merge pull request #1919 from wekoq/openssl
Recognize invalid static key
1 year ago
weko dab34e9051 get indent hash directly 1 year ago
weko ec2297ed9d Recognize invalid static key 1 year ago
orignal 7c535159bc static keys table 1 year ago
orignal 2af4a2b58d override reply token only if non-zero 1 year ago
orignal ead6a6dca3 correct parsing of caught RouterInfo at IBGW and OBEP 1 year ago
orignal 0ce15ffc91 check for incomplete HTTP header 1 year ago
orignal 76adac31c3 enrcrypt lookup if being sent through a tunnel 1 year ago
r4sas edfcd23b01
[webconsole] added a button to prematurely release a leaseset
Signed-off-by: r4sas <r4sas@i2pmail.org>
1 year ago
orignal f21e1c75d5 check tagset for null 1 year ago
orignal 786c27c8ec publish encrypted RouterInfo 1 year ago
orignal c34df2090c don't reply to DatabaseStore messages extracted from transit 1 year ago
orignal 5769a41208 use unordered_map for LeaseSets 1 year ago
orignal dc265367dc drop unexpected I2NP messages 1 year ago
orignal c22fc75370 set router properties from incoming connections 1 year ago
orignal 6206616347 don't set unreachable twice 1 year ago
orignal 7a12b5ca4b handle incomplete HTTP header lines 1 year ago
orignal b77ae08388 exclude previously non-reachable transports 1 year ago
orignal 527ee3b3c5 check if ident is unrechable only once 1 year ago
orignal cd5bfaabb5 mark and check unreachable ident hashes 1 year ago
orignal e20acb93cf don't lookup streaming destination for each message 1 year ago
orignal 132557f941 don't return default destination if port is specified explicitly 1 year ago
orignal b8d21a1282 create non-default port destination explicitly 1 year ago
orignal 4ebc7c970a bypass medium congestion(D) routers for client tunnels 1 year ago
orignal 572694b141 check routers' congestion before recreating a tunnel 1 year ago
orignal c1f19cb258 fixed typo 1 year ago
orignal caff003a85 check for published ipv4 addresses for floodfills and IBGW 1 year ago
orignal d580c0155a fixed typo 1 year ago
orignal 9475a22728 update introducers. cleanup unreachable routers 1 year ago
orignal e3fb9d8483 fixed warning 1 year ago
orignal 220ef283de rename SendTunnelDataMsg to SendTunnelDataMsgTo for router tunnel delivery types 1 year ago
orignal 8178df752b fixed warning 1 year ago
orignal 922e5915b1 rename SendTunnelDataMsg to SendTunnelDataMsgs for multiple messages 1 year ago
orignal dc6499aa98 fixed warnings 1 year ago
orignal 0c8a80b6f8 fixed warnings 1 year ago
orignal 7c2da75197 don't recreate existing streaming destination 1 year ago
orignal b8032e7fbf publish congestion cap G 1 year ago
orignal b42be2b391
Merge pull request #1910 from wekoq/critical_log_level
Add critical log level
1 year ago
weko a3bdc4ddc1 change some log levels back 1 year ago
weko 2abc997af8 change some log levels back 1 year ago
weko 710a35993d change some log level to error back 1 year ago
weko e36d5634e7 fix log level show in webconsole 1 year ago
weko 354a04f0f6 Up level for some logs to critical 1 year ago
weko a80aeb6715 add critical log level 1 year ago
orignal cd1af85e39 bypass slow transport sessions 1 year ago
orignal 60e648bf9a set cap 6 for unspecified ipv6 address 1 year ago
orignal c45e31b1b2 validate new router 1 year ago
orignal 6d204b4d7b shorter streaming I2NP data messages 1 year ago
ralsei 71bad23906
add dinit service
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
Dimitris Apostolou d91d734b5c Fix typos 1 year ago
orignal 5fee6df87a handle reset in reposnse to SYN 1 year ago
orignal 644d65054d create smaller I2NP packets 1 year ago
orignal f41563a700 check packet number for SessionConfirmed 1 year ago
orignal 32b54fa1f8 handle i2p.streaming.answerPings properly 1 year ago
orignal 084663d6ea mediam size I2NP messages 1 year ago
orignal 55b2f2c625 memory pool for IdentityEx 1 year ago
orignal 5ad9c8e740 create I2NP tunnel message for first fragment 1 year ago
R4SAS e96f0bfb14
[msvc] fix warnings, revert cmake boost libs linking list
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 8677cd54bd
[cmake] win32: do not use static boost libs without WITH_STATIC
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS b97ef1af49
2.47.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 227697c388
[i18n] update translations
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal a6bd8275ca 2.47.0 1 year ago
orignal 6f01ebc0a5 check target destination 1 year ago
orignal 98f06e3ba1
Merge pull request #1889 from polistern/feat/sam-udp-port
Added SAM UDP port parameter
1 year ago
R4SAS b6d1d8117b
[GHA] Windows MSVC workflow (#1904) 1 year ago
R4SAS 7b35c793f3
[reseed] support domains in yggdrasil reseeder, fix IPv6 URL host parsing
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 58ef08310d
[reseed] skip records in reserved IP ranges, check Yggdrasil avalability if domain resolves in ygg address
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal ec5c13a95e add back i2p.novg.net with new certificate 1 year ago
orignal 0a564d153a reseed update 1 year ago
R4SAS 0a8da6bc2f
[cmake] msvc build revision
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 46e4f4aea5 update RouterInfo if congestion cap changed 1 year ago
orignal 6d7f20961f
Merge pull request #1902 from Vort/pool_leak
Prevent leaking of ExploratoryPool
1 year ago
Vort 4b7fcdc719 Prevent leaking of ExploratoryPool 1 year ago
orignal 716926f0d7 publish high congestion cap 1 year ago
orignal 24a14e3440 moved max num transit tunnels to Tunnels 1 year ago
Vort 5470a3a453 Eliminate memory leak in Win32NetState 1 year ago
Sergey Fedorov c02c9c3c24 Makefile.osx: do not use Intel flags on PPC 1 year ago
orignal 3154eda6a6 fixed typos 1 year ago
orignal d50cf0ad83 recognize congestion caps 1 year ago
orignal d6ed9152ee
Merge pull request #1898 from Vort/reseed_fixes
Reseed fixes
1 year ago
Vort a4759694c8 Prevent out of bounds array access 1 year ago
Vort 6610af08c2 Correct processing of reseed.floodfill option 1 year ago
orignal 4db643aa8e limited number of acked packets to 511 1 year ago
orignal 75c9f596b2
Merge pull request #1894 from Vort/remove_reseed
Remove unreachable reseed
1 year ago
Vort 064c013a72 Remove unreachable reseed 1 year ago
orignal 75ab385ab7
Merge pull request #1893 from Vort/warning_fixes
Fix several warnings
1 year ago
Vort 9e0389df1b Fix several warnings 1 year ago
orignal 1b921a2eac removed some SSU1 code 1 year ago
orignal f2729b3efe
Merge pull request #1892 from Vort/msvc_compat
Improve MSVC 2015 compatibility
1 year ago
Vort 231c02c058 Make Win32NetState compatible with MSVC 1 year ago
Vort a199084c99 Add MSVC support to CMake build 1 year ago
Vort 64f0a545fd Improve MSVC 2015 compatibility 1 year ago
Vort 34617bcb44 Code style unification across file 1 year ago
Vort 5f8820d9d6 Silence several compiler warnings 1 year ago
Vort 10dfe39f5f
Fix architecture detection in cmake build (#1890) 1 year ago
R4SAS b7f0d87daf
GHA and Cmake changes (#1888)
Done with Vort's (https://github.com/Vort) cooperation

Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
polistern 3ff1adf597
feat: Added SAM UDP port parameter. 1 year ago
orignal 93d89a1fe0 fixed typo 1 year ago
orignal 3c9a574e90 create io_service after daemonization 1 year ago
orignal de82b3ae19 don't publish non-reachable router 1 year ago
orignal 4b421d3feb publish own RouterInfo in router's thread 1 year ago
orignal f84d88ac63 publish own RouterInfo in router's thread 1 year ago
orignal 2e62f9532f separate thread for processing router's messages 1 year ago
R4SAS 5657079355
[gha] update deb build action
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS bd63383d7f
[gha] update deb build action
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS db0f2fab11
[gha] update deb build action
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS f33b0cad2e
[gha] update deb build action
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS e3fbc246f4
[gha] try to fix deb build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal d602ea1061
Merge pull request #1883 from Vort/null_fix
Remove extra null characters from webconsole output
1 year ago
orignal d40cd00cdb use DHT table for floodfills 1 year ago
orignal 692600dfac
Merge pull request #1885 from Vort/null_check
Check for null pointer before dereferencing it
1 year ago
Vort 95cc544c92 Check for null pointer before dereferencing it 1 year ago
orignal 8544283110 don't expire connected routers 1 year ago
orignal abf687ff09 store RouterInfo in DHT 1 year ago
Vort be2629aa5a Remove extra null characters from webconsole output 1 year ago
R4SAS ebee6c5f13
2.46.1-1
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 3adff82d4a don't handle ack request for router 1 year ago
R4SAS 200ad5524d
2.46.1
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 82ac0aa492
2.46.1
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal b8a99878b6 don't create profile for every new non-floodfill 1 year ago
orignal eaca435a5b find multiple closest hashes 1 year ago
orignal ce05cce331 validate LeaseSet if signature verification was not requested 1 year ago
orignal e190dab7d6 fixed crash when shows leasesets 1 year ago
orignal 289c308600 set proper caps if host is unspecified 1 year ago
orignal bff12b06f4 fixed race condition 1 year ago
orignal b8590075e6 initial commit for Kademlia DHT 1 year ago
R4SAS 1da9e2e1c0
2.46.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS a1fb97cfad
[i18n] update and add Polish, Portuguese, Turkish
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS e53fe2d988
2.46.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 182a721674 2.46.0 1 year ago
barracuda156 00c75a7afa CMakeLists.txt: update comment re Boost and atomics on PPC 1 year ago
barracuda156 385e592045 TargetArch.cmake: fix info re OSX arch support, update copyright year 1 year ago
R4SAS 359781c698
[webconsole] streams table little fix
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS c6c7191682
[debian] exclude parallel flag, remove conffiles
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal fa286a6fb3 faster GetBit 1 year ago
orignal 02a36a9fa8 don't populate buffer of unreachable router 1 year ago
R4SAS 77142e59ee
[http] fix query detection, addresshelper processing, update tests
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 4156900fb5
Merge pull request #1879 from wekoq/no_reversed_ports
Don't use reversed port for choise random port. (by whothefuckami)
1 year ago
weko 76d39cc7c9 changed to tabs, move tor port to function 1 year ago
weko 9e0c5d67c7 Don't use reversed port for choise random port. (by whothefuckami) 1 year ago
orignal 03111ad0df don't save profiles under mutex 1 year ago
orignal abb81c353d fixed race condition 1 year ago
orignal 1ad38c0b95 fixed typo 1 year ago
orignal 532a29b0c4 don't reply with unreachable router 1 year ago
orignal 4f3a416e37 send DateTime together with RouterInfo 1 year ago
orignal 4d0ad47491 GetBit for IdentHash 1 year ago
orignal 7b632bd03d set minimal floodfill version to 0.9.51 1 year ago
orignal c2faa5c614 don't try to save RouterInfo if no buffer 1 year ago
orignal d15581d95e delete invalid router after update 1 year ago
orignal 7bde4de1f5 don't try to save unreachable routers 1 year ago
orignal 88f19f551d don't save RouterInfo buffer if invalid 1 year ago
orignal d79bdc9f66 send datetime block after approximately every 250 packets 1 year ago
orignal 48a3c767e5 in-meory storage for router profiles 1 year ago
R4SAS 86fc12e395
[style] clean code
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 3c65012a63
[ssu2] close socket if it was opened on OpenSocket
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 97b7ea0da5 create separate new ipv4 and ipv6 published addresses 1 year ago
orignal 1c4cc02c23 drop garlic message in garlic clove 1 year ago
orignal ac94341203 disconnect established session if clock skew detected 1 year ago
orignal 234540f9e7
Merge pull request #1873 from Vort/ntp_desc
Fix description for nettime.enabled option
1 year ago
Vort cb44a35fde Fix description for nettime.enabled option 1 year ago
orignal 6ac849fe37
Merge pull request #1872 from Vort/log_fix
Fix debug log output
1 year ago
Vort 0829b186b7 Fix debug log output 1 year ago
orignal 993900aa77 terminate sessions if clock was adjusted backwards too much 1 year ago
orignal aac9a8d18f check if clock was adjusted backwards 1 year ago
orignal 2baaa8bb8f fixed typo 1 year ago
orignal f29ef2c057 don't compare first byte for yggdrasil addresses 1 year ago
orignal d1c98c58b9 update status before deleting session 1 year ago
orignal 4930157e93 don't innsert back unreachable router 1 year ago
orignal d30d1e8a7d don't set unrechable for routers without published addresses 1 year ago
orignal 80a55c5b75 store unrechable in profile 1 year ago
orignal 3c02cade58 compare only first 8 bytes for temporary addreses 1 year ago
orignal 21123e2afa compare published address and actual endpoint 1 year ago
orignal f1415c2234 compare published address and actual endpoint 1 year ago
orignal 212a1156a1 filter our addresses with invalid hosts 1 year ago
orignal 54fb234424 limit number of acked packets to 510 1 year ago
orignal 5a6b50ae51 fixed typo 1 year ago
orignal 21542e8150 select first hop from high bandwidth peer for client tunnels 1 year ago
orignal 544fcd147f
Merge pull request #1867 from Vort/sort_transports
Sort transports by IP:port pairs
1 year ago
Vort 9bc3b11b96 Sort transports by IP:port pairs 1 year ago
orignal 02e7f6b0c3 cleanup out of sequence packet nums in one call 1 year ago
orignal f7101cc260 fixed warning 1 year ago
orignal e9f0ed6473 cleanup out-of-sequnce list more aggressivly 1 year ago
orignal 4960587f46 cleanup out-of-sequnce list more aggressivly 1 year ago
orignal bf8eecf407 more attempts to find good peer 1 year ago
orignal 09a1a78bd6
Merge pull request #1865 from wekoq/openssl
Add parameter for show TCSR with old algorithm and it's realization
1 year ago
weko 7df2ed6114 rename and refactor 1 year ago
weko 22b1066b0a Add parameter for show TCSR with old algorithm and it's realization 1 year ago
orignal 89695a7040
Merge pull request #1864 from Vort/ipv6_brackets
enclose IPv6 address in square brackets
1 year ago
Vort 2ed281472f enclose IPv6 address in square brackets 1 year ago
orignal fafdb0c590 drop too long or too short LeaseSet 1 year ago
R4SAS 2a6883e305
[debian] add missing space in changelog (closes #1863) 1 year ago
R4SAS 3cee8bfcb2
Update tests and corresponding makefiles (#1862) 1 year ago
orignal 86dbfdb536 mutex for encrypted LeaseSet update 1 year ago
orignal 70fec2bc99 don't publish localhost addresses in RouterInfo 1 year ago
orignal 8a106eb09e fixed test-http-req 1 year ago
R4SAS f9331897b8
[gha] fix docker manifest merging
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 126ca0209b
[gha] update docker build workflow
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal ad5540c9f3 delete address if corresponding transport is disabled 1 year ago
orignal e91d0bbec8 delete address if corresponding transport is disabled 1 year ago
orignal 8ee461f60a enable all ipv4 adresses even if one is already enabled 1 year ago
orignal 4de6201b84 update RouuterInfo if NTCP2 or SSU2 keys were recreated 1 year ago
orignal 273aa31b1e try another floodfill if it's incompatible with tunnels 1 year ago
R4SAS b31f52e332
[http] keep query even if it was empty (closes #1844)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 4fae7b8d65 don't update local RouterInfo addresses in Load but in InitTransports only 1 year ago
orignal 5479ddd03c publish NTCP2 addreses by index 1 year ago
orignal 1f23584c24 update all SSU2 addresses 1 year ago
orignal 067fb45a25 exclude router from tunnel build for 2.5 minutes if doesn't reply too often 1 year ago
R4SAS ac287a896c
[websonsole] use a function to format the amount of tunnel traffic
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 8baf62eb2c
[websonsole] fix int concatenation with char strings
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS e1ec79daf2
[webconsole] format transit tunnels with table
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal d4426118c5 exclude router from tunnel build for 2.5 minutes if declined 1 year ago
orignal 64fe56aa07
Merge pull request #1854 from Vort/server_forwards_style
use correct style for Server Forwards section
1 year ago
Vort 47eb49c34e use correct style for Server Forwards section 1 year ago
orignal cd6d86c8c3 make sure that async CreateStream complete 1 year ago
R4SAS 84d4e074ce
add loglevel checker, fix fields passing to translated string formatter
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS a0e71c4173
[i18n] update strings and translation file
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 533c8a8a55
[i18n] set decimal point based on language
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS a57ae4dc56
[i18n] add sweedish translation
Translation author: corona@mail.i2p

Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS 88dfe3ca4e
[i18n] fix build on macos
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS d68c7f8ea7
[i18n] fix build on macos
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
R4SAS e8ace998ba
[i18n] add support of string formatting
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal e8be39af17 memrory pool for SSU2IncompleteMessage 1 year ago
orignal 7196db09d6
Merge pull request #1852 from freeacetone/openssl
HTTPProxy message stream correcting and comments
1 year ago
acetone b290ee1aa0 Cfg example: verbose comments for Web Console auth and addresshelper for public proxy 1 year ago
acetone d105ab11af Joining two strings to one and correct comments 1 year ago
orignal bc888167a7 use linked list for out of sequence fragments 1 year ago
R4SAS 6ca6591c43
[make] set PREFIX from DESTDIR if it present
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal 36cb707e47
Merge pull request #1849 from freeacetone/openssl
Addresshelper updating: referer check
1 year ago
acetone 013d5ff74f Addresshelper request validation by Refer-header 1 year ago
acetone 9af5a90757
Copyright year updated 1 year ago
acetone d8b6f5438c
log typo 1 year ago
acetone 10030a4e0d Addresshelper updating: referer check 1 year ago
orignal 993dc72ce6 use separate pointer to second fragment of incomplete message 1 year ago
orignal 324ace103b memoery pool for fragments 1 year ago
orignal d530269e4f try to insert received msgid instead lookup 1 year ago
orignal 7146a4dbae check if session socket was closed before tunnels were built 1 year ago
R4SAS f79900653b
Update README.md 1 year ago
orignal f172f44f32
Merge pull request #1833 from TomasGlgg/feature
Использование скользящего среднего для рассчета tunnel creation success rate
1 year ago
orignal f34abe60fa 2.45.1 1 year ago
orignal a3c305032a don't set Firewalled upon SessionCreated if ports mismatch 1 year ago
orignal 2921eaa055 differentiate symmetric and full cone NAT 1 year ago
orignal 1cc68ea402 differentiate symmetric and full cone NAT 1 year ago
orignal c18e8f6c78 drop too long LeaseSet without processing 1 year ago
orignal e59ca8420e temporary change back to C++17 1 year ago
orignal a6f9a56e40 support C++20 1 year ago
R4SAS 4011502f5f
[docker] put config in correct place
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal acd6af709e don't use netdb memory pool for local RouterInfo 1 year ago
orignal 55704ece3a drop duplicated I2NP messages 1 year ago
orignal 0d3ede56cb reject duplicated trnsit tunnel 1 year ago
R4SAS 06fae976b3
[style] update editorconfig
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
orignal e95035c143
Merge pull request #1835 from kleenexi2p/openssl
Fix segfault when UPnP is enabled
1 year ago
kleenex 55be5c74f0
Fix segfault when UPnP is enabled
Added null check.

Signed-off-by: kleenex <kleenex@i2pmail.org>
1 year ago
R4SAS a1c16e129d
[rpm] fix date
Signed-off-by: R4SAS <r4sas@i2pmail.org>
1 year ago
Tomas Globis 66f82cb43f
Use moving average to calculate tunnel creation success rate 2 years ago

@ -13,6 +13,11 @@ insert_final_newline = true
indent_style = tab
indent_size = 4
[*.cmd]
indent_style = space
indent_size = 2
end_of_line = crlf
[*.{h,cpp}]
indent_style = tab
indent_size = 4
@ -25,3 +30,10 @@ indent_size = 4
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2
[*.patch]
trim_trailing_whitespace = false

@ -1,32 +1,61 @@
name: Build Debian packages
on: [push, pull_request]
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-deb.yml
- contrib/**
- daemon/**
- debian/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build:
name: ${{ matrix.dist }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dist: ['buster', 'bullseye', 'bookworm']
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build"
- uses: jtdor/build-deb-action@v1
- name: Commit Hash
id: commit
uses: prompt/actions-commit-hash@v3.0.0
- name: Build package
uses: jtdor/build-deb-action@v1
with:
docker-image: debian:${{ matrix.dist }}-slim
buildpackage-opts: --build=binary --no-sign
- uses: actions/upload-artifact@v3
before-build-hook: debchange --controlmaint --local "+${{ steps.commit.outputs.short }}~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build"
extra-build-deps: devscripts git
- name: Upload package
uses: actions/upload-artifact@v4
with:
name: i2pd_${{ matrix.dist }}
path: debian/artifacts/i2pd_*.deb
- uses: actions/upload-artifact@v3
- name: Upload debugging symbols
uses: actions/upload-artifact@v4
with:
name: i2pd-dbgsym_${{ matrix.dist }}
path: debian/artifacts/i2pd-dbgsym_*.deb

@ -1,16 +1,37 @@
name: Build on FreeBSD
on: [push, pull_request]
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-freebsd.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.bsd
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build:
runs-on: macos-12
runs-on: ubuntu-latest
name: with UPnP
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.3.0
uses: vmactions/freebsd-vm@v1
with:
usesh: true
mem: 2048
@ -21,8 +42,9 @@ jobs:
cd build
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
gmake -j2
- name: Upload artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: i2pd-freebsd
path: build/i2pd
path: build/i2pd

@ -1,21 +1,45 @@
name: Build on OSX
on: [push, pull_request]
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-osx.yml
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.homebrew
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build:
name: With USE_UPNP=${{ matrix.with_upnp }}
runs-on: macOS-latest
strategy:
fail-fast: true
matrix:
with_upnp: ['yes', 'no']
steps:
- uses: actions/checkout@v2
- name: install packages
- name: Checkout
uses: actions/checkout@v4
- name: Install required formulae
run: |
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew update
brew install boost miniupnpc openssl@1.1
- name: build application
- name: List installed formulae
run: brew list
- name: Build application
run: make HOMEBREW=1 USE_UPNP=${{ matrix.with_upnp }} PREFIX=$GITHUB_WORKSPACE/output -j3

@ -0,0 +1,80 @@
name: Build on Windows with MSVC
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-windows-msvc.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Win32/**
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build:
name: Build
runs-on: windows-latest
env:
boost_path: ${{ github.workspace }}\boost_1_83_0
openssl_path: ${{ github.workspace }}\openssl_3_2_1
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build and install zlib
run: |
powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)"
powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings
set BUILD_TYPE=Debug
./install_zlib.bat
set BUILD_TYPE=Release
./install_zlib.bat
del install_zlib.bat
- name: Install Boost
run: |
powershell -Command "(Start-BitsTransfer -Source https://sourceforge.net/projects/boost/files/boost-binaries/1.83.0/boost_1_83_0-msvc-14.3-64.exe/download -Destination boost_1_83_0-msvc-14.3-64.exe)"
./boost_1_83_0-msvc-14.3-64.exe /DIR="${{env.boost_path}}" /VERYSILENT /SUPPRESSMSGBOXES /SP-
- name: Install OpenSSL
run: |
powershell -Command "(Start-BitsTransfer -Source https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -Destination Win64OpenSSL-3_2_1.exe)"
./Win64OpenSSL-3_2_1.exe /DIR="${{env.openssl_path}}" /TASKS="copytobin" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- name: Make copy of the OpenSSL libraries for CMake
run: |
dir ${{ github.workspace }}
dir ${{env.openssl_path}}\lib\VC
dir ${{env.openssl_path}}\lib\VC\x64\
dir ${{env.openssl_path}}\lib\VC\x64\MTd\
xcopy /s /y "${{env.openssl_path}}\lib\VC\x64\MTd" "${{env.openssl_path}}\lib"
- name: Configure
working-directory: build
run: cmake -DBoost_ROOT="${{env.boost_path}}" -DOPENSSL_ROOT_DIR="${{env.openssl_path}}" -DWITH_STATIC=ON .
- name: Build
working-directory: build
run: cmake --build . --config Debug -- -m
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: i2pd-msvc
path: build/Debug/i2pd.*

@ -1,6 +1,25 @@
name: Build on Windows
on: [push, pull_request]
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-windows.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Win32/**
- Makefile
- Makefile.mingw
tags:
- '*'
pull_request:
branches:
- '*'
defaults:
run:
@ -8,68 +27,215 @@ defaults:
jobs:
build:
name: Building using ${{ matrix.arch }} toolchain
name: ${{ matrix.arch }}
runs-on: windows-latest
strategy:
fail-fast: true
fail-fast: false
matrix:
include: [
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt },
{ msystem: MINGW64, arch: x86_64, arch_short: x64 },
{ msystem: MINGW32, arch: i686, arch_short: x86 }
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc },
{ msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang },
{ msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc },
{ msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc }
]
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
install: base-devel git mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
update: true
- name: Install additional clang packages
if: ${{ matrix.msystem == 'CLANG64' }}
run: pacman --noconfirm -S mingw-w64-${{ matrix.arch }}-gcc-compat
- name: Build application
run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3
- name: Upload artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: i2pd-${{ matrix.arch_short }}.exe
path: i2pd.exe
build-cmake:
name: CMake ${{ matrix.arch }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include: [
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc },
{ msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang },
{ msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc },
{ msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc }
]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
install: base-devel git mingw-w64-${{ matrix.arch }}-cmake mingw-w64-${{ matrix.arch }}-ninja mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
update: true
- name: Build application
run: |
cd build
cmake -DWITH_GIT_VERSION=ON -DWITH_STATIC=ON -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
cmake --build . -- -j3
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: i2pd-cmake-${{ matrix.arch_short }}.exe
path: build/i2pd.exe
build-xp:
name: Building for Windows XP
name: XP
runs-on: windows-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW32
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc
cache: true
update: true
- name: Build WinXP-capable CRT packages
- name: Clone MinGW packages repository
run: git clone https://github.com/msys2/MINGW-packages
# headers
- name: Get headers package version
id: version-headers
run: |
echo "version=$(pacman -Si mingw-w64-i686-headers-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache headers package
uses: actions/cache@v4
id: cache-headers
with:
path: MINGW-packages/mingw-w64-headers-git/*.zst
key: winxp-headers-${{ steps.version-headers.outputs.version }}
- name: Build WinXP-capable headers package
if: steps.cache-headers.outputs.cache-hit != 'true'
run: |
git clone https://github.com/msys2/MINGW-packages
pushd MINGW-packages
pushd mingw-w64-headers-git
cd MINGW-packages/mingw-w64-headers-git
sed -i 's/0x601/0x501/' PKGBUILD
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-headers-git-*-any.pkg.tar.zst
popd
pushd mingw-w64-crt-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-crt-git-*-any.pkg.tar.zst
popd
pushd mingw-w64-winpthreads-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst
popd
popd
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install headers package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-headers-git/mingw-w64-i686-*-any.pkg.tar.zst
# CRT
- name: Get crt package version
id: version-crt
run: |
echo "version=$(pacman -Si mingw-w64-i686-crt-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache crt package
uses: actions/cache@v4
id: cache-crt
with:
path: MINGW-packages/mingw-w64-crt-git/*.zst
key: winxp-crt-${{ steps.version-crt.outputs.version }}
- name: Build WinXP-capable crt package
if: steps.cache-crt.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-crt-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install crt package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-crt-git/mingw-w64-i686-*-any.pkg.tar.zst
# winpthreads
- name: Get winpthreads package version
id: version-winpthreads
run: |
echo "version=$(pacman -Si mingw-w64-i686-winpthreads-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache winpthreads package
uses: actions/cache@v4
id: cache-winpthreads
with:
path: MINGW-packages/mingw-w64-winpthreads-git/*.zst
key: winxp-winpthreads-${{ steps.version-winpthreads.outputs.version }}
- name: Build WinXP-capable winpthreads package
if: steps.cache-winpthreads.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-winpthreads-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install winpthreads package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-winpthreads-git/mingw-w64-i686-*-any.pkg.tar.zst
# OpenSSL
- name: Get openssl package version
id: version-openssl
run: |
echo "version=$(pacman -Si mingw-w64-i686-openssl | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache openssl package
uses: actions/cache@v4
id: cache-openssl
with:
path: MINGW-packages/mingw-w64-openssl/*.zst
key: winxp-openssl-${{ steps.version-openssl.outputs.version }}
- name: Build WinXP-capable openssl package
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-openssl
gpg --recv-keys D894E2CE8B3D79F5
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install openssl package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-openssl/mingw-w64-i686-*-any.pkg.tar.zst
# Boost
- name: Get boost package version
id: version-boost
run: |
echo "version=$(pacman -Si mingw-w64-i686-boost | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache boost package
uses: actions/cache@v4
id: cache-boost
with:
path: MINGW-packages/mingw-w64-boost/*.zst
key: winxp-winpthreads-${{ steps.version-boost.outputs.version }}
- name: Build WinXP-capable boost package
if: steps.cache-boost.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-boost
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install boost package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
# Building i2pd
- name: Build application
run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3
- name: Upload artifacts
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: i2pd-xp.exe
path: i2pd.exe

@ -1,38 +1,65 @@
name: Build on Ubuntu
on: [push, pull_request]
on:
push:
branches:
- '*'
paths:
- .github/workflows/build.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build-make:
name: Make with USE_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
with_upnp: ['yes', 'no']
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
- name: install packages
run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update
sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
sudo apt-get install build-essential libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
- name: build application
run: make USE_UPNP=${{ matrix.with_upnp }} -j3
build-cmake:
name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
with_upnp: ['ON', 'OFF']
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v4
- name: install packages
run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update
sudo apt-get install build-essential cmake libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
sudo apt-get install build-essential cmake libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
- name: build application
run: |
cd build

@ -5,11 +5,22 @@ on:
branches:
- openssl
- docker
paths:
- .github/workflows/docker.yml
- contrib/docker/**
- contrib/certificates/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
jobs:
build:
name: Building container for ${{ matrix.platform }}
runs-on: ubuntu-latest
permissions:
packages: write
@ -25,41 +36,44 @@ jobs:
]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container for ${{ matrix.archname }}
uses: docker/build-push-action@v3
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container for ${{ matrix.archname }}
uses: docker/build-push-action@v5
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
provenance: false
push:
name: Pushing merged manifest
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
@ -67,74 +81,60 @@ jobs:
needs: build
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:latest
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push latest manifest image to GHCR
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:latest
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Store release version to env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest image to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:latest-release
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push release manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:latest-release
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push latest manifest image to GHCR
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Store release version to env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push release manifest to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true

@ -1,6 +1,236 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.52.0] - 2024-05-12
### Added
- Separate threads for persisting RouterInfos and profiles to disk
- Give preference to address with direct connection
- Exclude addresses with incorrect static or intro key
- Avoid two firewalled routers in the row in tunnel
- Drop unsolicited database search replies
### Changed
- Increase number of hashes to 16 in exploratory lookup reply
- Reduce number of a RouterInfo lookup attempts to 5
- Reset stream RTO if outbound tunnel was changed
- Insert previously excluded floodfill back when successfully connected
- Increase maximum stream resend attempts to 9
- Reply to exploratory lookups with only confirmed routers if low tunnel build rate
- Don't accept too old RouterInfo
- Build client tunnels through confirmed routers only if low tunnel build rate
- Manage netDb requests more frequently
- Don't reply with closer than us only floodfills for lookup
### Fixed
- Crash on router lookup if exploratory pool is not ready
- Race condition in excluded peers for next lookup
- Excessive number of lookups for same destination
- Race condition with transport peers during shutdown
- Corrupted RouterInfo files
## [2.51.0] - 2024-04-06
### Added
- Non-blocking mode for UDP sockets
- Set SSU2 socket buffer size based on bandwidth limit
- Encrypted tunnel tests
- Support for multiple UDP server tunnels on one destination
- Publish medium congestion indication
- Local domain sockets for SOCKS proxy upstream
- Tunnel status "declined" in web console
- SAM error reply "Incompatible crypto" if remote destination has incompatible crypto
- Reduce amount of traffic by handling local message drops
- Keep SSU2 socket open even if it fails to bind
- Lower SSU2 resend traffic spikes
- Expiration for messages in SSU2 send queue
- Use EWMA for stream RTT estimation
- Request choking delay if too many NACKs in stream
- Allow 0ms latency for tunnel
- Randomize tunnels selection for tests
### Changed
- Upstream SOCKS proxy from SOCKS4 to SOCKS5
- Transit tunnels limit to 4 bytes. Default value to 10K
- Reply CANT_REACH_PEER if connect to ourselves in SAM
- Don't send already expired I2NP messages
- Use monotonic timer to measure tunnel test latency
- Standard NTCP2 frame doesn't exceed 16K
- Always send request through tunnels in case of restricted routes
- Don't delete connected routers from NetDb
- Send lookup reply directly to reply tunnel gateway if possible
- Reduce unreachable router ban interval to 8 minutes
- Don't request banned routers / don't try to connect to unreachable router
- Consider 'M' routers as low bandwidth
- Limit minimal received SSU2 packet size to 40 bytes
- Bob picks peer test session only if Charlie's address supports peer testing
- Reject peer test msg 2 if peer testing is not supported
- Don't request termination if SSU2 session was not established
- Set maximum SSU2 queue size depending on RTT value
- New streaming RTT calculation algorithm
- Don't double initial RTO for streams when changing tunnels
- Restore failed tunnel if test or data for inbound tunnel received
- Don't fail last remaining tunnel in pool
- Publish LeasetSet again if local destination was not ready or no tunnels
- Make more attempts to pick high bandwidth hop for client tunnel
- Reduced SSU2 session termination timeout to 165 seconds
- Reseeds list
### Fixed
- ECIESx25519 symmetric key tagset early expiration
- Encrypted LeaseSet lookup
- Outbound tunnel build fails if it's endpoint is the same as reply tunnel gateway
- I2PControl RouterManager returns invalid JSON when unknown params are passed
- Mix of data between different UDP sessions on the same server
- TARGET_OS_SIMULATOR check
- Handling of "reservedrange" param
- New NTCP2 session gets teminated upon termination of old one
- New SSU2 session gets teminated upon termination of old one
- Peer test to non-supporting router
- Streaming ackThrough off 1 if number of NACKs exceeds 255
- Race condition in ECIESx25519 tags table
- Good tunnel becomes failed
- Crash when packet comes to terminated stream
- Stream hangs during LeaseSet update
## [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
- SAM UDP port parameter
- Support domain addresses for yggdrasil reseeds
### Changed
- DHT for floodfills instead plain list
- Process router's messages in separate thread
- Don't publish non-reachable router
- Send and check target destination in first streaming SYN packet
- Reseeds list
### Fixed
- Memory leak in windows network state detection
- Reseed attempts from invalid address
## [2.46.1] - 2023-02-20
### Fixed
- Race condition while getting router's peer profile
- Creation of new router.info
- Displaying LeaseSets in the webconsole
- Crash when processing ACK request
## [2.46.0] - 2023-02-15
### Added
- Limit number of acked SSU2 packets to 511
- Localization to Swedish, Portuguese, Turkish, Polish
- Periodically send Datetime block in NTCP2 and SSU2
- Don't select random port from reserved
- In memory table for peer profiles
- Store if router was unreachable in it's peer profile
- Show IPv6 addresses in square brackets in webconsole
- Check referer when processing Addresshelper
### Changed
- Algorithm for tunnel creation success rate calculation
- Drop incoming NTCP2 and SSU2 connection if published IP doesn't match actual endpoint
- Exclude actually unreachable router from netdb for 2 hours
- Select first hop from high bandwidth peers for client tunnels
- Drop too long or too short LeaseSet
- Delete router from netdb if became invalid after update
- Terminate existing session if clock skew detected
- Close previous UDP socket if open before reopening
- Minimal version for floodfill is 0.9.51
- Sort transports by endpoints in webconsole
### Fixed
- Deadlock during processing I2NP block with Garlic in ECIES encrypted message to router
- Race condition with encrypted LeaseSets
- HTTP query detection
- Connection attempts to IPs from invalid ranges
- Publish "0.0.0.0" in RouterInfo
- Crash upon receiving PeerTest 7
- Tunnels for closed SAM session socket
- Missing NTCP2 address in RouterInfo if enabled back
## [2.45.1] - 2023-01-11
### Added
- Full Cone NAT status error
### Changed
- Drop duplicated I2NP messages in SSU2
- Set rejection code 30 if tunnel with id already exists
- Network status is always OK if peer test msg 5 received
### Fixed
- UPnP crash if SSU2 or NTCP2 is disabled
- Crash on termination for some platforms
## [2.45.0] - 2023-01-03
### Added
- Test for Symmetric NAT with peer test msgs 6 and 7

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

@ -47,6 +47,10 @@ else
LD_DEBUG = -s
endif
ifneq (, $(DESTDIR))
PREFIX = $(DESTDIR)
endif
ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
ifeq ($(HOMEBREW),1)
@ -63,17 +67,22 @@ 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
INCFLAGS += -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR)
DEFINES += -DOPENSSL_SUPPRESS_DEPRECATED
NEEDED_CXXFLAGS += -MMD -MP
ifeq ($(USE_GIT_VERSION),yes)
GIT_VERSION := $(shell git describe --tags)
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
DEFINES += -DGITVER=$(GIT_VERSION)
endif
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC))
@ -106,17 +115,17 @@ wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
## custom FLAGS to work at build-time.
obj/%.o: %.cpp | mk_obj_dir
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -c -o $@ $<
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(DEFINES) $(INCFLAGS) -c -o $@ $<
# '-' is 'ignore if missing' on first run
-include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
$(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS) $(SHLIB_LANG)
$(SHLIB): $(LIB_OBJS)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB_LANG)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
endif
$(SHLIB_CLIENT): $(LIB_CLIENT_OBJS) $(SHLIB) $(SHLIB_LANG)

@ -6,7 +6,13 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl
## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
## -std=c++11. If you want to remove this variable please do so in a way that allows setting
## custom FLAGS to work at build-time.
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
CXXVER := $(shell $(CXX) -dumpversion)
ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1
NEEDED_CXXFLAGS = -std=c++11
else # newer versions support C++17
NEEDED_CXXFLAGS = -std=c++17
endif
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread

@ -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

@ -1,41 +1,40 @@
# root directory holding homebrew
BREWROOT = /usr/local
BREWROOT = /opt/homebrew
BOOSTROOT = ${BREWROOT}/opt/boost
SSLROOT = ${BREWROOT}/opt/openssl@1.1
UPNPROOT = ${BREWROOT}/opt/miniupnpc
CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
LDFLAGS = ${LD_DEBUG}
ifndef TRAVIS
CXX = clang++
endif
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wno-overloaded-virtual
NEEDED_CXXFLAGS ?= -std=c++11
INCFLAGS ?= -I${SSLROOT}/include -I${BOOSTROOT}/include
LDFLAGS ?= ${LD_DEBUG}
DEFINES += -DMAC_OSX
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a
ifeq ($(USE_UPNP),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
endif
LDLIBS += -lpthread -ldl
else
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes)
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif
ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
DEFINES += -DUSE_UPNP
INCFLAGS += -I${UPNPROOT}/include
ifeq ($(USE_STATIC),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
else
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif
# OSX Notes
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
endif
endif
install: all

@ -20,7 +20,11 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
NEEDED_CXXFLAGS += -std=c++11
LDLIBS = -latomic
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9
NEEDED_CXXFLAGS += -std=c++17
LDLIBS = -latomic
else ifeq ($(shell expr match ${CXXVER} "1[0-9]"),2) # gcc 10+
# NEEDED_CXXFLAGS += -std=c++20
NEEDED_CXXFLAGS += -std=c++17
LDLIBS = -latomic
else # not supported
@ -54,12 +58,13 @@ endif
# UPNP Support (miniupnpc 1.5 and higher)
ifeq ($(USE_UPNP),yes)
NEEDED_CXXFLAGS += -DUSE_UPNP
DEFINES += -DUSE_UPNP
endif
ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -D__AES__ -maes
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
endif
endif

@ -4,49 +4,50 @@ USE_WIN32_APP := yes
WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static
INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static -fPIC -msse
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
# Boost libraries suffix
BOOST_SUFFIX = -mt
NEEDED_CXXFLAGS += -std=c++17
DEFINES += -DWIN32_LEAN_AND_MEAN
# UPNP Support
ifeq ($(USE_UPNP),yes)
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB
LDLIBS = -lminiupnpc
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
ifeq ($(USE_WIN32_APP), yes)
NEEDED_CXXFLAGS += -DWIN32_APP
DEFINES += -DWIN32_APP
LDFLAGS += -mwindows
DAEMON_RC += Win32/Resource.rc
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif
ifeq ($(USE_WINXP_FLAGS), yes)
NEEDED_CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
endif
ifeq ($(USE_AESNI),yes)
NEEDED_CXXFLAGS += -D__AES__ -maes
NEEDED_CXXFLAGS += -maes
LDFLAGS += -maes
DEFINES += -D__AES__
endif
ifeq ($(USE_ASLR),yes)
@ -54,4 +55,4 @@ ifeq ($(USE_ASLR),yes)
endif
obj/%.o : %.rc | mk_obj_dir
$(WINDRES) -i $< -o $@
$(WINDRES) $(DEFINES) $(INCFLAGS) --preprocessor-arg=-MMD --preprocessor-arg=-MP --preprocessor-arg=-MF$@.d -i $< -o $@

@ -1,10 +1,10 @@
CXX = clang++
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11
INCFLAGS = -I/usr/local/include
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
@ -14,7 +14,7 @@ endif
ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
DEFINES += -DUSE_UPNP
ifeq ($(USE_STATIC),yes)
LDLIBS += /usr/local/lib/libminiupnpc.a
else
@ -22,8 +22,12 @@ ifeq ($(USE_UPNP),yes)
endif
endif
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
else
CXXFLAGS += -msse
OSARCH = $(shell uname -p)
ifneq ($(OSARCH),powerpc)
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
else
CXXFLAGS += -msse
endif
endif

@ -69,12 +69,12 @@ Build instructions:
**Supported systems:**
* GNU/Linux - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml)
* CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
* Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
* GNU/Linux (Debian, Ubuntu, etc) - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml)
* CentOS, Fedora, Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
* Alpine, ArchLinux, openSUSE, Gentoo, etc.
* Windows - [![Build on Windows](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml)
* Mac OS X - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml)
* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/) [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml)
* Mac OS - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml)
* Docker image - [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml)
* Snap - [![i2pd](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![i2pd](https://snapcraft.io/i2pd/trending.svg?name=0)](https://snapcraft.io/i2pd)
* FreeBSD - [![Build on FreeBSD](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml)
* Android - [![Android CI](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml/badge.svg)](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml)
@ -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
-------

@ -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
*
@ -29,7 +29,7 @@ namespace util
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
//setlocale(LC_ALL, "Russian");
setlocale(LC_TIME, "C");
i2p::log::SetThrowFunction ([](const std::string& s)
@ -47,7 +47,7 @@ namespace util
I2PService service((PSTR)SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
LogPrint(eLogCritical, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
@ -61,10 +61,10 @@ namespace util
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
//setlocale(LC_ALL, "Russian");
setlocale(LC_TIME, "C");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App ()) return false;
if (!i2p::win32::StartWin32App (isDaemon)) return false;
#endif
bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile)

@ -1,36 +1,36 @@
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
MAINICON ICON "mask.ico"
#endif // English (United States) resources
#ifndef APSTUDIO_INVOKED
#include "Resource.rc2"
#endif // not APSTUDIO_INVOKED
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
MAINICON ICON "mask.ico"
#endif // English (United States) resources
#ifndef APSTUDIO_INVOKED
#include "Resource.rc2"
#endif // not APSTUDIO_INVOKED

@ -2,7 +2,7 @@
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
#include "../libi2pd/version.h"
#include "version.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION I2PD_VERSION_MAJOR,I2PD_VERSION_MINOR,I2PD_VERSION_MICRO,I2PD_VERSION_PATCH
@ -25,7 +25,7 @@ BEGIN
VALUE "FileDescription", "C++ I2P daemon"
VALUE "FileVersion", I2PD_VERSION
VALUE "InternalName", CODENAME
VALUE "LegalCopyright", "Copyright (C) 2013-2022, The PurpleI2P Project"
VALUE "LegalCopyright", "Copyright (C) 2013-2023, The PurpleI2P Project"
VALUE "OriginalFilename", "i2pd"
VALUE "ProductName", "Purple I2P"
VALUE "ProductVersion", I2P_VERSION

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -45,6 +45,7 @@ namespace i2p
namespace win32
{
DWORD g_GracefulShutdownEndtime = 0;
bool g_isWinService;
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
{
@ -144,30 +145,37 @@ namespace win32
s << bytes << " Bytes\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
{
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 (i2p::context.GetError () != eRouterErrorNone)
if (testing)
s << " (Test)";
if (error != eRouterErrorNone)
{
switch (i2p::context.GetError ())
switch (error)
{
case eRouterErrorClockSkew:
s << " - Clock skew";
s << " - " << tr("Clock skew");
break;
case eRouterErrorOffline:
s << " - Offline";
s << " - " << tr("Offline");
break;
case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT";
s << " - " << tr("Symmetric NAT");
break;
case eRouterErrorFullConeNAT:
s << " - " << tr("Full cone NAT");
break;
case eRouterErrorNoDescriptors:
s << " - " << tr("No Descriptors");
break;
default: ;
}
@ -178,11 +186,11 @@ namespace win32
{
s << "\n";
s << "Status: ";
ShowNetworkStatus (s, i2p::context.GetStatus ());
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
if (i2p::context.SupportsV6 ())
{
s << " / ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
}
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
@ -347,6 +355,9 @@ namespace win32
}
}
}
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
#endif
}
case WM_TRAYICON:
{
@ -416,8 +427,9 @@ namespace win32
return DefWindowProc( hWnd, uMsg, wParam, lParam);
}
bool StartWin32App ()
bool StartWin32App (bool isWinService)
{
g_isWinService = isWinService;
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
{
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
@ -446,7 +458,9 @@ namespace win32
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
}
SubscribeToEvents();
// COM requires message loop to work, which is not implemented in service mode
if (!g_isWinService)
SubscribeToEvents();
return true;
}
@ -466,7 +480,8 @@ namespace win32
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
else if(!g_isWinService)
UnSubscribeFromEvents();
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
}

@ -17,7 +17,7 @@ namespace win32
{
extern DWORD g_GracefulShutdownEndtime;
bool StartWin32App ();
bool StartWin32App (bool isWinService);
void StopWin32App ();
int RunWin32App ();
bool GracefulShutdown ();

@ -15,6 +15,7 @@ IUnknown *pUnknown = nullptr;
INetworkListManager *pNetworkListManager = nullptr;
IConnectionPointContainer *pCPContainer = nullptr;
IConnectionPoint *pConnectPoint = nullptr;
CNetworkListManagerEvent *pNetEvent = nullptr;
DWORD Cookie = 0;
void SubscribeToEvents()
@ -29,7 +30,11 @@ void SubscribeToEvents()
if (SUCCEEDED(Result))
{
VARIANT_BOOL IsConnect = VARIANT_FALSE;
#if defined(_MSC_VER)
Result = pNetworkListManager->get_IsConnectedToInternet(&IsConnect);
#else
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
#endif
if (SUCCEEDED(Result)) {
i2p::transport::transports.SetOnline (true);
LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
@ -41,8 +46,8 @@ void SubscribeToEvents()
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint);
if(SUCCEEDED(Result))
{
CNetworkListManagerEvent *NetEvent = new CNetworkListManagerEvent;
Result = pConnectPoint->Advise((IUnknown *)NetEvent, &Cookie);
pNetEvent = new CNetworkListManagerEvent;
Result = pConnectPoint->Advise((IUnknown *)pNetEvent, &Cookie);
if (SUCCEEDED(Result))
LogPrint(eLogInfo, "NetState: Successfully subscribed to NetworkListManagerEvent messages");
else
@ -59,6 +64,7 @@ void SubscribeToEvents()
void UnSubscribeFromEvents()
{
LogPrint(eLogInfo, "NetState: Unsubscribing from NetworkListManagerEvents");
try
{
if (pConnectPoint) {
@ -66,14 +72,25 @@ void UnSubscribeFromEvents()
pConnectPoint->Release();
}
if (pNetEvent)
{
pNetEvent->Release();
}
if (pCPContainer)
{
pCPContainer->Release();
}
if (pNetworkListManager)
{
pNetworkListManager->Release();
}
if (pUnknown)
{
pUnknown->Release();
}
CoUninitialize();
}

@ -15,7 +15,7 @@
#include "Log.h"
#include "Transports.h"
class CNetworkListManagerEvent : public INetworkListManagerEvents
class CNetworkListManagerEvent final : public INetworkListManagerEvents
{
public:
CNetworkListManagerEvent() : m_ref(1) { }
@ -23,17 +23,15 @@ public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
HRESULT Result = S_OK;
if (IsEqualIID(riid, IID_IUnknown)) {
*ppvObject = (IUnknown *)this;
} else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) {
*ppvObject = (INetworkListManagerEvents *)this;
} else {
Result = E_NOINTERFACE;
return E_NOINTERFACE;
}
AddRef();
return Result;
return S_OK;
}
ULONG STDMETHODCALLTYPE AddRef()

@ -21,7 +21,7 @@ BOOL I2PService::isService()
HWINSTA hWinStation = GetProcessWindowStation();
if (hWinStation != NULL)
{
USEROBJECTFLAGS uof = { 0 };
USEROBJECTFLAGS uof = { FALSE, FALSE, 0 };
if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
{
bIsService = TRUE;
@ -119,12 +119,12 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service: Start error: ", dwError);
LogPrint(eLogCritical, "Win32Service: Start error: ", dwError);
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
LogPrint(eLogError, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogCritical, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_STOPPED);
}
}
@ -162,7 +162,7 @@ void I2PService::Stop()
}
catch (...)
{
LogPrint(eLogError, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogCritical, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(dwOriginalState);
}
}
@ -191,12 +191,12 @@ void I2PService::Pause()
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service: Pause error: ", dwError);
LogPrint(eLogCritical, "Win32Service: Pause error: ", dwError);
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
LogPrint(eLogError, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogCritical, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_RUNNING);
}
}
@ -215,12 +215,12 @@ void I2PService::Continue()
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service: Continue error: ", dwError);
LogPrint(eLogCritical, "Win32Service: Continue error: ", dwError);
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
LogPrint(eLogError, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogCritical, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_PAUSED);
}
}
@ -238,11 +238,11 @@ void I2PService::Shutdown()
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service: Shutdown error: ", dwError);
LogPrint(eLogCritical, "Win32Service: Shutdown error: ", dwError);
}
catch (...)
{
LogPrint(eLogError, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogCritical, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

14
build/.gitignore vendored

@ -1,6 +1,13 @@
# Various generated files
/CMakeFiles/
/Testing/
/tests/
/.ninja_*
/arch.c
/build.ninja
/i2pd
/i2pd.exe
/i2pd.exe.debug
/libi2pd.a
/libi2pdclient.a
/libi2pdlang.a
@ -8,8 +15,13 @@
/CMakeCache.txt
/CPackConfig.cmake
/CPackSourceConfig.cmake
/CTestTestfile.cmake
/install_manifest.txt
/arch.c
/Makefile
# windows build script
i2pd*.zip
build*.log
# MVS project files
*.vcxproj
*.vcxproj.filters
*.sln

@ -1,14 +1,32 @@
cmake_minimum_required(VERSION 3.7)
cmake_policy(VERSION 3.7)
project("i2pd")
if(${CMAKE_VERSION} VERSION_LESS 3.22)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.22)
endif()
# for debugging
#set(CMAKE_VERBOSE_MAKEFILE on)
# Win32 build with cmake is not supported
if(WIN32 OR MSVC OR MSYS OR MINGW)
message(SEND_ERROR "cmake build for windows is not supported. Please use MSYS2 with makefiles in project root.")
endif()
# paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(LIBI2PD_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd_client)
set(LANG_SRC_DIR ${CMAKE_SOURCE_DIR}/i18n)
set(DAEMON_SRC_DIR ${CMAKE_SOURCE_DIR}/daemon)
include(Version)
set_version("${LIBI2PD_SRC_DIR}/version.h" PROJECT_VERSION)
project(
i2pd
VERSION ${PROJECT_VERSION}
HOMEPAGE_URL "https://i2pd.website/"
LANGUAGES C CXX
)
# configurable options
option(WITH_AESNI "Use AES-NI instructions set" ON)
@ -26,27 +44,22 @@ IF(BUILD_TESTING)
enable_testing()
ENDIF()
# paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
# Handle paths nicely
include(GNUInstallDirs)
# architecture
# Architecture
include(TargetArch)
target_architecture(ARCHITECTURE)
set(LIBI2PD_SRC_DIR ../libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
set(LANG_SRC_DIR ../i18n)
set(DAEMON_SRC_DIR ../daemon)
include(CheckAtomic)
include_directories(${LIBI2PD_SRC_DIR})
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
include_directories(${LANG_SRC_DIR})
include_directories(${DAEMON_SRC_DIR})
if(WITH_STATIC)
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif()
include_directories(${LIBI2PD_SRC_DIR})
FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp)
add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "")
@ -57,11 +70,9 @@ if(WITH_LIBRARY)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Libraries)
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
# FIXME This pulls stdafx
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp)
add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
@ -74,6 +85,7 @@ if(WITH_LIBRARY)
COMPONENT Libraries)
endif()
include_directories(${LANG_SRC_DIR})
FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp)
add_library(libi2pdlang ${LANG_SRC})
set_target_properties(libi2pdlang PROPERTIES PREFIX "")
@ -86,6 +98,8 @@ if(WITH_LIBRARY)
COMPONENT Libraries)
endif()
include_directories(${DAEMON_SRC_DIR})
set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
@ -95,6 +109,22 @@ set(DAEMON_SRC
"${DAEMON_SRC_DIR}/UPnP.cpp"
)
if(WIN32)
set(WIN32_SRC_DIR ${CMAKE_SOURCE_DIR}/Win32)
include_directories(${WIN32_SRC_DIR})
list(APPEND DAEMON_SRC
"${WIN32_SRC_DIR}/DaemonWin32.cpp"
"${WIN32_SRC_DIR}/Win32App.cpp"
"${WIN32_SRC_DIR}/Win32Service.cpp"
"${WIN32_SRC_DIR}/Win32NetState.cpp"
)
file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
endif()
if(WITH_UPNP)
add_definitions(-DUSE_UPNP)
endif()
@ -102,30 +132,44 @@ endif()
if(WITH_GIT_VERSION)
include(GetGitRevisionDescription)
git_describe(GIT_VERSION)
add_definitions(-DGITVER="${GIT_VERSION}")
add_definitions(-DGITVER=${GIT_VERSION})
endif()
if(APPLE)
add_definitions(-DMAC_OSX)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail(libssp & libc)
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
# check for c++17 & c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if(HAIKU)
add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE)
endif()
if(MSVC)
add_definitions(-DWINVER=0x0600)
add_definitions(-D_WIN32_WINNT=0x0600)
else()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail(libssp & libc)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s")
endif()
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
# check for c++17 & c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@ -157,8 +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 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()
@ -178,6 +225,7 @@ endif()
# Use std::atomic instead of GCC builtins on macOS PowerPC:
# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
# This has been fixed in Boost 1.81, nevertheless we retain the setting for the sake of compatibility.
if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
add_definitions(-DBOOST_SP_USE_STD_ATOMIC)
endif()
@ -187,10 +235,36 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(WITH_STATIC)
if(NOT MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
if(MSVC)
set(Boost_USE_STATIC_RUNTIME ON)
else()
set(Boost_USE_STATIC_RUNTIME OFF)
endif()
if(MSVC)
set(OPENSSL_MSVC_STATIC_RT ON)
endif()
set(OPENSSL_USE_STATIC_LIBS ON)
set(ZLIB_USE_STATIC_LIBS ON)
if(MSVC)
set(ZLIB_NAMES zlibstatic zlibstat)
else()
set(ZLIB_NAMES libz zlibstatic zlibstat zlib z)
endif()
if(WITH_UPNP)
set(MINIUPNPC_USE_STATIC_LIBS ON)
add_definitions(-DMINIUPNP_STATICLIB)
endif()
set(BUILD_SHARED_LIBS OFF)
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
# set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
@ -200,17 +274,23 @@ else()
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
# No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
add_definitions(-DBOOST_ATOMIC_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
if(WIN32)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
endif()
endif()
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_INCLUDE_DIRS)
find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic)
if(NOT DEFINED Boost_FOUND)
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
endif()
find_package(OpenSSL REQUIRED)
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
if(NOT DEFINED OPENSSL_FOUND)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
endif()
@ -235,8 +315,6 @@ endif()
# load includes
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
include(CheckAtomic)
# show summary
message(STATUS "---------------------------------------")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
@ -252,16 +330,34 @@ 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 "---------------------------------------")
if(WITH_BINARY)
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
if(WIN32)
add_executable("${PROJECT_NAME}" WIN32 ${DAEMON_SRC} ${WIN32_RC})
else()
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
endif()
if(WIN32)
list(APPEND MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi")
# OpenSSL may require Crypt32 library on MSVC build, which is not added by CMake lesser than 3.21
if(MSVC AND ${CMAKE_VERSION} VERSION_LESS 3.21)
list(APPEND MINGW_EXTRA "crypt32")
endif()
endif()
if(WITH_STATIC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
if(NOT MSVC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif()
endif()
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@ -274,11 +370,18 @@ if(WITH_BINARY)
list(REMOVE_AT Boost_LIBRARIES -1)
endif()
# synchronization library is incompatible with Windows 7
if(WIN32)
get_target_property(BOOSTFSLIBS Boost::filesystem INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM BOOSTFSLIBS synchronization)
set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}")
endif()
if(WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS})
endif()
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")

@ -1,4 +1,4 @@
# Copyright (c) 2017-2022, The PurpleI2P Project
# Copyright (c) 2017-2023, The PurpleI2P Project
# This file is part of Purple i2pd project and licensed under BSD3
# See full license text in LICENSE file at top of project tree
@ -18,7 +18,7 @@ set(archdetect_c_code "
|| defined(_M_ARM64) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8)
#error cmake_ARCH arm64
#if defined(__ARM_ARCH_7__) \\
#elif defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\
@ -83,13 +83,13 @@ function(target_architecture output_var)
# First let's normalize the order of the values
# Note that it's not possible to compile PowerPC applications if you are using
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
# disable it by default
# the OS X SDK version 10.7 or later - you'll need 10.4/10.5/10.6 for that, so we
# disable it by default. Also, ppc64 is not supported in 10.6.
# See this page for more information:
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise; 10.6 also supports ppc.
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
@ -133,11 +133,11 @@ function(target_architecture output_var)
enable_language(C)
# Detect the architecture in a rather creative way...
# This compiles a small C program which is a series of ifdefs that selects a
# particular #error preprocessor directive whose message string contains the
# target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of the
# #error preprocessor directives... but by exploiting the preprocessor in this
# This compiles a small C program which is a series of ifdefs that selects
# a particular #error preprocessor directive whose message string contains
# the target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of
# the #error preprocessor directives... but by exploiting the preprocessor in this
# way, we can detect the correct target architecture even when cross-compiling,
# since the program itself never needs to be run (only the compiler/preprocessor)
try_run(

@ -0,0 +1,16 @@
# read version
function(set_version version_file output_var)
file(READ "${version_file}" version_data)
string(REGEX MATCH "I2PD_VERSION_MAJOR ([0-9]*)" _ ${version_data})
set(version_major ${CMAKE_MATCH_1})
string(REGEX MATCH "I2PD_VERSION_MINOR ([0-9]*)" _ ${version_data})
set(version_minor ${CMAKE_MATCH_1})
string(REGEX MATCH "I2PD_VERSION_MICRO ([0-9]*)" _ ${version_data})
set(version_micro ${CMAKE_MATCH_1})
set(${output_var} "${version_major}.${version_minor}.${version_micro}" PARENT_SCOPE)
endfunction()

@ -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,
}

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF1zCCA7+gAwIBAgIRAMDqFR09Xuj8ZUu+oetSvAEwDQYJKoZIhvcNAQELBQAw
dTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxHjAcBgNVBAMM
FWFkbWluQHN0b3JteWNsb3VkLm9yZzAeFw0yNDAxMjUxNDE1MzBaFw0zNDAxMjUx
NDE1MzBaMHUxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx
HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR4w
HAYDVQQDDBVhZG1pbkBzdG9ybXljbG91ZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDbGX+GikPzQXr9zvkrhfO9g0l49KHLNQhUKYqd6T+PfnGo
Fm0d3ZZVVQZ045vWgroOXDGGZZWxUIlb2inRaR2DF1TxN3pPYt59RgY9ZQ9+TL7o
isY91krCRygY8EcAmHIjlfZQ9dBVcL7CfyT0MYZA5Efee9+NDHSewTfQP9T2faIE
83Fcyd93a2mIHYjKUbJnojng/wgsy8srbsEuuTok4MIQmDj+B5nz+za2FgI0/ydh
srlMt4aGJF4/DIem9z9d0zBCOkwrmtFIzjNF1mOSA8ES4m5YnKA/y9rZlRidLPGu
prbXhPVnqHeOnHMz2QCw1wbVo504kl0bMqyEz2tVWsO9ep7iZoQs2xkFAEaegYNT
QLUpwVGlyuq3wXXwopFRffOSimGSazICwWI6j+K0pOtgefNJaWrqKYvtkj1SbK2L
LBNUIENz6VnB7KPRckuX6zxC8PpOiBK9BcftfO+xAz/wC6qq3riBPw30KKSym0nC
Zp5KciDn4Phtw9PGq8Bkl8SyWl0jtFnfTB1tzJkisf2qKcNHaFTEe2JW763YLbh/
AU+8X8evFu40qLgvOgKoyy5DLy6i8zetX+3t9K0Fxt9+Vzzq6lm5V/RS8iIPPn+M
q1/3Z5kD0KQBG9h/Gl8BH+lB71ZxPAOZ3SMu8DJZcxBLVmDWqQPCr5CKnoz0swID
AQABo2IwYDAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG
AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHgYDVR0OBBcEFWFkbWluQHN0b3JteWNs
b3VkLm9yZzANBgkqhkiG9w0BAQsFAAOCAgEARWOJ69vTHMneSXYscha+4Ytjg0RM
faewJNEGj8qy/Qvh9si2bWYNPRK6BlbHFS7pRYBLAnhaeLBGVv1CCR6GUMMe74zQ
UuMeAoWU6qMDmB3GfYoZJh8sIxpwHqyJeTdeccRbZ4sX4F6u3IHPXYiU/AgbYqH7
pYXQg2lCjXZYaDFAlEf5SlYUDOhhXe5kR8Edhlrsu32/JzA1DQK0JjxKCBp+DQmA
ltdOpQtAg03fHP4ssdj7VvjIDl28iIlATwBvHrdNm7T0tYWn6TWhvxbRqvfTxfaH
MvxnPdIJwNP4/9TyQkwjwHb1h+ucho3CnxI/AxspdOvT1ElMhP6Ce6rcS9pk11Rl
x0ChsqpWwDg7KYpg0qZFSKCTBp4zBq9xoMJ6BQcgMfyl736WbsCzFTEyfifp8beg
NxUa/Qk7w7cuSPGyMIKNOmOR7FLlFbtocy8sXVsUQdqnp/edelufdNe39U9uNtY6
yoXI9//Tc6NgOwy2Oyia0slZ5qHRkB7e4USXMRzJ3p4q9eCVKjAJs81Utp7O2U+9
vhbhwWP8CAnNTT1E5WS6EKtfrdqF7wjkV+noPGLDGmrXi01J1fSMAjMfVO+7/LOL
UN+G4ybKWnEhhOO27yidN8Xx6UrCS23DBlPPQAeA74dTsTExiOxf1o1EXzcQiMyO
LAj3/Ojbi1xkWhI=
-----END CERTIFICATE-----

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF2TCCA8GgAwIBAgIQIHQPtSoFU+cUpYD8PZaWZjANBgkqhkiG9w0BAQsFADB2
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW
YXJuYXZiaGF0dDI4OEBtYWlsLmkycDAeFw0yMzAxMjUxODUzNDFaFw0zMzAxMjUx
ODUzNDFaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx
HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w
HQYDVQQDDBZhcm5hdmJoYXR0Mjg4QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAtwG73sC0jYd3fgEzZh0SveAdUd5yD35nINJRrdPSrSwY
n3i1qGe3fNLj877PvUDU+qiHH0fFZfyFkXTaq3TUp1u4YkmvaoPHy6FZlojB08lK
FBm+iJ1hifQ7MFmvIKUGv+cjlN6xSoQ0U6B2QOy6iZnBgFZ/7jbRY4iZOIj7VJtY
aodeHfy0bWe447VJovbkUi7NJPFZQS65LMcAIWcWTxrC0Gj8SmdxL3a5+hxpmmg0
+KCQvWQDdxAQjsc16sgUCdUc6cWYO4yw9H6fgdq9GJX+LnXR9OB58GsAjjlLlFoI
CZxdARDpoqcIj6AoKIanALf8yfbIyrqqJE47cuaqV9bht5MWKnXbwHplEkT4ZNkh
PnRDia7B5HY3uwbt39CBm264PEWXvWG2sozTWKQqBjmMN2cj/NFDUEqKv6BggMY1
HcqxWFKRcgKCtRvrmTmfp5l0/ou+OtUaFUg0a6Qhtb93Hj10vK6wZzidBqj0ggzB
eJDI95b89u8JgzRoOBriuMKTc91WTkOvBLkB3dgUbUpx2p8KHjvf/pppBH9u0oxp
qJFFK840DbnJydEvjKezeVe5Ax6YRSRxyEdKzRoWdvKVxb3qBBKMdCKTYEPxHPBu
JMEQVUCXJMti++1KEiQGhcfWvLyT7OewbcIZNk9XWNrxlKcGrTp9AOwaaNC5m1kC
AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZhcm5hdmJoYXR0Mjg4
QG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAHiK0ld/1PF9DIhutD660/bzBg
mF2Z76hcBqDZ8tnQai/u/RXYrH9wso9BYyrVsvk3fr6tpGT49Ian0MVpPOxMoTU2
oBEmQlYrfclQLFsOLmA0y2r1ggXzIrt69jB710Vhwdnz09oOE8rS4E2T5oDD8Wvy
Kony+AarRceqtkOlzyquc42KjzdrbHsosF7G2iGhNI6t+T3BfWJ+Q+d5sj3OIh6e
gSfvHL44E4vZt6dtofRN3MAZ60kNLF5YWyaUo3Snv9Lso1IwIz3AVr5ehv+8sFL/
KxaXdkZ5Yn2YUX7p1t4VQd+eXVPYjf1befg4PvrwSkylu3Jpee3fllZSKXeSVx9x
jpJiq5vIakqk22pnWb1Vn7xzSW1vtEG7QLjobOr1WrcGiwdv+HKiWcXJXDzKoWXs
h3VEfr51Kap8cIJv+D6lJIG9IcIhiQ6CXWBmtjWJvbdVwFBy1/3Fhaou9liHi+gK
4Yh5a5OGCzc7xjtpGaTmoLEz7NzDNOdd/r840qRDOh70izzmFZd5Gwq4hoVcPJcS
EAySwtgqK0/4d0zDd2Wg9ASJV9DnDf8QuSmHZgZ9Efs47XcWz9TvkWUS1E66AJsN
mmI1NDQ3mv3dv5+WPq+dqqYFsnx3xWL1g5Z3buk0opeuXMzoHwM7UfN8h7Q1M5+t
+XBgkaYA4iEwYKqlCQ==
-----END CERTIFICATE-----

@ -1,33 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt
MIIFvjCCA6agAwIBAgIQBnsUOmOu2oZZIwHBmQc1BDANBgkqhkiG9w0BAQsFADBt
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN
aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x
aWdvckBub3ZnLm5ldDAeFw0yMzAxMjgxNDM4MzFaFw0zMzAxMjgxNDM4MzFaMG0x
CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT
FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4
cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF
x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h
vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm
w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw
MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy
Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy
f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b
mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d
Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP
0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq
jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvLkf
bM3uiYfp9m0vgdoftyXtk2/9bHf3u5iaM0WfoJIsw1iizo/mxJl+Iy7SxLC16nV0
v5FpncVv+Z8x9dgoAYVuLq9zKfsAbpj6kuxAqw6vJMlD1TiIL3nSODV9BJLk47X5
tmvoOSj9BgvemYThTE3nj+DbuJRW5q90KyBV/LdLrQJX3k5R3FFL5tTad2LKFNZ4
vEOcYwwx6mvrkJ2lly6bAQUCtfc648Jyq+NO3Rba1fmn7gcP9zXXc5KYsj/ovyY2
OaocSF5wMhzBuPxO+M2HqbYLMAkc6/GesGds8Rm8wofuhJoI5YtqJuLKZm6nQXSc
fx6PKgbKcTIUWNFMsxyfghz9hpbg0rkvC7PtfAjtV0yaDtUum1eZeNEx1HbRWN2n
TQNCVuv0yaKC41qxqzhEybkdjL9JlgUh7VuskaCelB0lz+kgYjGu8ezOa0ua2iKq
4FC/1MbPulxN8NOt4pmbGqqoxmCdShp38wdnOBM3DsAS9f0JaQZd4CDyY4DCSfVn
xPdWk31+VXVt3Ixh1EUqZWYTRSsZApkCyYzkiZ/qPGG6FR9Hq2SuhC5o4P44k7eo
6wwBWD8a5RjsZhvr05E5yBrKXh/PjLwmtG73QC+ouR54/5xtedvdTwNS94FnNctX
FT6QGZnRwCkhPaRe1oQMzP+88pGoCfO33GBAuwUCAwEAAaNaMFgwDgYDVR0PAQH/
BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E
BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC
AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk
5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o
3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS
AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal
zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs
0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ
cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4
4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6
GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW
dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5
qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w==
AQCteAb5/bqhHr/i5CJbDzlofprXFC826c19GxQ/9Hw0kA52l0J9Q8Vz8Vy7VQyP
QNa8MCv6FeNy8a/wXp6cafyFsBtvehVQO8lFlpCgMEl2Bma43+GaCwkrM6bFNXeW
iQ9h4e1KjsUZ8cQDNEcamiJ80+xbMhBrj5bAZwKmZs8MoGEMyXKEZmcmwA+/fy1c
cx4izsOsmRXmEHXsvB9ydJHZZeKW8+r0DAtgPslwXuXHG6MuBQo7dKCqn+iMxHXV
Jxriq3yvNffdGx4maSLJrjQ1ealt/UMzql7huVSItnVFWoYf7GAELXNJ/PmqVyaK
q11LQ8W/Aud6s/bblaJrFJnK8PbPpaw4RvHoWVLYaZYmQnV2msWs5EuESBlEADbv
UklQXLMc2f9HKWPA5678nvYPrmu8IL5pMkAxgGRqmd+7vCz4lU9M5z3HObU+WRBt
qEMYyXywV8o3tbmnlDS5S5Xxf+tLZn1cxz3ZrmcHPHDbLBNdvszF3CTJH/R2sQvD
bizvYJM+p5F+GWM5mt6w0HrOut5MRlpOws/NRrkbijuVA/A45nzTtKplIFYE3qe8
q5SAbwYLc8cJcZCN3PxtWwbEv81V33abMt5QcjnWGLH5t2+1Z2KLCgKLSCQTxM8s
zBPHtUe8qtSQaElnNLILYbtJ1w67dPnGYTphHihC+CXjBg==
-----END CERTIFICATE-----

@ -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.

@ -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.

@ -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.

@ -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

@ -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"

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

@ -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:

@ -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.

@ -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

@ -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"

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

@ -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:

@ -0,0 +1,8 @@
type = bgprocess
run-as = i2pd
command = /usr/bin/i2pd --conf=/var/lib/i2pd/i2pd.conf --pidfile=/var/lib/i2pd/i2pd.pid --daemon --service
smooth-recovery = true
depends-on = ntpd
# uncomment if you want to use i2pd with yggdrasil
# depends-on = yggdrasil
pid-file = /var/lib/i2pd/i2pd.pid

@ -60,8 +60,8 @@ RUN apk update \
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl miniupnpc musl-utils libstdc++
# 3. Copy preconfigured config file and entrypoint
COPY i2pd-docker.conf "$I2PD_HOME/i2pd.conf"
RUN chown i2pd:nobody "$I2PD_HOME/i2pd.conf"
COPY i2pd-docker.conf "$DATA_DIR/i2pd.conf"
RUN chown i2pd:nobody "$DATA_DIR/i2pd.conf"
COPY entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh

@ -1,13 +1,13 @@
# i2pd
# Copyright (C) 2021-2022 PurpleI2P team
# Copyright (C) 2021-2023 PurpleI2P team
# This file is distributed under the same license as the i2pd package.
# R4SAS <r4sas@i2pmail.org>, 2021-2022.
# R4SAS <r4sas@i2pmail.org>, 2021-2023.
#
msgid ""
msgstr ""
"Project-Id-Version: i2pd\n"
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
"POT-Creation-Date: 2022-07-26 21:22\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,66 +18,73 @@ msgstr ""
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
#: daemon/HTTPServer.cpp:108
msgid "day"
msgid_plural "days"
#: daemon/HTTPServer.cpp:107
#, c-format
msgid "%d day"
msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:112
msgid "hour"
msgid_plural "hours"
#: daemon/HTTPServer.cpp:111
#, c-format
msgid "%d hour"
msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:116
msgid "minute"
msgid_plural "minutes"
#: daemon/HTTPServer.cpp:115
#, c-format
msgid "%d minute"
msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:119
msgid "second"
msgid_plural "seconds"
#: daemon/HTTPServer.cpp:118
#, c-format
msgid "%d second"
msgid_plural "%d seconds"
msgstr[0] ""
msgstr[1] ""
#. tr: Kibibit
#: daemon/HTTPServer.cpp:127 daemon/HTTPServer.cpp:155
msgid "KiB"
#. tr: Kibibyte
#: daemon/HTTPServer.cpp:126
#, c-format
msgid "%.2f KiB"
msgstr ""
#. tr: Mebibit
#: daemon/HTTPServer.cpp:129
msgid "MiB"
#. tr: Mebibyte
#: daemon/HTTPServer.cpp:128
#, c-format
msgid "%.2f MiB"
msgstr ""
#. tr: Gibibit
#: daemon/HTTPServer.cpp:131
msgid "GiB"
#. tr: Gibibyte
#: daemon/HTTPServer.cpp:130
#, c-format
msgid "%.2f GiB"
msgstr ""
#: daemon/HTTPServer.cpp:148
#: daemon/HTTPServer.cpp:147
msgid "building"
msgstr ""
#: daemon/HTTPServer.cpp:149
#: daemon/HTTPServer.cpp:148
msgid "failed"
msgstr ""
#: daemon/HTTPServer.cpp:150
#: daemon/HTTPServer.cpp:149
msgid "expiring"
msgstr ""
#: daemon/HTTPServer.cpp:151
#: daemon/HTTPServer.cpp:150
msgid "established"
msgstr ""
#: daemon/HTTPServer.cpp:152
#: daemon/HTTPServer.cpp:151
msgid "unknown"
msgstr ""
#: daemon/HTTPServer.cpp:154
#: daemon/HTTPServer.cpp:153
msgid "exploratory"
msgstr ""
@ -94,32 +101,32 @@ msgstr ""
msgid "Main page"
msgstr ""
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:700
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742
msgid "Router commands"
msgstr ""
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:382
#: daemon/HTTPServer.cpp:394
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395
#: daemon/HTTPServer.cpp:407
msgid "Local Destinations"
msgstr ""
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:352
#: daemon/HTTPServer.cpp:438 daemon/HTTPServer.cpp:444
#: daemon/HTTPServer.cpp:597 daemon/HTTPServer.cpp:640
#: daemon/HTTPServer.cpp:644
#: 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:199 daemon/HTTPServer.cpp:650
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692
msgid "Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:359
#: daemon/HTTPServer.cpp:770 daemon/HTTPServer.cpp:786
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830
msgid "Transit Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:839
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898
msgid "Transports"
msgstr ""
@ -127,15 +134,16 @@ msgstr ""
msgid "I2P tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:908
#: daemon/HTTPServer.cpp:918
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927
#: daemon/HTTPServer.cpp:937
msgid "SAM sessions"
msgstr ""
#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1302
#: daemon/HTTPServer.cpp:1305 daemon/HTTPServer.cpp:1308
#: daemon/HTTPServer.cpp:1322 daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1370 daemon/HTTPServer.cpp:1373
#: 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 ""
@ -151,14 +159,14 @@ msgstr ""
msgid "Firewalled"
msgstr ""
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:253
#: daemon/HTTPServer.cpp:325
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235
#: daemon/HTTPServer.cpp:336
msgid "Unknown"
msgstr ""
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:369
#: daemon/HTTPServer.cpp:370 daemon/HTTPServer.cpp:976
#: daemon/HTTPServer.cpp:985
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382
#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003
#: daemon/HTTPServer.cpp:1011
msgid "Proxy"
msgstr ""
@ -166,564 +174,610 @@ msgstr ""
msgid "Mesh"
msgstr ""
#: daemon/HTTPServer.cpp:237
msgid "Error"
msgstr ""
#: daemon/HTTPServer.cpp:241
#: daemon/HTTPServer.cpp:242
msgid "Clock skew"
msgstr ""
#: daemon/HTTPServer.cpp:244
#: daemon/HTTPServer.cpp:245
msgid "Offline"
msgstr ""
#: daemon/HTTPServer.cpp:247
#: daemon/HTTPServer.cpp:248
msgid "Symmetric NAT"
msgstr ""
#: daemon/HTTPServer.cpp:259
#: daemon/HTTPServer.cpp:251
msgid "Full cone NAT"
msgstr ""
#: daemon/HTTPServer.cpp:254
msgid "No Descriptors"
msgstr ""
#: daemon/HTTPServer.cpp:263
msgid "Uptime"
msgstr ""
#: daemon/HTTPServer.cpp:262
#: daemon/HTTPServer.cpp:266
msgid "Network status"
msgstr ""
#: daemon/HTTPServer.cpp:267
#: daemon/HTTPServer.cpp:271
msgid "Network status v6"
msgstr ""
#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:280
#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284
msgid "Stopping in"
msgstr ""
#: daemon/HTTPServer.cpp:287
#: daemon/HTTPServer.cpp:291
msgid "Family"
msgstr ""
#: daemon/HTTPServer.cpp:288
#: daemon/HTTPServer.cpp:292
msgid "Tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:289
#: daemon/HTTPServer.cpp:296
msgid "Total tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:298
msgid "Received"
msgstr ""
#. tr: Kibibit/s
#: daemon/HTTPServer.cpp:291 daemon/HTTPServer.cpp:294
#: daemon/HTTPServer.cpp:297
msgid "KiB/s"
#. tr: Kibibyte/s
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303
#: daemon/HTTPServer.cpp:306
#, c-format
msgid "%.2f KiB/s"
msgstr ""
#: daemon/HTTPServer.cpp:292
#: daemon/HTTPServer.cpp:301
msgid "Sent"
msgstr ""
#: daemon/HTTPServer.cpp:295
#: daemon/HTTPServer.cpp:304
msgid "Transit"
msgstr ""
#: daemon/HTTPServer.cpp:298
#: daemon/HTTPServer.cpp:307
msgid "Data path"
msgstr ""
#: daemon/HTTPServer.cpp:301
#: daemon/HTTPServer.cpp:310
msgid "Hidden content. Press on text to see."
msgstr ""
#: daemon/HTTPServer.cpp:304
#: daemon/HTTPServer.cpp:314
msgid "Router Ident"
msgstr ""
#: daemon/HTTPServer.cpp:306
#: daemon/HTTPServer.cpp:316
msgid "Router Family"
msgstr ""
#: daemon/HTTPServer.cpp:307
#: daemon/HTTPServer.cpp:317
msgid "Router Caps"
msgstr ""
#: daemon/HTTPServer.cpp:308
#: daemon/HTTPServer.cpp:318
msgid "Version"
msgstr ""
#: daemon/HTTPServer.cpp:309
#: daemon/HTTPServer.cpp:319
msgid "Our external address"
msgstr ""
#: daemon/HTTPServer.cpp:337
#. tr: Shown when router doesn't publish itself and have "Firewalled" state
#: daemon/HTTPServer.cpp:349
msgid "supported"
msgstr ""
#: daemon/HTTPServer.cpp:350
#: daemon/HTTPServer.cpp:363
msgid "Routers"
msgstr ""
#: daemon/HTTPServer.cpp:351
#: daemon/HTTPServer.cpp:364
msgid "Floodfills"
msgstr ""
#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:962
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987
msgid "Client Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:368
#: daemon/HTTPServer.cpp:381
msgid "Services"
msgstr ""
#: daemon/HTTPServer.cpp:369 daemon/HTTPServer.cpp:370
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374
#: 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:369 daemon/HTTPServer.cpp:370
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374
#: 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:417
#: daemon/HTTPServer.cpp:434
msgid "Encrypted B33 address"
msgstr ""
#: daemon/HTTPServer.cpp:426
#: daemon/HTTPServer.cpp:442
msgid "Address registration line"
msgstr ""
#: daemon/HTTPServer.cpp:431
#: daemon/HTTPServer.cpp:447
msgid "Domain"
msgstr ""
#: daemon/HTTPServer.cpp:432
#: daemon/HTTPServer.cpp:448
msgid "Generate"
msgstr ""
#: daemon/HTTPServer.cpp:433
#: 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:439
#: daemon/HTTPServer.cpp:457
msgid "Address"
msgstr ""
#: daemon/HTTPServer.cpp:439
#: daemon/HTTPServer.cpp:459
msgid "Type"
msgstr ""
#: daemon/HTTPServer.cpp:439
#: daemon/HTTPServer.cpp:460
msgid "EncType"
msgstr ""
#: daemon/HTTPServer.cpp:449 daemon/HTTPServer.cpp:655
#: 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:464 daemon/HTTPServer.cpp:484
#: daemon/HTTPServer.cpp:669 daemon/HTTPServer.cpp:689
msgid "ms"
#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514
#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731
#, c-format
msgid "%dms"
msgstr ""
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:674
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716
msgid "Outbound tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:491
#: daemon/HTTPServer.cpp:521
msgid "Tags"
msgstr ""
#: daemon/HTTPServer.cpp:491
#: daemon/HTTPServer.cpp:522
msgid "Incoming"
msgstr ""
#: daemon/HTTPServer.cpp:498 daemon/HTTPServer.cpp:501
#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535
msgid "Outgoing"
msgstr ""
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:515
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551
msgid "Destination"
msgstr ""
#: daemon/HTTPServer.cpp:499
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814
msgid "Amount"
msgstr ""
#: daemon/HTTPServer.cpp:506
#: daemon/HTTPServer.cpp:540
msgid "Incoming Tags"
msgstr ""
#: daemon/HTTPServer.cpp:514 daemon/HTTPServer.cpp:517
#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554
msgid "Tags sessions"
msgstr ""
#: daemon/HTTPServer.cpp:515
#: daemon/HTTPServer.cpp:551
msgid "Status"
msgstr ""
#: daemon/HTTPServer.cpp:524 daemon/HTTPServer.cpp:582
#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621
msgid "Local Destination"
msgstr ""
#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:941
#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960
msgid "Streams"
msgstr ""
#: daemon/HTTPServer.cpp:558
#: daemon/HTTPServer.cpp:595
msgid "Close stream"
msgstr ""
#: daemon/HTTPServer.cpp:587
#: 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:590
#: daemon/HTTPServer.cpp:629
msgid "I2CP is not enabled"
msgstr ""
#: daemon/HTTPServer.cpp:616
#: daemon/HTTPServer.cpp:658
msgid "Invalid"
msgstr ""
#: daemon/HTTPServer.cpp:619
#: daemon/HTTPServer.cpp:661
msgid "Store type"
msgstr ""
#: daemon/HTTPServer.cpp:620
#: daemon/HTTPServer.cpp:662
msgid "Expires"
msgstr ""
#: daemon/HTTPServer.cpp:625
#: daemon/HTTPServer.cpp:667
msgid "Non Expired Leases"
msgstr ""
#: daemon/HTTPServer.cpp:628
#: daemon/HTTPServer.cpp:670
msgid "Gateway"
msgstr ""
#: daemon/HTTPServer.cpp:629
#: daemon/HTTPServer.cpp:671
msgid "TunnelID"
msgstr ""
#: daemon/HTTPServer.cpp:630
#: daemon/HTTPServer.cpp:672
msgid "EndDate"
msgstr ""
#: daemon/HTTPServer.cpp:640
msgid "not floodfill"
#: daemon/HTTPServer.cpp:682
msgid "floodfill mode is disabled"
msgstr ""
#: daemon/HTTPServer.cpp:651
#: daemon/HTTPServer.cpp:693
msgid "Queue size"
msgstr ""
#: daemon/HTTPServer.cpp:701
#: daemon/HTTPServer.cpp:743
msgid "Run peer test"
msgstr ""
#: daemon/HTTPServer.cpp:706
#: daemon/HTTPServer.cpp:744
msgid "Reload tunnels configuration"
msgstr ""
#: daemon/HTTPServer.cpp:747
msgid "Decline transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:708
#: daemon/HTTPServer.cpp:749
msgid "Accept transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:712 daemon/HTTPServer.cpp:717
#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758
msgid "Cancel graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:714 daemon/HTTPServer.cpp:719
#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760
msgid "Start graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:722
#: daemon/HTTPServer.cpp:763
msgid "Force shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:723
#: daemon/HTTPServer.cpp:764
msgid "Reload external CSS styles"
msgstr ""
#: daemon/HTTPServer.cpp:726
#: 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:728
#: daemon/HTTPServer.cpp:770
msgid "Logging level"
msgstr ""
#: daemon/HTTPServer.cpp:736
#: daemon/HTTPServer.cpp:779
msgid "Transit tunnels limit"
msgstr ""
#: daemon/HTTPServer.cpp:741 daemon/HTTPServer.cpp:760
#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803
msgid "Change"
msgstr ""
#: daemon/HTTPServer.cpp:748
#: daemon/HTTPServer.cpp:791
msgid "Change language"
msgstr ""
#: daemon/HTTPServer.cpp:786
#: daemon/HTTPServer.cpp:830
msgid "no transit tunnels currently built"
msgstr ""
#: daemon/HTTPServer.cpp:902 daemon/HTTPServer.cpp:925
#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944
msgid "SAM disabled"
msgstr ""
#: daemon/HTTPServer.cpp:918
#: daemon/HTTPServer.cpp:937
msgid "no sessions currently running"
msgstr ""
#: daemon/HTTPServer.cpp:931
#: daemon/HTTPServer.cpp:950
msgid "SAM session not found"
msgstr ""
#: daemon/HTTPServer.cpp:936
#: daemon/HTTPServer.cpp:955
msgid "SAM Session"
msgstr ""
#: daemon/HTTPServer.cpp:993
#: daemon/HTTPServer.cpp:1020
msgid "Server Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:1009
#: daemon/HTTPServer.cpp:1036
msgid "Client Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1023
#: daemon/HTTPServer.cpp:1050
msgid "Server Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1223
#: daemon/HTTPServer.cpp:1250
msgid "Unknown page"
msgstr ""
#: daemon/HTTPServer.cpp:1242
#: daemon/HTTPServer.cpp:1269
msgid "Invalid token"
msgstr ""
#: daemon/HTTPServer.cpp:1300 daemon/HTTPServer.cpp:1357
#: daemon/HTTPServer.cpp:1397
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359
#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454
msgid "SUCCESS"
msgstr ""
#: daemon/HTTPServer.cpp:1300
#: daemon/HTTPServer.cpp:1327
msgid "Stream closed"
msgstr ""
#: daemon/HTTPServer.cpp:1302
#: daemon/HTTPServer.cpp:1329
msgid "Stream not found or already was closed"
msgstr ""
#: daemon/HTTPServer.cpp:1305
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365
msgid "Destination not found"
msgstr ""
#: daemon/HTTPServer.cpp:1308
#: daemon/HTTPServer.cpp:1335
msgid "StreamID can't be null"
msgstr ""
#: daemon/HTTPServer.cpp:1310 daemon/HTTPServer.cpp:1375
#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1432
msgid "Return to destination page"
msgstr ""
#: daemon/HTTPServer.cpp:1311 daemon/HTTPServer.cpp:1324
#: daemon/HTTPServer.cpp:1399
msgid "You will be redirected in 5 seconds"
#: 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:1359
msgid "LeaseSet expiration time updated"
msgstr ""
#: daemon/HTTPServer.cpp:1362
msgid "LeaseSet is not found or already expired"
msgstr ""
#: daemon/HTTPServer.cpp:1322
msgid "Transit tunnels count must not exceed 65535"
#: daemon/HTTPServer.cpp:1379
#, c-format
msgid "Transit tunnels count must not exceed %d"
msgstr ""
#: daemon/HTTPServer.cpp:1323 daemon/HTTPServer.cpp:1398
#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455
msgid "Back to commands list"
msgstr ""
#: daemon/HTTPServer.cpp:1359
#: daemon/HTTPServer.cpp:1416
msgid "Register at reg.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1360
#: daemon/HTTPServer.cpp:1417
msgid "Description"
msgstr ""
#: daemon/HTTPServer.cpp:1360
#: daemon/HTTPServer.cpp:1417
msgid "A bit information about service on domain"
msgstr ""
#: daemon/HTTPServer.cpp:1361
#: daemon/HTTPServer.cpp:1418
msgid "Submit"
msgstr ""
#: daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1424
msgid "Domain can't end with .b32.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1370
#: daemon/HTTPServer.cpp:1427
msgid "Domain must end with .i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1373
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:1393
#: daemon/HTTPServer.cpp:1450
msgid "Unknown command"
msgstr ""
#: daemon/HTTPServer.cpp:1397
#: daemon/HTTPServer.cpp:1454
msgid "Command accepted"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:163
#: libi2pd_client/HTTPProxy.cpp:166
msgid "Proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:171
#: libi2pd_client/HTTPProxy.cpp:174
msgid "Proxy info"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:179
#: libi2pd_client/HTTPProxy.cpp:182
msgid "Proxy error: Host not found"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:180
#: libi2pd_client/HTTPProxy.cpp:183
msgid "Remote host not found in router's addressbook"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:181
#: libi2pd_client/HTTPProxy.cpp:184
msgid "You may try to find this host on jump services below"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:282 libi2pd_client/HTTPProxy.cpp:297
#: libi2pd_client/HTTPProxy.cpp:331 libi2pd_client/HTTPProxy.cpp:372
#: 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:282
#: libi2pd_client/HTTPProxy.cpp:333
msgid "Proxy unable to parse your request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:297
msgid "addresshelper is not supported"
#: libi2pd_client/HTTPProxy.cpp:348
msgid "Addresshelper is not supported"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:306 libi2pd_client/HTTPProxy.cpp:315
#: libi2pd_client/HTTPProxy.cpp:392
msgid "Host"
#: libi2pd_client/HTTPProxy.cpp:373
#, c-format
msgid ""
"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>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:375
msgid "Addresshelper forced update rejected"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:306
msgid "added to router's addressbook from helper"
#: 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>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:307
msgid "Click here to proceed:"
#: libi2pd_client/HTTPProxy.cpp:384
msgid "Addresshelper request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:307 libi2pd_client/HTTPProxy.cpp:317
msgid "Continue"
#: 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:308 libi2pd_client/HTTPProxy.cpp:318
msgid "Addresshelper found"
#: libi2pd_client/HTTPProxy.cpp:395
msgid "Addresshelper adding"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:315
msgid "already in router's addressbook"
#: 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 ""
#. tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it.
#: libi2pd_client/HTTPProxy.cpp:316
msgid "Click here to update record:"
#: libi2pd_client/HTTPProxy.cpp:404
msgid "Addresshelper update"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:331
msgid "invalid request uri"
#: libi2pd_client/HTTPProxy.cpp:417
msgid "Invalid request URI"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:372
#: libi2pd_client/HTTPProxy.cpp:460
msgid "Can't detect destination host from request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:389 libi2pd_client/HTTPProxy.cpp:393
#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481
msgid "Outproxy failure"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:389
msgid "bad outproxy settings"
#: libi2pd_client/HTTPProxy.cpp:477
msgid "Bad outproxy settings"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:392
msgid "not inside I2P network, but outproxy is not enabled"
#: 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:482
msgid "unknown outproxy url"
#: libi2pd_client/HTTPProxy.cpp:569
msgid "Unknown outproxy URL"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:490
msgid "cannot resolve upstream proxy"
#: libi2pd_client/HTTPProxy.cpp:575
msgid "Cannot resolve upstream proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:498
msgid "hostname too long"
#: libi2pd_client/HTTPProxy.cpp:583
msgid "Hostname is too long"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:525
msgid "cannot connect to upstream socks proxy"
#: libi2pd_client/HTTPProxy.cpp:610
msgid "Cannot connect to upstream SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:531
msgid "Cannot negotiate with socks proxy"
#: libi2pd_client/HTTPProxy.cpp:616
msgid "Cannot negotiate with SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:573
#: libi2pd_client/HTTPProxy.cpp:658
msgid "CONNECT error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:573
msgid "Failed to Connect"
#: libi2pd_client/HTTPProxy.cpp:658
msgid "Failed to connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:584 libi2pd_client/HTTPProxy.cpp:610
msgid "socks proxy error"
#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695
msgid "SOCKS proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:592
msgid "failed to send request to upstream"
#: libi2pd_client/HTTPProxy.cpp:677
msgid "Failed to send request to upstream"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:613
msgid "No Reply From socks proxy"
#: libi2pd_client/HTTPProxy.cpp:698
msgid "No reply from SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:620
msgid "cannot connect"
#: libi2pd_client/HTTPProxy.cpp:705
msgid "Cannot connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:620
msgid "http out proxy not implemented"
#: libi2pd_client/HTTPProxy.cpp:705
msgid "HTTP out proxy not implemented"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:621
msgid "cannot connect to upstream http proxy"
#: libi2pd_client/HTTPProxy.cpp:706
msgid "Cannot connect to upstream HTTP proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:654
#: libi2pd_client/HTTPProxy.cpp:739
msgid "Host is down"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:654
#: libi2pd_client/HTTPProxy.cpp:739
msgid ""
"Can't create connection to requested host, it may be down. Please try again "
"later."

@ -1,29 +1,30 @@
`xgettext` command for extracting translation
---
```
xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
```
Regex for transforming gettext translations to our format:
---
```
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
```
```
in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
out: {"$1", "$2"},\n
```
```
in: ^#[:.](.*)$\n
out: <to empty line>
```
```
in: \n\n
out: \n
```
`xgettext` command for extracting translation
---
```
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
```
```
in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
out: {"$1", "$2"},\n
```
```
in: \n\n
out: \n
```

@ -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,15 +31,16 @@
## * 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, none)
## Log messages above this level (debug, info, *warn, error, critical, none)
## If you set it to none, logging will be disabled
# loglevel = warn
## Write full CLF-formatted date and time to log (default: write only time)
# 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,90 +71,97 @@
## 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
# user = i2pd
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, czech, french,
## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian
## and uzbek languages
# 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,
## because anyone could spoof the short domain via addresshelper and forward other users to phishing links
# addresshelper = true
## Address of a proxy server inside I2P, which is used to visit regular Internet
# outproxy = http://false.i2p
## 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
@ -161,33 +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 port 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]
@ -198,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
@ -210,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
@ -226,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]
@ -246,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]
@ -271,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

@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.45.0
Version: 2.52.0
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,7 +144,40 @@ getent passwd i2pd >/dev/null || \
%changelog
* Mon Tue 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
* Sun May 12 2024 orignal <orignal@i2pmail.org> - 2.52.0
- update to 2.52.0
* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
- update to 2.51.0
* 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
* Mon Feb 20 2023 r4sas <r4sas@i2pmail.org> - 2.46.1
- update to 2.46.1
* Wed Feb 15 2023 orignal <orignal@i2pmail.org> - 2.46.0
- update to 2.46.0
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
- update to 2.45.1
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0

@ -1,5 +1,5 @@
Name: i2pd
Version: 2.45.0
Version: 2.52.0
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,39 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun May 12 2024 orignal <orignal@i2pmail.org> - 2.52.0
- update to 2.52.0
* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
- update to 2.51.0
* 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
* Mon Feb 20 2023 r4sas <r4sas@i2pmail.org> - 2.46.1
- update to 2.46.1
* Wed Feb 15 2023 orignal <orignal@i2pmail.org> - 2.46.0
- update to 2.46.0
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
- update to 2.45.1
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0

@ -1,293 +1,293 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
******************************************************************
*
* This is style sheet for webconsole, with @media selectors for adaptive
* view on desktop and mobile devices, respecting preferred user's color
* scheme used in system/browser.
*
* Minified copy of that style sheet is bundled inside i2pd sources.
*/
:root {
--main-bg-color: #fafafa;
--main-text-color: #103456;
--main-link-color: #894c84;
--main-link-hover-color: #fafafa;
}
@media (prefers-color-scheme: dark) {
:root {
--main-bg-color: #242424;
--main-text-color: #17ab5c;
--main-link-color: #bf64b7;
--main-link-hover-color: #000000;
}
}
body {
font: 100%/1.5em sans-serif;
margin: 0;
padding: 1.5em;
background: var(--main-bg-color);
color: var(--main-text-color);
}
a, .slide label {
text-decoration: none;
color: var(--main-link-color);
}
a:hover, .slide label:hover, button[type=submit]:hover {
color: var(--main-link-hover-color);
background: var(--main-link-color);
}
a.button {
appearance: button;
text-decoration: none;
padding: 0 5px;
border: 1px solid var(--main-link-color);
}
.header {
font-size: 2.5em;
text-align: center;
margin: 1em 0;
color: var(--main-link-color);
}
.wrapper {
margin: 0 auto;
padding: 1em;
max-width: 64em;
}
.menu {
display: block;
float: left;
overflow: hidden;
padding: 4px;
max-width: 12em;
white-space: nowrap;
text-overflow: ellipsis;
}
.listitem {
display: block;
font-family: monospace;
font-size: 1.2em;
white-space: nowrap;
}
.tableitem {
font-family: monospace;
font-size: 1.2em;
white-space: nowrap;
}
.content {
float: left;
font-size: 1em;
margin-left: 2em;
padding: 4px;
max-width: 50em;
overflow: auto;
}
.tunnel.established {
color: #56B734;
}
.tunnel.expiring {
color: #D3AE3F;
}
.tunnel.failed {
color: #D33F3F;
}
.tunnel.building {
color: #434343;
}
caption {
font-size: 1.5em;
text-align: center;
color: var(--main-link-color);
}
table {
display: table;
border-collapse: collapse;
text-align: center;
}
table.extaddr {
text-align: left;
}
table.services {
width: 100%;
}
textarea {
background-color: var(--main-bg-color);
color: var(--main-text-color);
word-break: break-all;
}
.streamdest {
width: 120px;
max-width: 240px;
overflow: hidden;
text-overflow: ellipsis;
}
.slide div.slidecontent, .slide [type="checkbox"] {
display: none;
}
.slide [type="checkbox"]:checked ~ div.slidecontent {
display: block;
margin-top: 0;
padding: 0;
}
.disabled {
color: #D33F3F;
}
.enabled {
color: #56B734;
}
button[type=submit] {
background-color: transparent;
color: var(--main-link-color);
text-decoration: none;
padding: 5px;
border: 1px solid var(--main-link-color);
font-size: 14px;
}
input, select, select option {
background-color: var(--main-bg-color);
color: var(--main-link-color);
padding: 5px;
border: 1px solid var(--main-link-color);
font-size: 14px;
}
input:focus, select:focus, select option:focus {
outline: none;
}
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
}
@media screen and (max-width: 1150px) { /* adaptive style */
.wrapper {
max-width: 58em;
}
.content {
max-width: 40em;
}
}
@media screen and (max-width: 980px) {
body {
font: 100%/1.2em sans-serif;
padding: 1.2em 0 0 0;
}
.menu {
width: 100%;
max-width: unset;
display: block;
float: none;
position: unset;
font-size: 16px;
text-align: center;
}
.menu a, .commands a {
display: inline-block;
padding: 4px;
}
.content {
float: none;
margin-left: unset;
margin-top: 16px;
max-width: 100%;
width: 100%;
text-align: center;
}
a, .slide label {
display: block;
}
.header {
margin: unset;
font-size: 1.5em;
}
small {
display: block
}
a.button {
appearance: button;
text-decoration: none;
margin-top: 10px;
padding: 6px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
width: -webkit-fill-available;
}
input, select {
width: 35%;
text-align: center;
padding: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 18px;
}
table.extaddr {
margin: auto;
text-align: unset;
}
textarea {
width: -webkit-fill-available;
height: auto;
padding: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 12px;
}
button[type=submit] {
padding: 5px 15px;
background: transparent;
border: 2px solid var(--main-link-color);
cursor: pointer;
-webkit-border-radius: 5px;
border-radius: 5px;
position: relative;
height: 36px;
display: -webkit-inline-box;
margin-top: 10px;
}
}
/*
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
******************************************************************
*
* This is style sheet for webconsole, with @media selectors for adaptive
* view on desktop and mobile devices, respecting preferred user's color
* scheme used in system/browser.
*
* Minified copy of that style sheet is bundled inside i2pd sources.
*/
:root {
--main-bg-color: #fafafa;
--main-text-color: #103456;
--main-link-color: #894c84;
--main-link-hover-color: #fafafa;
}
@media (prefers-color-scheme: dark) {
:root {
--main-bg-color: #242424;
--main-text-color: #17ab5c;
--main-link-color: #bf64b7;
--main-link-hover-color: #000000;
}
}
body {
font: 100%/1.5em sans-serif;
margin: 0;
padding: 1.5em;
background: var(--main-bg-color);
color: var(--main-text-color);
}
a, .slide label {
text-decoration: none;
color: var(--main-link-color);
}
a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover {
color: var(--main-link-hover-color);
background: var(--main-link-color);
}
a.button {
appearance: button;
text-decoration: none;
padding: 0 5px;
border: 1px solid var(--main-link-color);
}
.header {
font-size: 2.5em;
text-align: center;
margin: 1em 0;
color: var(--main-link-color);
}
.wrapper {
margin: 0 auto;
padding: 1em;
max-width: 64em;
}
.menu {
display: block;
float: left;
overflow: hidden;
padding: 4px;
max-width: 12em;
white-space: nowrap;
text-overflow: ellipsis;
}
.listitem {
display: block;
font-family: monospace;
font-size: 1.2em;
white-space: nowrap;
}
.tableitem {
font-family: monospace;
font-size: 1.2em;
white-space: nowrap;
}
.content {
float: left;
font-size: 1em;
margin-left: 2em;
padding: 4px;
max-width: 50em;
overflow: auto;
}
.tunnel.established {
color: #56B734;
}
.tunnel.expiring {
color: #D3AE3F;
}
.tunnel.failed {
color: #D33F3F;
}
.tunnel.building {
color: #434343;
}
caption {
font-size: 1.5em;
text-align: center;
color: var(--main-link-color);
}
table {
display: table;
border-collapse: collapse;
text-align: center;
}
table.extaddr {
text-align: left;
}
table.services {
width: 100%;
}
textarea {
background-color: var(--main-bg-color);
color: var(--main-text-color);
word-break: break-all;
}
.streamdest {
width: 120px;
max-width: 240px;
overflow: hidden;
text-overflow: ellipsis;
}
.slide div.slidecontent, .slide [type="checkbox"] {
display: none;
}
.slide [type="checkbox"]:checked ~ div.slidecontent {
display: block;
margin-top: 0;
padding: 0;
}
.disabled {
color: #D33F3F;
}
.enabled {
color: #56B734;
}
button[type=submit] {
background-color: transparent;
color: var(--main-link-color);
text-decoration: none;
padding: 5px;
border: 1px solid var(--main-link-color);
font-size: 14px;
}
input, select, select option {
background-color: var(--main-bg-color);
color: var(--main-link-color);
padding: 5px;
border: 1px solid var(--main-link-color);
font-size: 14px;
}
input:focus, select:focus, select option:focus {
outline: none;
}
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
}
@media screen and (max-width: 1150px) { /* adaptive style */
.wrapper {
max-width: 58em;
}
.content {
max-width: 40em;
}
}
@media screen and (max-width: 980px) {
body {
font: 100%/1.2em sans-serif;
padding: 1.2em 0 0 0;
}
.menu {
width: 100%;
max-width: unset;
display: block;
float: none;
position: unset;
font-size: 16px;
text-align: center;
}
.menu a, .commands a {
display: inline-block;
padding: 4px;
}
.content {
float: none;
margin-left: unset;
margin-top: 16px;
max-width: 100%;
width: 100%;
text-align: center;
}
a, .slide label {
display: block;
}
.header {
margin: unset;
font-size: 1.5em;
}
small {
display: block
}
a.button {
appearance: button;
text-decoration: none;
margin-top: 10px;
padding: 6px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
width: -webkit-fill-available;
}
input, select {
width: 35%;
text-align: center;
padding: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 18px;
}
table.extaddr {
margin: auto;
text-align: unset;
}
textarea {
width: -webkit-fill-available;
height: auto;
padding: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 12px;
}
button[type=submit] {
padding: 5px 15px;
background: transparent;
border: 2px solid var(--main-link-color);
cursor: pointer;
-webkit-border-radius: 5px;
border-radius: 5px;
position: relative;
height: 36px;
display: -webkit-inline-box;
margin-top: 10px;
}
}

@ -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
*
@ -150,17 +150,20 @@ 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
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);
bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved);
i2p::transport::transports.SetCheckReserved(checkReserved);
i2p::context.Init ();
i2p::transport::InitTransports ();
@ -176,16 +179,16 @@ namespace util
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
uint32_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels"))
transitTunnels *= 2; // double default number of transit tunnels for floodfill
SetMaxNumTransitTunnels (transitTunnels);
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels);
/* this section also honors 'floodfill' flag, if set above */
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
if (bandwidth.length () > 0)
{
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
if (bandwidth.length () == 1 && ((bandwidth[0] >= 'K' && bandwidth[0] <= 'P') || bandwidth[0] == 'X' ))
{
i2p::context.SetBandwidth (bandwidth[0]);
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
@ -269,7 +272,7 @@ namespace util
if (hidden)
{
LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
i2p::data::netdb.SetHidden(true);
i2p::context.SetHidden(true);
}
std::string httpLang; i2p::config::GetOption("http.lang", httpLang);
@ -299,18 +302,16 @@ namespace util
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: Starting Transports");
if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu2);
if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started");
else
{
LogPrint(eLogError, "Daemon: Failed to start Transports");
LogPrint(eLogCritical, "Daemon: Failed to start Transports");
/** shut down netdb right away */
i2p::transport::transports.Stop();
i2p::data::netdb.Stop();
@ -329,15 +330,17 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: Failed to start Webconsole: ", ex.what ());
LogPrint (eLogCritical, "Daemon: Failed to start Webconsole: ", ex.what ());
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
}
}
LogPrint(eLogInfo, "Daemon: Starting Tunnels");
i2p::tunnel::tunnels.Start();
LogPrint(eLogInfo, "Daemon: Starting Router context");
i2p::context.Start();
LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start ();
@ -354,7 +357,7 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: Failed to start I2PControl: ", ex.what ());
LogPrint (eLogCritical, "Daemon: Failed to start I2PControl: ", ex.what ());
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
}
}
@ -366,6 +369,8 @@ namespace util
LogPrint(eLogInfo, "Daemon: Shutting down");
LogPrint(eLogInfo, "Daemon: Stopping Client");
i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Router context");
i2p::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
i2p::tunnel::tunnels.Stop();

@ -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
*
@ -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)
{
@ -103,18 +104,18 @@ namespace http {
int num;
if ((num = seconds / 86400) > 0) {
s << num << " " << tr("day", "days", num) << ", ";
s << ntr("%d day", "%d days", num, num) << ", ";
seconds -= num * 86400;
}
if ((num = seconds / 3600) > 0) {
s << num << " " << tr("hour", "hours", num) << ", ";
s << ntr("%d hour", "%d hours", num, num) << ", ";
seconds -= num * 3600;
}
if ((num = seconds / 60) > 0) {
s << num << " " << tr("minute", "minutes", num) << ", ";
s << ntr("%d minute", "%d minutes", num, num) << ", ";
seconds -= num * 60;
}
s << seconds << " " << tr("second", "seconds", seconds);
s << ntr("%d second", "%d seconds", seconds, seconds);
}
static void ShowTraffic (std::stringstream& s, uint64_t bytes)
@ -122,40 +123,37 @@ namespace http {
s << std::fixed << std::setprecision(2);
auto numKBytes = (double) bytes / 1024;
if (numKBytes < 1024)
s << numKBytes << " " << tr(/* tr: Kibibit */ "KiB");
s << tr(/* tr: Kibibyte */ "%.2f KiB", numKBytes);
else if (numKBytes < 1024 * 1024)
s << numKBytes / 1024 << " " << tr(/* tr: Mebibit */ "MiB");
s << tr(/* tr: Mebibyte */ "%.2f MiB", numKBytes / 1024);
else
s << numKBytes / 1024 / 1024 << " " << tr(/* tr: Gibibit */ "GiB");
s << tr(/* tr: Gibibyte */ "%.2f GiB", numKBytes / 1024 / 1024);
}
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
{
std::string state, stateText;
switch (eState) {
switch (eState)
{
case i2p::tunnel::eTunnelStateBuildReplyReceived :
case i2p::tunnel::eTunnelStatePending : state = "building"; break;
case i2p::tunnel::eTunnelStateBuildFailed :
case i2p::tunnel::eTunnelStateTestFailed :
case i2p::tunnel::eTunnelStateBuildFailed : state = "failed"; stateText = "declined"; break;
case i2p::tunnel::eTunnelStateTestFailed : state = "failed"; stateText = "test failed"; break;
case i2p::tunnel::eTunnelStateFailed : state = "failed"; break;
case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break;
case i2p::tunnel::eTunnelStateEstablished : state = "established"; break;
default: state = "unknown"; break;
}
if (state == "building") stateText = tr("building");
else if (state == "failed") stateText = tr("failed");
else if (state == "expiring") stateText = tr("expiring");
else if (state == "established") stateText = tr("established");
else stateText = tr("unknown");
if (stateText.empty ()) stateText = tr(state);
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, ";
s << " " << (int) (bytes / 1024) << "&nbsp;" << tr(/* tr: Kibibit */ "KiB") << "\r\n";
ShowTraffic(s, bytes);
s << "\r\n";
}
static void SetLogLevel (const std::string& level)
{
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
if (level == "none" || level == "critical" || level == "error" || level == "warn" || level == "info" || level == "debug")
i2p::log::Logger().SetLogLevel(level);
else {
LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted");
@ -198,7 +196,7 @@ namespace http {
if (i2p::context.AcceptsTunnels () || i2p::tunnel::tunnels.CountTransitTunnels())
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n";
s <<
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr("Transports") << "</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
@ -220,18 +218,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)
@ -245,6 +244,9 @@ namespace http {
case eRouterErrorSymmetricNAT:
s << " - " << tr("Symmetric NAT");
break;
case eRouterErrorFullConeNAT:
s << " - " << tr("Full cone NAT");
break;
case eRouterErrorNoDescriptors:
s << " - " << tr("No Descriptors");
break;
@ -259,12 +261,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))
@ -285,15 +287,20 @@ namespace http {
if (family.length () > 0)
s << "<b>"<< tr("Family") << ":</b> " << family << "<br>\r\n";
s << "<b>" << tr("Tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%<br>\r\n";
bool isTotalTCSR;
i2p::config::GetOption("http.showTotalTCSR", isTotalTCSR);
if (isTotalTCSR) {
s << "<b>" << tr("Total tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTotalTunnelCreationSuccessRate() << "%<br/>\r\n";
}
s << "<b>" << tr("Received") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ());
s << " (" << (double) i2p::transport::transports.GetInBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")<br>\r\n";
s << "<b>" << tr("Sent") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ());
s << " (" << (double) i2p::transport::transports.GetOutBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")<br>\r\n";
s << "<b>" << tr("Transit") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")<br>\r\n";
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
s << "<div class='slide'>";
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
@ -325,17 +332,18 @@ namespace http {
default:
s << tr("Unknown");
}
if (address->IsV6 ())
bool v6 = address->IsV6 ();
if (v6)
{
if (address->IsV4 ()) s << "v4";
s << "v6";
}
s << "</td>\r\n";
if (address->published)
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
s << "<td>" << (v6 ? "[" : "") << address->host.to_string() << (v6 ? "]:" : ":") << address->port << "</td>\r\n";
else
{
s << "<td>" << tr("supported");
s << "<td>" << tr(/* tr: Shown when router doesn't publish itself and have "Firewalled" state */ "supported");
if (address->port)
s << " :" << address->port;
s << "</td>\r\n";
@ -411,8 +419,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 ());
@ -424,12 +436,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";
@ -438,9 +449,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";
@ -463,7 +488,7 @@ namespace http {
}
s << "&#8658; " << it->GetTunnelID () << ":me";
if (it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
s << " ( " << tr(/* tr: Milliseconds */ "%dms", it->GetMeanLatency()) << " )";
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
s << "</div>\r\n";
}
@ -483,22 +508,26 @@ namespace http {
);
}
if (it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
s << "</div>\r\n";
}
}
s << "<br>\r\n";
s << "<b>" << tr("Tags") << "</b><br>\r\n" << tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
s << "<b>" << tr("Tags") << "</b><br>\r\n"
<< tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
if (!dest->GetSessions ().empty ()) {
std::stringstream tmp_s; uint32_t out_tags = 0;
for (const auto& it: dest->GetSessions ()) {
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
out_tags += it.second->GetNumOutgoingTags ();
}
s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-tags\" />\r\n"
<< "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n"
<< "<input type=\"checkbox\" id=\"slide-tags\" />\r\n"
<< "<div class=\"slidecontent\">\r\n"
<< "<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n"
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
} else
s << tr("Outgoing") << ": <i>0</i><br>\r\n";
s << "<br>\r\n";
@ -513,8 +542,11 @@ namespace http {
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "</td><td>" << it.second->GetState () << "</td></tr>\r\n";
ecies_sessions++;
}
s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n"
<< "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n"
<< "<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n"
<< "<div class=\"slidecontent\">\r\n<table>\r\n"
<< "<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n"
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
} else
s << tr("Tags sessions") << ": <i>0</i><br>\r\n";
s << "<br>\r\n";
@ -537,7 +569,7 @@ namespace http {
<< tr("Streams")
<< "</caption>\r\n<thead>\r\n<tr>"
<< "<th style=\"width:25px;\">StreamID</th>"
<< "<th style=\"width:5px;\" \\>" // Stream closing button column
<< "<th style=\"width:5px;\">&nbsp;</th>" // Stream closing button column
<< "<th class=\"streamdest\">Destination</th>"
<< "<th>Sent</th>"
<< "<th>Received</th>"
@ -574,6 +606,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)
@ -608,7 +642,10 @@ namespace http {
if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET)
ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
else
ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
{
ls.reset (new i2p::data::LeaseSet2 (storeType));
ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false);
}
if (!ls) return;
s << "<div class=\"leaseset listitem";
if (ls->IsExpired())
@ -639,7 +676,7 @@ namespace http {
}
else if (!i2p::context.IsFloodfill ())
{
s << "<b>" << tr("LeaseSets") << ":</b> " << tr("not floodfill") << ".<br>\r\n";
s << "<b>" << tr("LeaseSets") << ":</b> " << tr(/* Message on LeaseSets page */ "floodfill mode is disabled") << ".<br>\r\n";
}
else
{
@ -668,7 +705,7 @@ namespace http {
}
s << "&#8658; " << it->GetTunnelID () << ":me";
if (it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
s << "</div>\r\n";
}
@ -688,7 +725,7 @@ namespace http {
);
}
if (it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )";
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
s << "</div>\r\n";
}
@ -726,19 +763,21 @@ namespace http {
s << "<br>\r\n<small>" << tr("<b>Note:</b> any action done here are not persistent and not changes your config files.") << "</small>\r\n<br>\r\n";
auto loglevel = i2p::log::Logger().GetLogLevel();
s << "<b>" << tr("Logging level") << "</b><br>\r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
s << " <a class=\"button\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
uint16_t maxTunnels = GetMaxNumTransitTunnels ();
s << " <a class=\"button" << (loglevel == eLogNone ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogCritical ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=critical&token=" << token << "\"> critical </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogError ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogWarning ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogInfo ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogDebug ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
uint32_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels ();
s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n";
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
s << " <input type=\"number\" min=\"0\" max=\"65535\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
s << " <input type=\"number\" min=\"0\" max=\"" << TRANSIT_TUNNELS_LIMIT <<"\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
s << "</form>\r\n<br>\r\n";
@ -768,60 +807,71 @@ namespace http {
{
if (i2p::tunnel::tunnels.CountTransitTunnels())
{
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n";
s << "<table><thead><th>&#8658;</th><th>ID</th><th>&#8658;</th><th>" << tr("Amount") << "</th></thead><tbody class=\"tableitem\">";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
{
s << "<div class=\"listitem\">\r\n";
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
s << it->GetTunnelID () << " &#8658; ";
s << "<tr><td></td><td>" << it->GetTunnelID () << "</td><td>&#8658;</td><td>";
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
s << " &#8658; " << it->GetTunnelID ();
s << "<tr><td>&#8658;</td><td>" << it->GetTunnelID () << "</td><td></td><td>";
else
s << " &#8658; " << it->GetTunnelID () << " &#8658; ";
s << " " << it->GetNumTransmittedBytes () << "</div>\r\n";
s << "<tr><td>&#8658;</td><td>" << it->GetTunnelID () << "</td><td>&#8658;</td><td>";
ShowTraffic(s, it->GetNumTransmittedBytes ());
s << "</td></tr>\r\n";
}
s << "</div>\r\n";
s << "</tbody></table>\r\n";
}
else
{
s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr("no transit tunnels currently built") << ".<br>\r\n";
s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr(/* Message on transit tunnels page */ "no transit tunnels currently built") << ".<br>\r\n";
}
}
template<typename Sessions>
static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name)
{
auto comp = [](typename Sessions::mapped_type a, typename Sessions::mapped_type b)
{ return a->GetRemoteEndpoint() < b->GetRemoteEndpoint(); };
std::set<typename Sessions::mapped_type, decltype(comp)> sortedSessions(comp);
for (const auto& it : sessions)
{
auto ret = sortedSessions.insert(it.second);
if (!ret.second)
LogPrint(eLogError, "HTTPServer: Duplicate remote endpoint detected: ", (*ret.first)->GetRemoteEndpoint());
}
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
for (const auto& it: sessions )
for (const auto& it: sortedSessions)
{
auto endpoint = it.second->GetRemoteEndpoint ();
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v4 ())
auto endpoint = it->GetRemoteEndpoint ();
if (it && it->IsEstablished () && endpoint.address ().is_v4 ())
{
tmp_s << "<div class=\"listitem\">\r\n";
if (it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
if (it->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< endpoint.address ().to_string () << ":" << endpoint.port ();
if (!it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
tmp_s << " [itag:" << it.second->GetRelayTag () << "]";
if (it.second->GetSendQueueSize () > 0)
tmp_s << " [queue:" << it.second->GetSendQueueSize () << "]";
if (!it->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]";
if (it->GetRelayTag ())
tmp_s << " [itag:" << it->GetRelayTag () << "]";
if (it->GetSendQueueSize () > 0)
tmp_s << " [queue:" << it->GetSendQueueSize () << "]";
if (it->IsSlow ()) tmp_s << " [slow]";
tmp_s << "</div>\r\n" << std::endl;
cnt++;
}
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v6 ())
if (it && it->IsEstablished () && endpoint.address ().is_v6 ())
{
tmp_s6 << "<div class=\"listitem\">\r\n";
if (it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
if (it->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
if (!it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]";
if (it.second->GetSendQueueSize () > 0)
tmp_s6 << " [queue:" << it.second->GetSendQueueSize () << "]";
if (!it->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]";
if (it->GetRelayTag ())
tmp_s6 << " [itag:" << it->GetRelayTag () << "]";
if (it->GetSendQueueSize () > 0)
tmp_s6 << " [queue:" << it->GetSendQueueSize () << "]";
tmp_s6 << "</div>\r\n" << std::endl;
cnt6++;
}
@ -881,7 +931,7 @@ namespace http {
s << "</div>\r\n";
}
else
s << "<b>" << tr("SAM sessions") << ":</b> " << tr("no sessions currently running") << ".<br>\r\n";
s << "<b>" << tr("SAM sessions") << ":</b> " << tr(/* Message on SAM sessions page */ "no sessions currently running") << ".<br>\r\n";
}
void ShowSAMSession (std::stringstream& s, const std::string& id)
@ -925,34 +975,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 ()) {
@ -990,7 +1048,7 @@ namespace http {
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
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;
@ -1200,7 +1258,7 @@ namespace http {
url.parse_query(params);
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
std::string redirect = "5; url=" + webroot + "?page=commands";
std::string redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=commands";
std::string token = params["token"];
if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ())
@ -1274,20 +1332,50 @@ namespace http {
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("StreamID can't be null") << "<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 5 seconds") << "</b>";
redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32;
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_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);
if (limit > 0 && limit <= 65535)
SetMaxNumTransitTunnels (limit);
if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT)
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (limit);
else {
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Transit tunnels count must not exceed 65535") << "\r\n<br>\r\n<br>\r\n";
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Transit tunnels count must not exceed %d", TRANSIT_TUNNELS_LIMIT) << "\r\n<br>\r\n<br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a>\r\n<br>\r\n";
s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
res.add_header("Refresh", redirect.c_str());
return;
}
@ -1362,7 +1450,7 @@ namespace http {
s << "<b>" << tr("SUCCESS") << "</b>:&nbsp;" << tr("Command accepted") << "<br><br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a><br>\r\n";
s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
res.add_header("Refresh", redirect.c_str());
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -24,6 +24,8 @@ namespace http
{
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds
const int TRANSIT_TUNNELS_LIMIT = 1000000;
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
{

@ -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
*
@ -38,7 +38,7 @@ namespace http
"@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n"
"body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n"
"a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n"
"a:hover, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
"a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
"a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n"
".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n"
".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n"

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -338,10 +338,11 @@ namespace client
{
for (auto it = params.begin (); it != params.end (); it++)
{
if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first);
auto it1 = m_RouterManagerHandlers.find (it->first);
if (it1 != m_RouterManagerHandlers.end ()) {
if (it1 != m_RouterManagerHandlers.end ())
{
if (it != params.begin ()) results << ",";
(this->*(it1->second))(results);
} else
LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first);

@ -1,10 +1,15 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifdef USE_UPNP
#include <string>
#include <thread>
#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
#include "Log.h"
#include "RouterContext.h"
@ -110,10 +115,16 @@ namespace transport
return;
}
#if (MINIUPNPC_API_VERSION >= 18)
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr),
m_externalIPAddress, sizeof (m_externalIPAddress));
#else
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
#endif
m_upnpUrlsInitialized=err!=0;
if (err == UPNP_IGD_VALID_CONNECTED)
{
#if (MINIUPNPC_API_VERSION < 18)
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS)
{
@ -121,6 +132,7 @@ namespace transport
return;
}
else
#endif
{
LogPrint (eLogError, "UPnP: Found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0])
@ -163,14 +175,14 @@ namespace transport
if (!a) return;
for (const auto& address : *a)
{
if (!address->host.is_v6 () && address->port)
if (address && !address->host.is_v6 () && address->port)
TryPortMapping (address);
}
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
m_Timer.expires_from_now (boost::posix_time::minutes(UPNP_PORT_FORWARDING_INTERVAL)); // every 20 minutes
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
PortMapping ();
PortMapping ();
});
}
@ -215,7 +227,7 @@ namespace transport
if (!a) return;
for (const auto& address : *a)
{
if (!address->host.is_v6 () && address->port)
if (address && !address->host.is_v6 () && address->port)
CloseMapping (address);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -28,7 +28,8 @@ namespace i2p
namespace transport
{
const int UPNP_RESPONSE_TIMEOUT = 2000; // in milliseconds
const int UPNP_PORT_FORWARDING_INTERVAL = 20; // in minutes
enum
{
UPNP_IGD_NONE = 0,

@ -162,18 +162,27 @@ namespace i2p
#ifndef ANDROID
if (lockf(pidFH, F_TLOCK, 0) != 0)
#else
struct flock fl;
fl.l_len = 0;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
if (fcntl(pidFH, F_SETLK, &fl) != 0)
#endif
{
LogPrint(eLogError, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno));
std::cerr << "i2pd: Could not lock pid file " << pidfile << ": " << strerror(errno) << std::endl;
return false;
}
#endif
char pid[10];
sprintf(pid, "%d\n", getpid());
ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 0)
{
LogPrint(eLogError, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno));
LogPrint(eLogCritical, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno));
std::cerr << "i2pd: Could not write pidfile " << pidfile << ": " << strerror(errno) << std::endl;
return false;
}

72
debian/changelog vendored

@ -1,3 +1,75 @@
i2pd (2.52.0-1) unstable; urgency=medium
* updated to version 2.52.0
-- orignal <orignal@i2pmail.org> Sun, 12 May 2024 16:00:00 +0000
i2pd (2.51.0-1) unstable; urgency=medium
* updated to version 2.51.0/0.9.62
-- orignal <orignal@i2pmail.org> Sat, 06 Apr 2024 16:00:00 +0000
i2pd (2.50.2-1) 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
-- orignal <orignal@i2pmail.org> Sat, 11 Mar 2023 16:00:00 +0000
i2pd (2.46.1-2) unstable; urgency=critical
* re-pushed release due to new critical bug
-- r4sas <r4sas@i2pmail.org> Mon, 20 Feb 2023 23:40:00 +0000
i2pd (2.46.1-1) unstable; urgency=high
* updated to version 2.46.1/0.9.57
-- r4sas <r4sas@i2pmail.org> Mon, 20 Feb 2023 02:45:00 +0000
i2pd (2.46.0-1) unstable; urgency=high
* updated to version 2.46.0/0.9.57
-- orignal <orignal@i2pmail.org> Wed, 15 Feb 2023 19:00:00 +0000
i2pd (2.45.1-1) unstable; urgency=medium
* updated to version 2.45.1/0.9.57
-- orignal <orignal@i2pmail.org> Wed, 11 Jan 2023 19:00:00 +0000
i2pd (2.45.0-1) unstable; urgency=high
* updated to version 2.45.0/0.9.57

2
debian/conffiles vendored

@ -1,2 +0,0 @@
/etc/i2pd/i2pd.conf
/etc/i2pd/tunnels.conf

2
debian/i2pd.1 vendored

@ -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/rules vendored

@ -8,6 +8,6 @@ export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND =
%:
dh $@ --parallel
dh $@
override_dh_auto_install:

@ -64,10 +64,10 @@ namespace afrikaans // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"dag", "dae"}},
{"hours", {"uur", "ure"}},
{"minutes", {"minuut", "minute"}},
{"seconds", {"seconde", "sekondes"}},
{"%d days", {"%d dag", "%d dae"}},
{"%d hours", {"%d uur", "%d ure"}},
{"%d minutes", {"%d minuut", "%d minute"}},
{"%d seconds", {"%d seconde", "%d sekondes"}},
{"", {"", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,15 +31,16 @@ namespace armenian // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "ԿիԲ"},
{"MiB", "ՄիԲ"},
{"GiB", "ԳիԲ"},
{"%.2f KiB", "%.2f ԿիԲ"},
{"%.2f MiB", "%.2f ՄիԲ"},
{"%.2f GiB", "%.2f ԳիԲ"},
{"building", "կառուցվում է"},
{"failed", "Անհաջող"},
{"expiring", "Լրանում է"},
{"established", "կարգավոյված է"},
{"unknown", "անհայտ"},
{"exploratory", "հետազոտոկան"},
{"Purple I2P Webconsole", "Վեբ-կոնսոլ Purple I2P"},
{"<b>i2pd</b> webconsole", "Վեբ-կոնսոլ <b>i2pd</b>"},
{"Main page", "Գլխավոր էջ"},
{"Router commands", "Երթուղիչի հրահանգներ"},
@ -57,10 +58,10 @@ namespace armenian // language namespace
{"Unknown", "Անհայտ"},
{"Proxy", "Պրոկսի"},
{"Mesh", "MESH-ցանց"},
{"Error", "Սխալ"},
{"Clock skew", "Ոչ ճշգրիտ ժամանակ"},
{"Offline", "Օֆլայն"},
{"Symmetric NAT", "Սիմետրիկ NAT"},
{"Full cone NAT", "Full cone NAT"},
{"Uptime", "Առկայություն"},
{"Network status", "Ցանցի կարգավիճակ"},
{"Network status v6", "Ցանցի կարգավիճակ v6"},
@ -68,7 +69,7 @@ namespace armenian // language namespace
{"Family", "Խմբատեսակ"},
{"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"},
{"Received", "Ստացվել է"},
{"KiB/s", "ԿիԲ/վ"},
{"%.2f KiB/s", "%.2f ԿիԲ/վ"},
{"Sent", "Ուղարկվել է"},
{"Transit", "Տարանցում"},
{"Data path", "Տվյալների ուղին"},
@ -89,12 +90,12 @@ namespace armenian // language namespace
{"Address registration line", "Հասցեի գրանցման տող"},
{"Domain", "Տիրույթ"},
{"Generate", "Գեներացնել"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b> Նշում. </b> արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել 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> Նշում. </b> արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել i2pd-tools գործիքակազմը:"},
{"Address", "Հասցե"},
{"Type", "Տեսակը"},
{"EncType", "Գաղտնագրի տեսակը"},
{"Inbound tunnels", "Մուտքային թունելներ"},
{"ms", "մլվ"},
{"%dms", "%dմլվ"},
{"Outbound tunnels", "Ելքային թունելներ"},
{"Tags", "Թեգեր"},
{"Incoming", "Մուտքային"},
@ -112,11 +113,10 @@ namespace armenian // language namespace
{"Invalid", "Անվավեր"},
{"Store type", "Պահեստավորման տեսակը"},
{"Expires", "Սպառվում է"},
{"Non Expired Leases", "Չսպառված Lease-եր"},
{"Non Expired Leases", "Չսպառված Lease-եր"},
{"Gateway", "Դարպաս"},
{"TunnelID", "Թունելի ID"},
{"EndDate", "Ավարտ"},
{"not floodfill", "ոչ floodfill-ներ"},
{"Queue size", "Հերթի չափսը"},
{"Run peer test", "Գործարկել փորձարկումը"},
{"Decline transit tunnels", "Մերժել տարանցիկ թունելներ"},
@ -146,10 +146,7 @@ namespace armenian // language namespace
{"Destination not found", "Հասցեի վայրը չի գտնվել"},
{"StreamID can't be null", "StreamID-ն չի կարող լինել դատարկ"},
{"Return to destination page", "Վերադառնալ նախորդ էջի հասցե"},
{"You will be redirected in 5 seconds", "Դուք կտեղափոխվեք 5 վայրկյանից"},
{"Transit tunnels count must not exceed 65535", "Տարանցիկ թունելների քանակը չպետք է գերազանցի 65535-ը"},
{"Back to commands list", "Վերադառնալ հրահանգների ցուցակ"},
{"Register at reg.i2p", "Գրանցել reg.i2p-ում"},
{"Description", "Նկարագրություն"},
{"A bit information about service on domain", "Մի փոքր տեղեկատվություն տիրոիյթում գտնվող ծառայության մասին"},
{"Submit", "Ուղարկվել"},
@ -165,43 +162,35 @@ namespace armenian // language namespace
{"You may try to find this host on jump services below", "Ստորև Դուք կարող եք գտնել այս հոսթը jump ծառայությունների միջոցով"},
{"Invalid request", "Սխալ հարցում"},
{"Proxy unable to parse your request", "Պրոկսին չի կարող հասկանալ Ձեր հարցումը"},
{"addresshelper is not supported", "addresshelper-ը համատեղելի չէ"},
{"Host", "Հոսթ"},
{"added to router's addressbook from helper", "Ավելացված է երթուղիչի հասցեագրքում helper-ի միջոցով"},
{"Click here to proceed:", "Շարունակելու համար սեղմեք այստեղ"},
{"Continue", "Շարունակել"},
{"Addresshelper found", "addresshelper-ը գնտված է"},
{"already in router's addressbook", "արդեն առկա է երթուղիչի հասցեագրքում"},
{"Click here to update record:", "Սեղմեկ այստեղ որպեսզի թարվացնեք գրառումը"},
{"invalid request uri", "Սխալ ձևավորված URI հարցում"},
{"Invalid request URI", "Սխալ ձևավորված URI հարցում"},
{"Can't detect destination host from request", "Չհաջողվեց հայնտաբերեկ վայրի հասցեն նշված հարցմամբ"},
{"Outproxy failure", "Սխալ արտաքին պրոքսի"},
{"bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"},
{"not inside I2P network, but outproxy is not enabled", "Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"},
{"unknown outproxy url", "արտաքին պրոքսիի անհայտ URL"},
{"cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"},
{"hostname too long", "Հոսթի անունը չափազանց երկար է"},
{"cannot connect to upstream socks proxy", "չհաջողվեց միանալ վերադաս socks պրոկսիին"},
{"Cannot negotiate with socks proxy", "Չհաջողվեց պայմանավորվել վերադաս socks պրոկսիի հետ"},
{"Bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Հոսթ %s Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"},
{"Unknown outproxy URL", "Արտաքին պրոքսիի անհայտ URL"},
{"Cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"},
{"Hostname is too long", "Հոսթի անունը չափազանց երկար է"},
{"Cannot connect to upstream SOCKS proxy", "Չհաջողվեց միանալ վերադաս SOCKS պրոկսի սերվերին"},
{"Cannot negotiate with SOCKS proxy", "Չհաջողվեց պայմանավորվել վերադաս SOCKS պրոկսիի հետ"},
{"CONNECT error", "Սխալ CONNECT հարցում"},
{"Failed to Connect", "Միանալ չhաջողվեց"},
{"socks proxy error", "Սխալ SOCKS պրոկսի"},
{"failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"},
{"No Reply From socks proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"},
{"cannot connect", "Հնարավոր չե միանալ"},
{"http out proxy not implemented", "Արտաքին http պրոկսին դեռ իրականացված չէ"},
{"cannot connect to upstream http proxy", "Չհաջողվեց միանալ վերադաս http պրոկսի սերվերին"},
{"Failed to connect", "Միանալ չhաջողվեց"},
{"SOCKS proxy error", "Սխալ SOCKS պրոկսի"},
{"Failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"},
{"No reply from SOCKS proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"},
{"Cannot connect", "Հնարավոր չե միանալ"},
{"HTTP out proxy not implemented", "Արտաքին HTTP պրոկսին դեռ իրականացված չէ"},
{"Cannot connect to upstream HTTP proxy", "Չհաջողվեց միանալ վերադաս HTTP պրոկսի սերվերին"},
{"Host is down", "Հոսթն անհասանելի է"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ:"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"օր", "օր"}},
{"hours", {"ժամ", "ժամ"}},
{"minutes", {"րոպե", "րոպե"}},
{"seconds", {"վարկյան", "վարկյան"}},
{"%d days", {"%d օր", "%d օր"}},
{"%d hours", {"%d ժամ", "%d ժամ"}},
{"%d minutes", {"%d րոպե", "%d րոպե"}},
{"%d seconds", {"%d վարկյան", "%d վարկյան"}},
{"", {"", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -13,7 +13,6 @@
#include "I18N.h"
// Simplified Chinese localization file
// This is an example translation file without strings in it.
namespace i2p
{
@ -32,9 +31,9 @@ namespace chinese // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "正在构建"},
{"failed", "连接失败"},
{"expiring", "即将过期"},
@ -46,7 +45,7 @@ namespace chinese // language namespace
{"Main page", "主页"},
{"Router commands", "路由命令"},
{"Local Destinations", "本地目标"},
{"LeaseSets", ""},
{"LeaseSets", ""},
{"Tunnels", "隧道"},
{"Transit Tunnels", "中转隧道"},
{"Transports", "传输"},
@ -58,19 +57,21 @@ namespace chinese // language namespace
{"Firewalled", "受到防火墙限制"},
{"Unknown", "未知"},
{"Proxy", "代理"},
{"Mesh", "Mesh组网"},
{"Error", "错误"},
{"Mesh", "自组网"},
{"Clock skew", "时钟偏移"},
{"Offline", "离线"},
{"Symmetric NAT", "对称 NAT"},
{"Full cone NAT", "全锥型NAT"},
{"No Descriptors", "无描述符"},
{"Uptime", "运行时间"},
{"Network status", "IPv4 网络状态"},
{"Network status v6", "IPv6 网络状态"},
{"Stopping in", "距停止还有:"},
{"Family", "家族"},
{"Tunnel creation success rate", "隧道创建成功率"},
{"Total tunnel creation success rate", "当前隧道创建成功率"},
{"Received", "已接收"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "已发送"},
{"Transit", "中转"},
{"Data path", "数据文件路径"},
@ -91,12 +92,13 @@ namespace chinese // language namespace
{"Address registration line", "地址域名注册"},
{"Domain", "域名"},
{"Generate", "生成"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>注意:</b> 结果字符串只能用于注册次级域名(例如example.i2p)。若需注册子域名,请使用 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>注意:</b> 结果字符串只能用于注册二级域名(例如example.i2p)。若需注册三级域名,请使用 i2pd-tools。"},
{"Address", "地址"},
{"Type", "类型"},
{"EncType", "加密类型"},
{"Expire LeaseSet", "到期租约集"},
{"Inbound tunnels", "入站隧道"},
{"ms", "毫秒"},
{"%dms", "%dms"},
{"Outbound tunnels", "出站隧道"},
{"Tags", "标签"},
{"Incoming", "传入"},
@ -109,6 +111,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", "无效"},
@ -118,9 +121,10 @@ namespace chinese // language namespace
{"Gateway", "网关"},
{"TunnelID", "隧道 ID"},
{"EndDate", "结束日期"},
{"not floodfill", "洪泛"},
{"floodfill mode is disabled", "洪泛已禁用"},
{"Queue size", "队列大小"},
{"Run peer test", "运行节点测试"},
{"Reload tunnels configuration", "重新载入隧道配置"},
{"Decline transit tunnels", "拒绝中转隧道"},
{"Accept transit tunnels", "允许中转隧道"},
{"Cancel graceful shutdown", "取消平滑关闭"},
@ -128,7 +132,7 @@ namespace chinese // language namespace
{"Force shutdown", "强制停止"},
{"Reload external CSS styles", "重载外部 CSS 样式"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>注意:</b> 此处完成的任何操作都不是永久的,不会更改您的配置文件。"},
{"Logging level", "日志记录级别"},
{"Logging level", "日志级别"},
{"Transit tunnels limit", "中转隧道限制"},
{"Change", "修改"},
{"Change language", "更改语言"},
@ -148,8 +152,10 @@ namespace chinese // language namespace
{"Destination not found", "找不到目标"},
{"StreamID can't be null", "StreamID 不能为空"},
{"Return to destination page", "返回目标页面"},
{"You will be redirected in 5 seconds", "您将在5秒内被重定向"},
{"Transit tunnels count must not exceed 65535", "中转隧道数量不能超过 65535"},
{"You will be redirected in %d seconds", "您将在%d秒内被重定向"},
{"LeaseSet expiration time updated", "租约集到期时间已更新"},
{"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 注册域名"},
{"Description", "描述"},
@ -157,42 +163,42 @@ 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", "代理错误"},
{"Proxy info", "代理信息"},
{"Proxy error: Host not found", "代理错误:未找到主机"},
{"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"},
{"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到主机"},
{"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到主机"},
{"Invalid request", "无效请求"},
{"Proxy unable to parse your request", "代理无法解析您的请求"},
{"addresshelper is not supported", "不支持地址助手"},
{"Host", "主机"},
{"added to router's addressbook from helper", "将此地址从地址助手添加到路由地址簿"},
{"Click here to proceed:", "点击此处继续:"},
{"Continue", "继续"},
{"Addresshelper found", "已找到地址助手"},
{"already in router's addressbook", "已在路由地址簿中"},
{"Click here to update record:", "点击此处更新地址簿记录"},
{"invalid request uri", "无效的 URL 请求"},
{"Addresshelper is not supported", "不支持地址助手"},
{"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>.", "主机 %s <font color=red>已在路由地址簿中</font>。<b>请注意:此地址的来源可能是有害的!</b>点击此处更新记录:<a href=\"%s%s%s&update=true\">继续</a>"},
{"Addresshelper forced update rejected", "地址助手强制更新被拒绝"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "若要在路由器地址簿中添加主机 <b>%s</b> 请点击这里: <a href=\"%s%s%s\">继续</a>"},
{"Addresshelper request", "请求地址助手"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "主机 %s 已通过地址助手添加到路由地址簿中。点击此处继续:<a href=\"%s\">继续</a>"},
{"Addresshelper adding", "正在添加地址助手"},
{"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>.", "主机 %s <font color=red>已在路由地址簿中</font>。点击此处更新记录:<a href=\"%s%s%s&update=true\">继续</a>"},
{"Addresshelper update", "更新地址助手"},
{"Invalid request URI", "无效的 URI 请求"},
{"Can't detect destination host from request", "无法从请求中检测到目标主机"},
{"Outproxy failure", "出口代理故障"},
{"bad outproxy settings", "错误的出口代理设置"},
{"not inside I2P network, but outproxy is not enabled", "该地址不在 I2P 网络内,但未启用出口代理"},
{"unknown outproxy url", "未知的出口代理地址"},
{"cannot resolve upstream proxy", "无法解析上游代理"},
{"hostname too long", "主机名过长"},
{"cannot connect to upstream socks proxy", "无法连接到上游 socks 代理"},
{"Cannot negotiate with socks proxy", "无法与 socks 代理协商"},
{"Bad outproxy settings", "错误的出口代理设置"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "主机 %s 不在 I2P 网络内,但出口代理未启用"},
{"Unknown outproxy URL", "未知的出口代理地址"},
{"Cannot resolve upstream proxy", "无法解析上游代理"},
{"Hostname is too long", "主机名过长"},
{"Cannot connect to upstream SOCKS proxy", "无法连接到上游 SOCKS 代理"},
{"Cannot negotiate with SOCKS proxy", "无法与 SOCKS 代理协商"},
{"CONNECT error", "连接错误"},
{"Failed to Connect", "连接失败"},
{"socks proxy error", "socks 代理错误"},
{"failed to send request to upstream", "向上游发送请求失败"},
{"No Reply From socks proxy", "没有来自 socks 代理的回复"},
{"cannot connect", "无法连接"},
{"http out proxy not implemented", "http 出口代理未实现"},
{"cannot connect to upstream http proxy", "无法连接到上游 http 代理"},
{"Failed to connect", "连接失败"},
{"SOCKS proxy error", "SOCKS 代理错误"},
{"Failed to send request to upstream", "向上游发送请求失败"},
{"No reply from SOCKS proxy", "没有来自 SOCKS 代理的回复"},
{"Cannot connect", "无法连接"},
{"HTTP out proxy not implemented", "HTTP 出口代理未实现"},
{"Cannot connect to upstream HTTP proxy", "无法连接到上游 HTTP 代理"},
{"Host is down", "主机已关闭"},
{"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"},
{"", ""},
@ -200,10 +206,10 @@ namespace chinese // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {""}},
{"hours", {""}},
{"minutes", {""}},
{"seconds", {""}},
{"%d days", {"%d 天"}},
{"%d hours", {"%d 小"}},
{"%d minutes", {"%d "}},
{"%d seconds", {"%d "}},
{"", {""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,23 +31,23 @@ namespace czech // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "vytváří se"},
{"failed", "selhalo"},
{"expiring", "končící"},
{"expiring", "vyprší platnost"},
{"established", "vytvořeno"},
{"unknown", "neznámý"},
{"exploratory", "průzkumné"},
{"Purple I2P Webconsole", "Purple I2P Webkonsole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsole"},
{"Purple I2P Webconsole", "Purple I2P webová konzole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webová konzole"},
{"Main page", "Hlavní stránka"},
{"Router commands", "Router příkazy"},
{"Local Destinations", "Lokální destinace"},
{"LeaseSets", "LeaseSety"},
{"Local Destinations", "Místní cíle"},
{"LeaseSets", "Sety pronájmu"},
{"Tunnels", "Tunely"},
{"Transit Tunnels", "Transitní tunely"},
{"Transit Tunnels", "Tranzitní tunely"},
{"Transports", "Transporty"},
{"I2P tunnels", "I2P tunely"},
{"SAM sessions", "SAM relace"},
@ -58,22 +58,24 @@ namespace czech // language namespace
{"Unknown", "Neznámý"},
{"Proxy", "Proxy"},
{"Mesh", "Síť"},
{"Error", "Chyba"},
{"Clock skew", "Časová nesrovnalost"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetrický NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Žádné popisovače"},
{"Uptime", "Doba provozu"},
{"Network status", "Status sítě"},
{"Network status v6", "Status sítě v6"},
{"Network status", "Stav sítě"},
{"Network status v6", "Stav sítě v6"},
{"Stopping in", "Zastavuji za"},
{"Family", "Rodina"},
{"Tunnel creation success rate", "Úspěšnost vytváření tunelů"},
{"Total tunnel creation success rate", "Celková míra úspěšnosti vytváření tunelů"},
{"Received", "Přijato"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Odesláno"},
{"Transit", "Tranzit"},
{"Data path", "Cesta k data souborům"},
{"Hidden content. Press on text to see.", "Skrytý kontent. Pro zobrazení, klikni na text."},
{"Data path", "Cesta k datovým souborům"},
{"Hidden content. Press on text to see.", "Skrytý obsah. Pro zobrazení klikněte sem."},
{"Router Ident", "Routerová Identita"},
{"Router Family", "Rodina routerů"},
{"Router Caps", "Omezení Routerů"},
@ -94,8 +96,9 @@ namespace czech // language namespace
{"Address", "Adresa"},
{"Type", "Typ"},
{"EncType", "EncType"},
{"Expire LeaseSet", "Zrušit platnost setu pronájmu"},
{"Inbound tunnels", "Příchozí tunely"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Odchozí tunely"},
{"Tags", "Štítky"},
{"Incoming", "Příchozí"},
@ -104,22 +107,24 @@ namespace czech // language namespace
{"Amount", "Množství"},
{"Incoming Tags", "Příchozí štítky"},
{"Tags sessions", "Relace štítků"},
{"Status", "Status"},
{"Local Destination", "Lokální Destinace"},
{"Status", "Stav"},
{"Local Destination", "Místní cíl"},
{"Streams", "Toky"},
{"Close stream", "Uzavřít tok"},
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
{"I2CP session not found", "I2CP relace nenalezena"},
{"I2CP is not enabled", "I2CP není zapnuto"},
{"Invalid", "Neplatný"},
{"Store type", "Druh uložení"},
{"Expires", "Vyprší"},
{"Non Expired Leases", "Nevypršené Leasy"},
{"Non Expired Leases", "Pronájmy, kterým nevypršela platnost"},
{"Gateway", "Brána"},
{"TunnelID", "ID tunelu"},
{"EndDate", "Datum ukončení"},
{"not floodfill", "není floodfill"},
{"floodfill mode is disabled", "režim floodfill je vypnut"},
{"Queue size", "Velikost fronty"},
{"Run peer test", "Spustit peer test"},
{"Reload tunnels configuration", "Znovu načíst nastavení tunelů"},
{"Decline transit tunnels", "Odmítnout tranzitní tunely"},
{"Accept transit tunnels", "Přijmout tranzitní tunely"},
{"Cancel graceful shutdown", "Zrušit hladké vypnutí"},
@ -147,16 +152,17 @@ namespace czech // language namespace
{"Destination not found", "Destinace nenalezena"},
{"StreamID can't be null", "StreamID nemůže být null"},
{"Return to destination page", "Zpět na stránku destinací"},
{"You will be redirected in 5 seconds", "Budete přesměrováni za 5 vteřin"},
{"Transit tunnels count must not exceed 65535", "Počet tranzitních tunelů nesmí přesáhnout 65535"},
{"Back to commands list", "Zpět na list příkazů"},
{"You will be redirected in %d seconds", "Budete přesměrováni za %d sekund"},
{"LeaseSet expiration time updated", "Aktualizován čas vypršení platnosti setu pronájmu"},
{"LeaseSet is not found or already expired", "Set pronájmu není k nalezení nebo již vypršela jeho platnost"},
{"Transit tunnels count must not exceed %d", "Počet tranzitních tunelů nesmí překročit %d"},
{"Back to commands list", "Zpět na seznam příkazů"},
{"Register at reg.i2p", "Zaregistrovat na reg.i2p"},
{"Description", "Popis"},
{"A bit information about service on domain", "Trochu informací o službě na doméně"},
{"Submit", "Odeslat"},
{"Domain can't end with .b32.i2p", "Doména nesmí končit na .b32.i2p"},
{"Domain must end with .i2p", "Doména musí končit s .i2p"},
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
{"Unknown command", "Neznámý příkaz"},
{"Command accepted", "Příkaz přijat"},
{"Proxy error", "Chyba proxy serveru"},
@ -166,32 +172,33 @@ namespace czech // language namespace
{"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"},
{"Invalid request", "Neplatný požadavek"},
{"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"},
{"addresshelper is not supported", "Adresshelper není podporován"},
{"Host", "Hostitel"},
{"added to router's addressbook from helper", "přidáno do adresáře routeru od pomocníka"},
{"Click here to proceed:", "Pro pokračování, klikněte zde:"},
{"Continue", "Pokračovat"},
{"Addresshelper found", "Adresář nalezen"},
{"already in router's addressbook", "je již v adresáři routeru"},
{"Click here to update record:", "Pro aktualizaci záznamu, klikněte zde:"},
{"invalid request uri", "neplatný URI požadavek"},
{"Addresshelper is not supported", "Addresshelper není podporován"},
{"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>.", "Hostitel %s je <font color=red>již v adresáři routeru</font>. <b>Buďte opatrní: zdroj této URL může být škodlivý!</b> Klikněte zde pro aktualizaci záznamu: <a href=\"%s%s%s&update=true\">Pokračovat</a>."},
{"Addresshelper forced update rejected", "Addresshelperem vynucená aktualizace zamítnuta"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pro přidání hostitele <b>%s</b> do adresáře routeru, klikněte zde: <a href=\"%s%s%s\">Pokračovat</a>."},
{"Addresshelper request", "Požadavek Addresshelperu"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Hostitel %s přidán do adresáře routeru od pomocníka. Klikněte zde pro pokračování: <a href=\"%s\">Pokračovat</a>."},
{"Addresshelper adding", "Addresshelper přidávání"},
{"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>.", "Hostitel %s je <font color=red>již v adresáři routeru</font>. Klikněte zde pro aktualizaci záznamu: <a href=\"%s%s%s&update=true\">Pokračovat</a>."},
{"Addresshelper update", "Addresshelper aktualizace"},
{"Invalid request URI", "Neplatný URI požadavek"},
{"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"},
{"Outproxy failure", "Outproxy selhání"},
{"bad outproxy settings", "špatné outproxy nastavení"},
{"not inside I2P network, but outproxy is not enabled", "není uvnitř I2P sítě a outproxy není nastavena"},
{"unknown outproxy url", "neznámá outproxy URL"},
{"cannot resolve upstream proxy", "nelze rozluštit upstream proxy server"},
{"hostname too long", "Název hostitele je příliš dlouhý"},
{"cannot connect to upstream socks proxy", "nelze se připojit k upstream socks proxy serveru"},
{"Cannot negotiate with socks proxy", "Nelze vyjednávat se socks proxy serverem"},
{"Bad outproxy settings", "Špatné outproxy nastavení"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Hostitel %s není uvnitř I2P sítě a outproxy není nastavena"},
{"Unknown outproxy URL", "Neznámá outproxy URL"},
{"Cannot resolve upstream proxy", "Nelze rozluštit upstream proxy server"},
{"Hostname is too long", "Název hostitele je příliš dlouhý"},
{"Cannot connect to upstream SOCKS proxy", "Nelze se připojit k upstream SOCKS proxy serveru"},
{"Cannot negotiate with SOCKS proxy", "Nelze vyjednávat se SOCKS proxy serverem"},
{"CONNECT error", "Chyba PŘIPOJENÍ"},
{"Failed to Connect", "Připojení se nezdařilo"},
{"socks proxy error", "chyba socks proxy serveru"},
{"failed to send request to upstream", "odeslání žádosti upstream serveru se nezdařilo"},
{"No Reply From socks proxy", "Žádná odpověď od socks proxy serveru"},
{"cannot connect", "nelze se připojit"},
{"http out proxy not implemented", "http out proxy není implementován"},
{"cannot connect to upstream http proxy", "nelze se připojit k upstream socks proxy serveru"},
{"Failed to connect", "Připojení se nezdařilo"},
{"SOCKS proxy error", "Chyba SOCKS proxy serveru"},
{"Failed to send request to upstream", "Odeslání žádosti upstream serveru se nezdařilo"},
{"No reply from SOCKS proxy", "Žádná odpověď od SOCKS proxy serveru"},
{"Cannot connect", "Nelze se připojit"},
{"HTTP out proxy not implemented", "HTTP out proxy není implementován"},
{"Cannot connect to upstream HTTP proxy", "Nelze se připojit k upstream HTTP proxy serveru"},
{"Host is down", "Hostitel je nedostupný"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."},
{"", ""},
@ -199,10 +206,10 @@ namespace czech // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"den", "dny", "dní", "dní"}},
{"hours", {"hodina", "hodiny", "hodin", "hodin"}},
{"minutes", {"minuta", "minuty", "minut", "minut"}},
{"seconds", {"vteřina", "vteřiny", "vteřin", "vteřin"}},
{"%d days", {"%d den", "%d dny", "%d dní", "%d dní"}},
{"%d hours", {"%d hodina", "%d hodiny", "%d hodin", "%d hodin"}},
{"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}},
{"%d seconds", {"%d vteřina", "%d vteřiny", "%d vteřin", "%d vteřin"}},
{"", {"", "", "", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,9 +31,9 @@ namespace french // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "Kio"},
{"MiB", "Mio"},
{"GiB", "Gio"},
{"%.2f KiB", "%.2f Kio"},
{"%.2f MiB", "%.2f Mio"},
{"%.2f GiB", "%.2f Gio"},
{"building", "En construction"},
{"failed", "échoué"},
{"expiring", "expiré"},
@ -58,18 +58,20 @@ namespace french // language namespace
{"Unknown", "Inconnu"},
{"Proxy", "Proxy"},
{"Mesh", "Maillé"},
{"Error", "Erreur"},
{"Clock skew", "Horloge décalée"},
{"Clock skew", "Décalage de l'horloge"},
{"Offline", "Hors ligne"},
{"Symmetric NAT", "NAT symétrique"},
{"Full cone NAT", "NAT à cône complet"},
{"No Descriptors", "Aucuns Descripteurs"},
{"Uptime", "Temps de fonctionnement"},
{"Network status", "État du réseau"},
{"Network status v6", "État du réseau v6"},
{"Stopping in", "Arrêt dans"},
{"Family", "Famille"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Tunnel creation success rate", "Taux de création de tunnel réussie"},
{"Total tunnel creation success rate", "Taux total de création de tunnel réussie"},
{"Received", "Reçu"},
{"KiB/s", "kio/s"},
{"%.2f KiB/s", "%.2f Kio/s"},
{"Sent", "Envoyé"},
{"Transit", "Transité"},
{"Data path", "Emplacement des données"},
@ -81,6 +83,7 @@ namespace french // language namespace
{"Our external address", "Notre adresse externe"},
{"supported", "supporté"},
{"Routers", "Routeurs"},
{"Floodfills", "Remplisseurs"},
{"Client Tunnels", "Tunnels clients"},
{"Services", "Services"},
{"Enabled", "Activé"},
@ -89,11 +92,13 @@ 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"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnels sortants"},
{"Tags", "Balises"},
{"Incoming", "Entrant"},
@ -106,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"},
@ -115,15 +121,17 @@ namespace french // language namespace
{"Gateway", "Passerelle"},
{"TunnelID", "ID du tunnel"},
{"EndDate", "Date de fin"},
{"floodfill mode is disabled", "le mode de remplissage est désactivé"},
{"Queue size", "Longueur de la file"},
{"Run peer test", "Lancer test des pairs"},
{"Reload tunnels configuration", "Recharger la configuration des tunnels"},
{"Decline transit tunnels", "Refuser les tunnels transitoires"},
{"Accept transit tunnels", "Accepter les tunnels transitoires"},
{"Cancel graceful shutdown", "Annuler l'arrêt gracieux"},
{"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"},
@ -134,6 +142,8 @@ namespace french // language namespace
{"SAM session not found", "session SAM introuvable"},
{"SAM Session", "Session SAM"},
{"Server Tunnels", "Tunnels serveurs"},
{"Client Forwards", "Transmission du client"},
{"Server Forwards", "Transmission du serveur"},
{"Unknown page", "Page inconnue"},
{"Invalid token", "Jeton invalide"},
{"SUCCESS", "SUCCÈS"},
@ -142,8 +152,10 @@ namespace french // language namespace
{"Destination not found", "Destination introuvable"},
{"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 5 seconds", "Vous allez être redirigé dans cinq secondes"},
{"Transit tunnels count must not exceed 65535", "Le nombre de tunnels transitoires ne doit pas dépasser 65535"},
{"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"},
{"Description", "Description"},
@ -151,42 +163,42 @@ 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", "Hôte"},
{"added to router's addressbook from helper", "Ajouté au carnet d'adresse du routeur par l'assistant"},
{"Click here to proceed:", "Cliquez ici pour continuer:"},
{"Continue", "Continuer"},
{"Addresshelper found", "Assistant d'adresse trouvé"},
{"already in router's addressbook", "déjà dans le carnet d'adresses du routeur"},
{"Click here to update record:", "Cliquez ici pour mettre à jour le carnet d'adresse:"},
{"invalid request uri", "uri de la requête invalide"},
{"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>."},
{"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>."},
{"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>."},
{"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"},
{"Outproxy failure", "Échec de proxy de sortie"},
{"bad outproxy settings", "Mauvaise configuration du proxy de sortie"},
{"not inside I2P network, but outproxy is not enabled", "pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"},
{"unknown outproxy url", "URL du proxy de sortie inconnu"},
{"cannot resolve upstream proxy", "impossible de résoudre l'adresse du proxy en amont"},
{"hostname too long", "nom d'hôte trop long"},
{"cannot connect to upstream socks proxy", "impossible de se connecter au proxy socks en amont"},
{"Cannot negotiate with socks proxy", "Impossible de négocier avec le proxy socks"},
{"Bad outproxy settings", "Mauvaise configuration du proxy de sortie"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Hôte %s pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"},
{"Unknown outproxy URL", "URL du proxy de sortie inconnu"},
{"Cannot resolve upstream proxy", "Impossible de résoudre l'adresse du proxy en amont"},
{"Hostname is too long", "Nom d'hôte trop long"},
{"Cannot connect to upstream SOCKS proxy", "Impossible de se connecter au proxy SOCKS en amont"},
{"Cannot negotiate with SOCKS proxy", "Impossible de négocier avec le proxy SOCKS"},
{"CONNECT error", "Erreur de connexion"},
{"Failed to Connect", "Échec de connexion"},
{"socks proxy error", "Erreur de proxy socks"},
{"failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"},
{"No Reply From socks proxy", "Pas de réponse du proxy socks"},
{"cannot connect", "impossible de connecter"},
{"http out proxy not implemented", "Proxy de sortie HTTP non implémenté"},
{"cannot connect to upstream http proxy", "impossible de se connecter au proxy HTTP en amont"},
{"Failed to connect", "Échec de connexion"},
{"SOCKS proxy error", "Erreur de proxy SOCKS"},
{"Failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"},
{"No reply from SOCKS proxy", "Pas de réponse du proxy SOCKS"},
{"Cannot connect", "Impossible de connecter"},
{"HTTP out proxy not implemented", "Proxy de sortie HTTP non implémenté"},
{"Cannot connect to upstream HTTP proxy", "Impossible de se connecter au proxy HTTP en amont"},
{"Host is down", "Hôte hors service"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."},
{"", ""},
@ -194,10 +206,10 @@ namespace french // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"jour", "jours"}},
{"hours", {"heure", "heures"}},
{"minutes", {"minute", "minutes"}},
{"seconds", {"seconde", "secondes"}},
{"%d days", {"%d jour", "%d jours"}},
{"%d hours", {"%d heure", "%d heures"}},
{"%d minutes", {"%d minute", "%d minutes"}},
{"%d seconds", {"%d seconde", "%d secondes"}},
{"", {"", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,9 +31,9 @@ namespace german // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "In Bau"},
{"failed", "fehlgeschlagen"},
{"expiring", "läuft ab"},
@ -58,10 +58,10 @@ namespace german // language namespace
{"Unknown", "Unbekannt"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"Error", "Fehler"},
{"Clock skew", "Zeitabweichung"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symmetrisches NAT"},
{"No Descriptors", "Keine Beschreibungen"},
{"Uptime", "Laufzeit"},
{"Network status", "Netzwerkstatus"},
{"Network status v6", "Netzwerkstatus v6"},
@ -69,7 +69,7 @@ namespace german // language namespace
{"Family", "Familie"},
{"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"},
{"Received", "Eingegangen"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Gesendet"},
{"Transit", "Transit"},
{"Data path", "Datenpfad"},
@ -95,7 +95,7 @@ namespace german // language namespace
{"Type", "Typ"},
{"EncType", "Verschlüsselungstyp"},
{"Inbound tunnels", "Eingehende Tunnel"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Ausgehende Tunnel"},
{"Tags", "Tags"},
{"Incoming", "Eingehend"},
@ -117,9 +117,10 @@ namespace german // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Enddatum"},
{"not floodfill", "kein Floodfill"},
{"floodfill mode is disabled", "Floodfill Modus ist deaktiviert"},
{"Queue size", "Größe der Warteschlange"},
{"Run peer test", "Peer-Test durchführen"},
{"Reload tunnels configuration", "Tunnel Konfiguration neu laden"},
{"Decline transit tunnels", "Transittunnel ablehnen"},
{"Accept transit tunnels", "Transittunnel akzeptieren"},
{"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"},
@ -147,8 +148,8 @@ namespace german // language namespace
{"Destination not found", "Ziel nicht gefunden"},
{"StreamID can't be null", "StreamID kann nicht null sein"},
{"Return to destination page", "Zurück zur Ziel-Seite"},
{"You will be redirected in 5 seconds", "Du wirst in 5 Sekunden weitergeleitet"},
{"Transit tunnels count must not exceed 65535", "Es darf maximal 65535 Transittunnel geben"},
{"You will be redirected in %d seconds", "Du wirst umgeleitet in %d Sekunden"},
{"Transit tunnels count must not exceed %d", "Die Anzahl der Transittunnel darf nicht über %d gehen"},
{"Back to commands list", "Zurück zur Befehlsliste"},
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
{"Description", "Beschreibung"},
@ -166,32 +167,33 @@ namespace german // language namespace
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"},
{"Invalid request", "Ungültige Anfrage"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"},
{"addresshelper is not supported", "Addresshelfer wird nicht unterstützt"},
{"Host", "Host"},
{"added to router's addressbook from helper", "vom Helfer zum Router-Adressbuch hinzugefügt"},
{"Click here to proceed:", "Klicke hier um fortzufahren:"},
{"Continue", "Fortsetzen"},
{"Addresshelper found", "Adresshelfer gefunden"},
{"already in router's addressbook", "bereits im Adressbuch des Routers"},
{"Click here to update record:", "Klicke hier, um den Eintrag zu aktualisieren:"},
{"invalid request uri", "ungültige Anfrage-URI"},
{"Addresshelper is not supported", "Adresshelfer wird nicht unterstützt"},
{"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>.", "Host %s ist <font color=red>bereits im Adressbuch des Routers</font>. <b>Vorsicht: Die Quelle dieser URL kann schädlich sein!</b> Klicken Sie hier, um den Datensatz zu aktualisieren: <a href=\"%s%s%s&update=true\">Weiter</a>."},
{"Addresshelper forced update rejected", "Adresshelfer gezwungene Aktualisierung abgelehnt"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Um den Host <b>%s</b> im Adressbuch des Routers hinzuzufügen, klicken Sie hier: <a href=\"%s%s%s\">Weiter</a>."},
{"Addresshelper request", "Adresshelfer gefunden"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Host %s wurde vom Helfer zum Adressbuch des Routers hinzugefügt. Klicken Sie hier, um fortzufahren: <a href=\"%s\">Weiter</a>."},
{"Addresshelper adding", "Adresshelfer hinzufügen"},
{"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>.", "Host %s ist <font color=red>bereits im Adressbuch des Routers</font>. Klicken Sie hier, um den Eintrag zu aktualisieren: <a href=\"%s%s%s&update=true\">Weiter</a>."},
{"Addresshelper update", "Adresshelfer aktualisieren"},
{"Invalid request URI", "Ungültige Anfrage-URI"},
{"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"},
{"Outproxy failure", "Outproxy-Fehler"},
{"bad outproxy settings", "ungültige Outproxy-Einstellungen"},
{"not inside I2P network, but outproxy is not enabled", "außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
{"unknown outproxy url", "unbekannte Outproxy-URL"},
{"cannot resolve upstream proxy", "kann den Upstream-Proxy nicht auflösen"},
{"hostname too long", "Hostname zu lang"},
{"cannot connect to upstream socks proxy", "Kann keine Verbindung zum Upstream-Socks-Proxy herstellen"},
{"Cannot negotiate with socks proxy", "Kann nicht mit Socks-Proxy verhandeln"},
{"Bad outproxy settings", "Ungültige Outproxy-Einstellungen"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
{"Unknown outproxy URL", "Unbekannte Outproxy-URL"},
{"Cannot resolve upstream proxy", "Kann den Upstream-Proxy nicht auflösen"},
{"Hostname is too long", "Hostname zu lang"},
{"Cannot connect to upstream SOCKS proxy", "Kann keine Verbindung zum Upstream-SOCKS-Proxy herstellen"},
{"Cannot negotiate with SOCKS proxy", "Kann nicht mit SOCKS-Proxy verhandeln"},
{"CONNECT error", "CONNECT-Fehler"},
{"Failed to Connect", "Verbindung konnte nicht hergestellt werden"},
{"socks proxy error", "Socks-Proxy-Fehler"},
{"failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"},
{"No Reply From socks proxy", "Keine Antwort vom Socks-Proxy"},
{"cannot connect", "kann nicht verbinden"},
{"http out proxy not implemented", "HTTP-Outproxy nicht implementiert"},
{"cannot connect to upstream http proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"},
{"Failed to connect", "Verbindung konnte nicht hergestellt werden"},
{"SOCKS proxy error", "SOCKS-Proxy-Fehler"},
{"Failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"},
{"No reply from SOCKS proxy", "Keine Antwort vom SOCKS-Proxy"},
{"Cannot connect", "Kann nicht verbinden"},
{"HTTP out proxy not implemented", "HTTP-Outproxy nicht implementiert"},
{"Cannot connect to upstream HTTP proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"},
{"Host is down", "Host ist offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."},
{"", ""},
@ -199,10 +201,10 @@ namespace german // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"Tag", "Tage"}},
{"hours", {"Stunde", "Stunden"}},
{"minutes", {"Minute", "Minuten"}},
{"seconds", {"Sekunde", "Sekunden"}},
{"%d days", {"%d Tag", "%d Tage"}},
{"%d hours", {"%d Stunde", "%d Stunden"}},
{"%d minutes", {"%d Minute", "%d Minuten"}},
{"%d seconds", {"%d Sekunde", "%d Sekunden"}},
{"", {"", ""}},
};

@ -1,11 +1,12 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <clocale>
#include "ClientContext.h"
#include "I18N_langs.h"
#include "I18N.h"
@ -18,9 +19,15 @@ namespace i18n
{
const auto it = i2p::i18n::languages.find(lang);
if (it == i2p::i18n::languages.end()) // fallback
{
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
setlocale(LC_NUMERIC, "english");
}
else
{
i2p::client::context.SetLanguage (it->second.LocaleFunc());
setlocale(LC_NUMERIC, lang.c_str()); // set decimal point based on language
}
}
std::string translate (const std::string& arg)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -67,17 +67,69 @@ namespace i18n
const std::map<std::string, std::vector<std::string>> m_Plurals;
std::function<int(int)> m_Formula;
};
void SetLanguage(const std::string &lang);
std::string translate (const std::string& arg);
std::string translate (const std::string& arg, const std::string& arg2, const int& n);
} // i18n
} // i2p
template<typename... TArgs>
std::string tr (TArgs&&... args)
/**
* @brief Get translation of string
* @param arg String with message
*/
template<typename TValue>
std::string tr (TValue&& arg)
{
return i2p::i18n::translate(std::forward<TValue>(arg));
}
/**
* @brief Get translation of string and format it
* @param arg String with message
* @param args Array of arguments for string formatting
*/
template<typename TValue, typename... TArgs>
std::string tr (TValue&& arg, TArgs&&... args)
{
return i2p::i18n::translate(std::forward<TArgs>(args)...);
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg));
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
}
/**
* @brief Get translation of string with plural forms
* @param arg String with message in singular form
* @param arg2 String with message in plural form
* @param n Integer, used for selection of form
*/
template<typename TValue, typename TValue2>
std::string ntr (TValue&& arg, TValue2&& arg2, int& n)
{
return i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
}
/**
* @brief Get translation of string with plural forms and format it
* @param arg String with message in singular form
* @param arg2 String with message in plural form
* @param n Integer, used for selection of form
* @param args Array of arguments for string formatting
*/
template<typename TValue, typename TValue2, typename... TArgs>
std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args)
{
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
}
#endif // __I18N_H__

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -23,19 +23,23 @@ namespace i18n
};
// Add localization here with language name as namespace
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace czech { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace czech { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace polish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace portuguese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace swedish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
/**
* That map contains international language name lower-case, name in it's language and it's code
@ -50,8 +54,12 @@ namespace i18n
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
{ "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} },
{ "polish", {"Polski", "pl", i2p::i18n::polish::GetLocale} },
{ "portuguese", {"Português", "pt", i2p::i18n::portuguese::GetLocale} },
{ "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} },
{ "swedish", {"Svenska", "sv", i2p::i18n::swedish::GetLocale} },
{ "turkish", {"Türk dili", "tr", i2p::i18n::turkish::GetLocale} },
{ "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
{ "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
{ "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} },

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,9 +31,9 @@ namespace italian // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "in costruzione"},
{"failed", "fallito"},
{"expiring", "in scadenza"},
@ -58,18 +58,20 @@ namespace italian // language namespace
{"Unknown", "Sconosciuto"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"Error", "Errore"},
{"Clock skew", "Orologio disallineato"},
{"Offline", "Disconnesso"},
{"Symmetric NAT", "NAT simmetrico"},
{"Full cone NAT", "Cono completo NAT"},
{"No Descriptors", "Nessun descrittore"},
{"Uptime", "In funzione da"},
{"Network status", "Stato della rete"},
{"Network status v6", "Stato della rete v6"},
{"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"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Inviati"},
{"Transit", "Transitati"},
{"Data path", "Percorso dati"},
@ -94,8 +96,9 @@ namespace italian // language namespace
{"Address", "Indirizzo"},
{"Type", "Tipologia"},
{"EncType", "Tipo di crittografia"},
{"Expire LeaseSet", "Scadenza LeaseSet"},
{"Inbound tunnels", "Tunnel in entrata"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnel in uscita"},
{"Tags", "Tag"},
{"Incoming", "In entrata"},
@ -108,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"},
@ -117,9 +121,10 @@ namespace italian // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Data di fine"},
{"not floodfill", "no floodfill"},
{"floodfill mode is disabled", "la modalità floodfill è disabilitata"},
{"Queue size", "Dimensione della coda"},
{"Run peer test", "Esegui il test dei peer"},
{"Reload tunnels configuration", "Ricarica la configurazione dei tunnel"},
{"Decline transit tunnels", "Rifiuta tunnel di transito"},
{"Accept transit tunnels", "Accetta tunnel di transito"},
{"Cancel graceful shutdown", "Annulla l'interruzione controllata"},
@ -147,8 +152,10 @@ namespace italian // language namespace
{"Destination not found", "Destinazione non trovata"},
{"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 5 seconds", "Verrai reindirizzato in 5 secondi"},
{"Transit tunnels count must not exceed 65535", "Il numero di tunnel di transito non può superare i 65535"},
{"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"},
{"Description", "Descrizione"},
@ -156,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"},
@ -166,32 +172,33 @@ namespace italian // language namespace
{"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"},
{"Invalid request", "Richiesta non valida"},
{"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"},
{"addresshelper is not supported", "addresshelper non è supportato"},
{"Host", "Host"},
{"added to router's addressbook from helper", "aggiunto alla rubrica tramite l'helper"},
{"Click here to proceed:", "Clicca qui per procedere:"},
{"Continue", "Continua"},
{"Addresshelper found", "Addresshelper trovato"},
{"already in router's addressbook", "già presente nella rubrica del router"},
{"Click here to update record:", "Clicca qui per aggiornare l'elemento:"},
{"invalid request uri", "uri della richiesta non valido"},
{"Addresshelper is not supported", "Addresshelper non è supportato"},
{"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'host %s è <font color=red>già nella rubrica del router</font>. <b>Attenzione: la fonte di questo URL potrebbe essere dannosa!</b> Fai clic qui per aggiornare il record: <a href=\"%s%s%s&update=true\">Continua</a>."},
{"Addresshelper forced update rejected", "Aggiornamento forzato dell'helper degli indirizzi rifiutato"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Per aggiungere host <b>%s</b> nella rubrica del router, clicca qui: <a href=\"%s%s%s\">Continua</a>."},
{"Addresshelper request", "Richiesta di indirizzo helper"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "L'host %s viene aggiunto alla rubrica del router dall'helper. Fai clic qui per procedere: <a href=\"%s\">Continua</a>."},
{"Addresshelper adding", "Aggiunta di Addresshelper"},
{"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'host %s è <font color=red>già nella rubrica del router</font>. Clicca qui per aggiornare il record: <a href=\"%s%s%s&update=true\">Continua</a>."},
{"Addresshelper update", "Aggiornamento dell'helper degli indirizzi"},
{"Invalid request URI", "URI della richiesta non valido"},
{"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"},
{"Outproxy failure", "Fallimento del proxy di uscita"},
{"bad outproxy settings", "impostazioni errate del proxy di uscita"},
{"not inside I2P network, but outproxy is not enabled", "non all'interno della rete I2P, ma il proxy di uscita non è abilitato"},
{"unknown outproxy url", "url del proxy di uscita sconosciuto"},
{"cannot resolve upstream proxy", "impossibile identificare il flusso a monte del proxy"},
{"hostname too long", "il nome dell'host è troppo lungo"},
{"cannot connect to upstream socks proxy", "impossibile connettersi al flusso a monte del proxy socks"},
{"Cannot negotiate with socks proxy", "Impossibile negoziare con il proxy socks"},
{"Bad outproxy settings", "Impostazioni errate del proxy di uscita"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s non all'interno della rete I2P, ma il proxy di uscita non è abilitato"},
{"Unknown outproxy URL", "URL del proxy di uscita sconosciuto"},
{"Cannot resolve upstream proxy", "Impossibile identificare il flusso a monte del proxy"},
{"Hostname is too long", "Il nome dell'host è troppo lungo"},
{"Cannot connect to upstream SOCKS proxy", "Impossibile connettersi al flusso a monte del proxy SOCKS"},
{"Cannot negotiate with SOCKS proxy", "Impossibile negoziare con il proxy SOCKS"},
{"CONNECT error", "Errore di connessione"},
{"Failed to Connect", "Connessione fallita"},
{"socks proxy error", "errore del proxy socks"},
{"failed to send request to upstream", "invio della richiesta a monte non riuscito"},
{"No Reply From socks proxy", "Nessuna risposta dal proxy socks"},
{"cannot connect", "impossibile connettersi"},
{"http out proxy not implemented", "proxy http di uscita non implementato"},
{"cannot connect to upstream http proxy", "impossibile connettersi al proxy http a monte"},
{"Failed to connect", "Connessione fallita"},
{"SOCKS proxy error", "Errore del proxy SOCKS"},
{"Failed to send request to upstream", "Invio della richiesta a monte non riuscito"},
{"No reply from SOCKS proxy", "Nessuna risposta dal proxy SOCKS"},
{"Cannot connect", "Impossibile connettersi"},
{"HTTP out proxy not implemented", "Proxy HTTP di uscita non implementato"},
{"Cannot connect to upstream HTTP proxy", "Impossibile connettersi al flusso a monte del proxy HTTP"},
{"Host is down", "L'host è offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."},
{"", ""},
@ -199,10 +206,10 @@ namespace italian // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"giorno", "giorni"}},
{"hours", {"ora", "ore"}},
{"minutes", {"minuto", "minuti"}},
{"seconds", {"secondo", "secondi"}},
{"%d days", {"%d giorno", "%d giorni"}},
{"%d hours", {"%d ora", "%d ore"}},
{"%d minutes", {"%d minuto", "%d minuti"}},
{"%d seconds", {"%d secondo", "%d secondi"}},
{"", {"", ""}},
};

@ -0,0 +1,223 @@
/*
* Copyright (c) 2023-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Polish localization file
namespace i2p
{
namespace i18n
{
namespace polish // language namespace
{
// language name in lowercase
static std::string language = "polish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "Kompilowanie"},
{"failed", "nieudane"},
{"expiring", "wygasający"},
{"established", "ustanowiony"},
{"unknown", "nieznany"},
{"exploratory", "eksploracyjny"},
{"Purple I2P Webconsole", "Konsola webowa Purple I2P"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> konsola webowa"},
{"Main page", "Strona główna"},
{"Router commands", "Komendy routera"},
{"Local Destinations", "Lokalne miejsca docelowe"},
{"LeaseSets", "ZestawyNajmu"},
{"Tunnels", "Tunele"},
{"Transit Tunnels", "Tunele Tranzytu"},
{"Transports", "Transportery"},
{"I2P tunnels", "Tunele I2P"},
{"SAM sessions", "Sesje SAM"},
{"ERROR", "BŁĄD"},
{"OK", "Ok"},
{"Testing", "Testowanie"},
{"Firewalled", "Za zaporą sieciową"},
{"Unknown", "Nieznany"},
{"Proxy", "Proxy"},
{"Mesh", "Sieć"},
{"Clock skew", "Przesunięcie czasu"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetryczny NAT"},
{"Full cone NAT", "Pełny stożek NAT"},
{"No Descriptors", "Brak deskryptorów"},
{"Uptime", "Czas pracy"},
{"Network status", "Stan sieci"},
{"Network status v6", "Stan sieci v6"},
{"Stopping in", "Zatrzymywanie za"},
{"Family", "Rodzina"},
{"Tunnel creation success rate", "Wskaźnik sukcesu tworzenia tunelu"},
{"Total tunnel creation success rate", "Całkowity wskaźnik sukcesu tworzenia tunelu"},
{"Received", "Odebrano"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Wysłane"},
{"Transit", "Tranzyt"},
{"Data path", "Ścieżka do danych"},
{"Hidden content. Press on text to see.", "Ukryta zawartość. Naciśnij tekst, aby zobaczyć."},
{"Router Ident", "Identyfikator routera"},
{"Router Family", "Rodzina routera"},
{"Router Caps", "Możliwości routera"},
{"Version", "Wersja"},
{"Our external address", "Nasz zewnętrzny adres"},
{"supported", "wspierane"},
{"Routers", "Routery"},
{"Floodfills", "Floodfille"},
{"Client Tunnels", "Tunele Klienta"},
{"Services", "Usługi"},
{"Enabled", "Aktywny"},
{"Disabled", "Wyłączony"},
{"Encrypted B33 address", "Zaszyfrowany adres B33"},
{"Address registration line", "Linia rejestracji adresu"},
{"Domain", "Domena"},
{"Generate", "Generuj"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Uwaga:</b> wynik string może być używany tylko do rejestracji domen 2LD (przykład.i2p). Do rejestracji subdomen należy użyć narzędzi i2pd."},
{"Address", "Adres"},
{"Type", "Typ"},
{"EncType", "TypEnkrypcji"},
{"Expire LeaseSet", "Wygaśnij LeaseSet"},
{"Inbound tunnels", "Tunele przychodzące"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunele wychodzące"},
{"Tags", "Tagi"},
{"Incoming", "Przychodzące"},
{"Outgoing", "Wychodzące"},
{"Destination", "Miejsce docelowe"},
{"Amount", "Ilość"},
{"Incoming Tags", "Przychodzące tagi"},
{"Tags sessions", "Sesje tagów"},
{"Status", "Status"},
{"Local Destination", "Lokalne miejsce docelowe"},
{"Streams", "Strumienie"},
{"Close stream", "Zamknij strumień"},
{"Such destination is not found", "Nie znaleziono takiego miejsca docelowego"},
{"I2CP session not found", "Sesja I2CP nie została znaleziona"},
{"I2CP is not enabled", "I2CP nie jest włączone"},
{"Invalid", "Niepoprawny"},
{"Store type", "Rodzaj przechowywania"},
{"Expires", "Wygasa za"},
{"Non Expired Leases", "Leasingi niewygasłe"},
{"Gateway", "Brama"},
{"TunnelID", "IDTunelu"},
{"EndDate", "DataZakończenia"},
{"floodfill mode is disabled", "tryb floodfill jest wyłączony"},
{"Queue size", "Wielkość kolejki"},
{"Run peer test", "Wykonaj test peer"},
{"Reload tunnels configuration", "Załaduj ponownie konfigurację tuneli"},
{"Decline transit tunnels", "Odrzuć tunele tranzytowe"},
{"Accept transit tunnels", "Akceptuj tunele tranzytowe"},
{"Cancel graceful shutdown", "Anuluj łagodne wyłączenie"},
{"Start graceful shutdown", "Rozpocznij łagodne wyłączenie"},
{"Force shutdown", "Wymuś wyłączenie"},
{"Reload external CSS styles", "Odśwież zewnętrzne style CSS"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Uwaga:</b> każda akcja wykonana tutaj nie jest trwała i nie zmienia Twoich plików konfiguracyjnych."},
{"Logging level", "Poziom logowania"},
{"Transit tunnels limit", "Limit tuneli tranzytowych"},
{"Change", "Zmień"},
{"Change language", "Zmień język"},
{"no transit tunnels currently built", "brak obecnie zbudowanych tuneli tranzytowych"},
{"SAM disabled", "SAM wyłączony"},
{"no sessions currently running", "brak aktualnie uruchomionych sesji"},
{"SAM session not found", "Sesja SAM nie została znaleziona"},
{"SAM Session", "Sesja SAM"},
{"Server Tunnels", "Tunele Serwera"},
{"Client Forwards", "Przekierowania Klienta"},
{"Server Forwards", "Przekierowania Serwera"},
{"Unknown page", "Nieznana strona"},
{"Invalid token", "Nieprawidłowy token"},
{"SUCCESS", "SUKCES"},
{"Stream closed", "Strumień zamknięty"},
{"Stream not found or already was closed", "Strumień nie został znaleziony lub został już zamknięty"},
{"Destination not found", "Nie znaleziono punktu docelowego"},
{"StreamID can't be null", "StreamID nie może być null"},
{"Return to destination page", "Wróć do strony miejsca docelowego"},
{"You will be redirected in %d seconds", "Zostaniesz prekierowany za %d sekund"},
{"LeaseSet expiration time updated", "Zaktualizowano czas wygaśnięcia LeaseSet"},
{"LeaseSet is not found or already expired", "LeaseSet nie został znaleziony lub już wygasł"},
{"Transit tunnels count must not exceed %d", "Liczba tuneli tranzytowych nie może przekraczać %d"},
{"Back to commands list", "Powrót do listy poleceń"},
{"Register at reg.i2p", "Zarejestruj się na reg.i2p"},
{"Description", "Opis"},
{"A bit information about service on domain", "Trochę informacji o usłudze w domenie"},
{"Submit", "Zatwierdź"},
{"Domain can't end with .b32.i2p", "Domena nie może kończyć się na .b32.i2p"},
{"Domain must end with .i2p", "Domena musi kończyć się na .i2p"},
{"Unknown command", "Nieznana komenda"},
{"Command accepted", "Polecenie zaakceptowane"},
{"Proxy error", "Błąd serwera proxy"},
{"Proxy info", "Informacje o proxy"},
{"Proxy error: Host not found", "Błąd proxy: Nie znaleziono hosta"},
{"Remote host not found in router's addressbook", "Nie znaleziono zdalnego hosta w książce adresowej routera"},
{"You may try to find this host on jump services below", "Możesz znaleźć tego hosta na poniższych usługach skoku"},
{"Invalid request", "Nieprawidłowe żądanie"},
{"Proxy unable to parse your request", "Serwer proxy nie może przetworzyć Twojego żądania"},
{"Addresshelper is not supported", "Adresshelper nie jest obsługiwany"},
{"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>.", "Host %s <font color=red>jest już w książce adresowej routera</font>. <b>Uważaj: źródło tego adresu URL może być szkodliwe!</b> Kliknij tutaj, aby zaktualizować rekord: <a href=\"%s%s%s&update=true\">Kontynuuj</a>."},
{"Addresshelper forced update rejected", "Wymuszona aktualizacja Addreshelper odrzucona"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Aby dodać host <b>%s</b> w książce adresowej routera, kliknij tutaj: <a href=\"%s%s%s\">Kontynuuj</a>."},
{"Addresshelper request", "Prośba Addresshelper"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Host %s dodany do książki adresowej routera od pomocnika. Kliknij tutaj, aby kontynuować: <a href=\"%s\">Kontynuuj</a>."},
{"Addresshelper adding", "Dodawanie Addresshelper"},
{"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>.", "Host %s jest <font color=red>już w książce adresowej routera</font>. Kliknij tutaj, aby zaktualizować rekord: <a href=\"%s%s%s&update=true\">Kontynuuj</a>."},
{"Addresshelper update", "Aktualizacja Adresshelper"},
{"Invalid request URI", "Nieprawidłowe URI żądania"},
{"Can't detect destination host from request", "Nie można wykryć hosta docelowego z żądania"},
{"Outproxy failure", "Błąd proxy wyjściowego"},
{"Bad outproxy settings", "Błędne ustawienia proxy wyjściowych"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s nie jest wewnątrz sieci I2P, a proxy wyjściowe nie jest włączone"},
{"Unknown outproxy URL", "Nieznany adres URL proxy wyjściowego"},
{"Cannot resolve upstream proxy", "Nie można rozwiązać serwera proxy upstream"},
{"Hostname is too long", "Nazwa hosta jest zbyt długa"},
{"Cannot connect to upstream SOCKS proxy", "Nie można połączyć się z proxy SOCKS upstream"},
{"Cannot negotiate with SOCKS proxy", "Nie można negocjować z proxy SOCKS"},
{"CONNECT error", "Błąd POŁĄCZENIE"},
{"Failed to connect", "Nie udało się połączyć"},
{"SOCKS proxy error", "Błąd proxy SOCKS"},
{"Failed to send request to upstream", "Nie udało się wysłać żądania do upstream"},
{"No reply from SOCKS proxy", "Brak odpowiedzi od serwera proxy SOCKS"},
{"Cannot connect", "Nie można się połączyć"},
{"HTTP out proxy not implemented", "Serwer wyjściowy proxy HTTP nie został zaimplementowany"},
{"Cannot connect to upstream HTTP proxy", "Nie można połączyć się z proxy HTTP upstream"},
{"Host is down", "Host jest niedostępny"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Nie można utworzyć połączenia z żądanym hostem, może być wyłączony. Spróbuj ponownie później."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d dzień", "%d dni", "%d dni", "%d dni"}},
{"%d hours", {"%d godzina", "%d godziny", "%d godzin", "%d godzin"}},
{"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}},
{"%d seconds", {"%d sekunda", "%d sekundy", "%d sekund", "%d sekund"}},
{"", {"", "", "", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

@ -0,0 +1,223 @@
/*
* Copyright (c) 2023-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Portuguese localization file
namespace i2p
{
namespace i18n
{
namespace portuguese // language namespace
{
// language name in lowercase
static std::string language = "portuguese";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "construindo"},
{"failed", "falhou"},
{"expiring", "expirando"},
{"established", "estabelecido"},
{"unknown", "desconhecido"},
{"exploratory", "exploratório"},
{"Purple I2P Webconsole", "Webconsole Purple I2P"},
{"<b>i2pd</b> webconsole", "webconsole <b>i2pd</b>"},
{"Main page", "Página Principal"},
{"Router commands", "Comandos do Roteador"},
{"Local Destinations", "Destinos Locais"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Túneis"},
{"Transit Tunnels", "Túneis de Trânsito"},
{"Transports", "Transportes"},
{"I2P tunnels", "Túneis I2P"},
{"SAM sessions", "Sessões do SAM"},
{"ERROR", "ERRO"},
{"OK", "OK"},
{"Testing", "Testando"},
{"Firewalled", "Sob Firewall"},
{"Unknown", "Desconhecido"},
{"Proxy", "Proxy"},
{"Mesh", "Malha"},
{"Clock skew", "Desvio de Relógio"},
{"Offline", "Desligado"},
{"Symmetric NAT", "NAT Simétrico"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Sem Descritores"},
{"Uptime", "Tempo Ativo"},
{"Network status", "Estado da rede"},
{"Network status v6", "Estado da rede v6"},
{"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"},
{"Transit", "Trânsito"},
{"Data path", "Diretório de dados"},
{"Hidden content. Press on text to see.", "Conteúdo oculto. Clique no texto para revelar."},
{"Router Ident", "Identidade do Roteador"},
{"Router Family", "Família do Roteador"},
{"Router Caps", "Limites do Roteador"},
{"Version", "Versão"},
{"Our external address", "Nosso endereço externo"},
{"supported", "suportado"},
{"Routers", "Roteadores"},
{"Floodfills", "Modo Inundação"},
{"Client Tunnels", "Túneis de Clientes"},
{"Services", "Serviços"},
{"Enabled", "Ativado"},
{"Disabled", "Desativado"},
{"Encrypted B33 address", "Endereço B33 criptografado"},
{"Address registration line", "Linha de cadastro de endereço"},
{"Domain", "Domínio"},
{"Generate", "Gerar"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b> Nota: </b>A string resultante só pode ser usada para registrar domínios 2LD (exemplo.i2p). Para registrar subdomínios por favor utilize o i2pd-tools."},
{"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"},
{"Tags", "Etiquetas"},
{"Incoming", "Entradas"},
{"Outgoing", "Saídas"},
{"Destination", "Destinos"},
{"Amount", "Quantidade"},
{"Incoming Tags", "Etiquetas de Entrada"},
{"Tags sessions", "Sessões de Etiquetas"},
{"Status", "Estado"},
{"Local Destination", "Destino Local"},
{"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"},
{"Store type", "Tipo de armazenamento"},
{"Expires", "Expira em"},
{"Non Expired Leases", "Sessões não expiradas"},
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Data final"},
{"floodfill mode is disabled", "Mode de inundação está desativado"},
{"Queue size", "Tamanho da fila"},
{"Run peer test", "Executar teste de peers"},
{"Reload tunnels configuration", "Recarregar a configuração dos túneis"},
{"Decline transit tunnels", "Negar túneis de trânsito"},
{"Accept transit tunnels", "Aceitar túneis de trânsito"},
{"Cancel graceful shutdown", "Cancelar desligamento gracioso"},
{"Start graceful shutdown", "Iniciar desligamento gracioso"},
{"Force shutdown", "Forçar desligamento"},
{"Reload external CSS styles", "Recarregar estilos CSS externos"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b> Nota: </b> Qualquer ação feita aqui não será permanente e não altera os seus arquivos de configuração."},
{"Logging level", "Nível de registro"},
{"Transit tunnels limit", "Limite de túneis de trânsito"},
{"Change", "Mudar"},
{"Change language", "Trocar idioma"},
{"no transit tunnels currently built", "Nenhum túnel de trânsito construido no momento"},
{"SAM disabled", "SAM desativado"},
{"no sessions currently running", "Nenhuma sessão funcionando no momento"},
{"SAM session not found", "Nenhuma sessão do SAM encontrada"},
{"SAM Session", "Sessão do SAM"},
{"Server Tunnels", "Túneis de Servidor"},
{"Client Forwards", "Túneis de Cliente"},
{"Server Forwards", "Encaminhamentos de Servidor"},
{"Unknown page", "Página desconhecida"},
{"Invalid token", "Token Inválido"},
{"SUCCESS", "SUCESSO"},
{"Stream closed", "Fluxo fechado"},
{"Stream not found or already was closed", "Fluxo não encontrado ou já fechado"},
{"Destination not found", "Destino não encontrado"},
{"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 em reg.i2p"},
{"Description", "Descrição"},
{"A bit information about service on domain", "Algumas informações sobre o serviço no domínio"},
{"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"},
{"Unknown command", "Comando desconhecido"},
{"Command accepted", "Comando aceito"},
{"Proxy error", "Erro no proxy"},
{"Proxy info", "Informações do proxy"},
{"Proxy error: Host not found", "Erro no proxy: Host não encontrado"},
{"Remote host not found in router's addressbook", "O host remoto não foi encontrado no livro de endereços do roteador"},
{"You may try to find this host on jump services below", "Você pode tentar encontrar este host nos serviços de jump abaixo"},
{"Invalid request", "Requisição inválida"},
{"Proxy unable to parse your request", "O proxy foi incapaz de processar a sua requisição"},
{"Addresshelper is not supported", "O Auxiliar de Endereços não é suportado"},
{"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>.", "O host %s já <font color=red>está no catálogo de endereços do roteador</font>. <b>Cuidado: a fonte desta URL pode ser perigosa!</b> Clique aqui para atualizar o registro: <a href=\"%s%s%s&update=true\">Continuar</a>."},
{"Addresshelper forced update rejected", "A atualização forçada do Auxiliar de Endereços foi rejeitada"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Para adicionar o host <b> %s </b> ao catálogo de endereços do roteador, clique aqui: <a href='%s%s%s'>Continuar </a>."},
{"Addresshelper request", "Requisição ao Auxiliar de Endereços"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "O host %s foi adicionado ao catálogo de endereços do roteador por um auxiliar. Clique aqui para prosseguir: <a href='%s'> Continuar </a>."},
{"Addresshelper adding", "Auxiliar de Endereço adicionando"},
{"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>.", "O host %s já <font color=red>está no catálogo de endereços do roteador </font>. Clique aqui para atualizar o registro: <a href=\"%s%s%s&update=true\">Continuar</a>."},
{"Addresshelper update", "Atualização do Auxiliar de Endereços"},
{"Invalid request URI", "A URI de requisição é inválida"},
{"Can't detect destination host from request", "Incapaz de detectar o host de destino da requisição"},
{"Outproxy failure", "Falha no outproxy"},
{"Bad outproxy settings", "Má configurações do outproxy"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "O host %s não está dentro da rede I2P, mas o outproxy não está ativado"},
{"Unknown outproxy URL", "URL de outproxy desconhecida"},
{"Cannot resolve upstream proxy", "Não é possível resolver o proxy de entrada"},
{"Hostname is too long", "O hostname é muito longo"},
{"Cannot connect to upstream SOCKS proxy", "Não é possível se conectar ao proxy SOCKS de entrada"},
{"Cannot negotiate with SOCKS proxy", "Não é possível negociar com o proxy SOCKS"},
{"CONNECT error", "Erro de CONEXÃO"},
{"Failed to connect", "Falha ao conectar"},
{"SOCKS proxy error", "Erro no proxy SOCKS"},
{"Failed to send request to upstream", "Falha ao enviar requisição para o fluxo de entrada"},
{"No reply from SOCKS proxy", "Sem resposta do proxy SOCKS"},
{"Cannot connect", "Impossível conectar"},
{"HTTP out proxy not implemented", "proxy de saída HTTP não implementado"},
{"Cannot connect to upstream HTTP proxy", "Não é possível conectar ao proxy HTTP de entrada"},
{"Host is down", "Host está desligado"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Não é possível se conectar ao host requisitado, talvez ele esteja for do ar. Por favor, tente novamente mais tarde."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d Dia", "%d Dias"}},
{"%d hours", {"%d hora", "%d horas"}},
{"%d minutes", {"%d minuto", "%d minutos"}},
{"%d seconds", {"%d Segundo", "%d segundos"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,15 +31,16 @@ namespace russian // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "КиБ"},
{"MiB", "МиБ"},
{"GiB", "ГиБ"},
{"%.2f KiB", "%.2f КиБ"},
{"%.2f MiB", "%.2f МиБ"},
{"%.2f GiB", "%.2f ГиБ"},
{"building", "строится"},
{"failed", "неудачный"},
{"expiring", "истекает"},
{"established", "работает"},
{"unknown", "неизвестно"},
{"exploratory", "исследовательский"},
{"Purple I2P Webconsole", "Веб-консоль Purple I2P"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Главная"},
{"Router commands", "Команды роутера"},
@ -57,18 +58,20 @@ namespace russian // language namespace
{"Unknown", "Неизвестно"},
{"Proxy", "Прокси"},
{"Mesh", "MESH-сеть"},
{"Error", "Ошибка"},
{"Clock skew", "Не точное время"},
{"Offline", "Оффлайн"},
{"Symmetric NAT", "Симметричный NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Нет дескрипторов"},
{"Uptime", "В сети"},
{"Network status", "Сетевой статус"},
{"Network status v6", "Сетевой статус v6"},
{"Stopping in", "Остановка через"},
{"Family", "Семейство"},
{"Tunnel creation success rate", "Успешно построенных туннелей"},
{"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"},
{"Received", "Получено"},
{"KiB/s", "КиБ/с"},
{"%.2f KiB/s", "%.2f КиБ/с"},
{"Sent", "Отправлено"},
{"Transit", "Транзит"},
{"Data path", "Путь к данным"},
@ -93,8 +96,9 @@ namespace russian // language namespace
{"Address", "Адрес"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Просрочить Лизсет"},
{"Inbound tunnels", "Входящие туннели"},
{"ms", "мс"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Исходящие туннели"},
{"Tags", "Теги"},
{"Incoming", "Входящие"},
@ -107,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", "Некорректный"},
@ -116,9 +121,10 @@ namespace russian // language namespace
{"Gateway", "Шлюз"},
{"TunnelID", "ID туннеля"},
{"EndDate", "Заканчивается"},
{"not floodfill", "не флудфил"},
{"floodfill mode is disabled", "режим флудфила отключен"},
{"Queue size", "Размер очереди"},
{"Run peer test", "Запустить тестирование"},
{"Reload tunnels configuration", "Перезагрузить конфигурацию туннелей"},
{"Decline transit tunnels", "Отклонять транзитные туннели"},
{"Accept transit tunnels", "Принимать транзитные туннели"},
{"Cancel graceful shutdown", "Отменить плавную остановку"},
@ -146,8 +152,10 @@ namespace russian // language namespace
{"Destination not found", "Точка назначения не найдена"},
{"StreamID can't be null", "StreamID не может быть пустым"},
{"Return to destination page", "Вернуться на страницу точки назначения"},
{"You will be redirected in 5 seconds", "Вы будете переадресованы через 5 секунд"},
{"Transit tunnels count must not exceed 65535", "Число транзитных туннелей не должно превышать 65535"},
{"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"},
{"Description", "Описание"},
@ -155,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", "Ошибка прокси"},
@ -165,32 +172,33 @@ namespace russian // language namespace
{"You may try to find this host on jump services below", "Вы можете попробовать найти узел через джамп сервисы ниже"},
{"Invalid request", "Некорректный запрос"},
{"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"},
{"addresshelper is not supported", "addresshelper не поддерживается"},
{"Host", "Узел"},
{"added to router's addressbook from helper", "добавлен в адресную книгу роутера через хелпер"},
{"Click here to proceed:", "Нажмите здесь, чтобы продолжить:"},
{"Continue", "Продолжить"},
{"Addresshelper found", "Найден addresshelper"},
{"already in router's addressbook", "уже в адресной книге роутера"},
{"Click here to update record:", "Нажмите здесь, чтобы обновить запись:"},
{"invalid request uri", "некорректный URI запроса"},
{"Addresshelper is not supported", "Addresshelper не поддерживается"},
{"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>.", "Узел %s <font color=red>уже в адресной книге роутера</font>. <b>Будьте осторожны: источник данной ссылки может быть вредоносным!</b> Нажмите здесь, чтобы обновить запись: <a href=\"%s%s%s&update=true\">Продолжить</a>."},
{"Addresshelper forced update rejected", "Принудительное обновление через Addresshelper отклонено"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Чтобы добавить узел <b>%s</b> в адресную книгу роутера, нажмите здесь: <a href=\"%s%s%s\">Продолжить</a>."},
{"Addresshelper request", "Запрос добавления Addresshelper"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Узел %s добавлен в адресную книгу роутера через хелпер. Нажмите здесь, чтобы продолжить: <a href=\"%s\">Продолжить</a>."},
{"Addresshelper adding", "Добавление Addresshelper"},
{"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>.", "Узел %s <font color=red>уже в адресной книге роутера</font>. Нажмите здесь, чтобы обновить запись: <a href=\"%s%s%s&update=true\">Продолжить</a>."},
{"Addresshelper update", "Обновление записи через Addresshelper"},
{"Invalid request URI", "Некорректный URI запроса"},
{"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"},
{"Outproxy failure", "Ошибка внешнего прокси"},
{"bad outproxy settings", "некорректные настройки внешнего прокси"},
{"not inside I2P network, but outproxy is not enabled", "не в I2P сети, но внешний прокси не включен"},
{"unknown outproxy url", "неизвестный URL внешнего прокси"},
{"cannot resolve upstream proxy", "не удается определить вышестоящий прокси"},
{"hostname too long", "имя хоста слишком длинное"},
{"cannot connect to upstream socks proxy", "не удается подключиться к вышестоящему SOCKS прокси"},
{"Cannot negotiate with socks proxy", "Не удается договориться с вышестоящим SOCKS прокси"},
{"Bad outproxy settings", "Некорректные настройки внешнего прокси"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Узел %s не в I2P сети, но внешний прокси не включен"},
{"Unknown outproxy URL", "Неизвестный URL внешнего прокси"},
{"Cannot resolve upstream proxy", "Не удается определить вышестоящий прокси"},
{"Hostname is too long", "Имя хоста слишком длинное"},
{"Cannot connect to upstream SOCKS proxy", "Не удалось подключиться к вышестоящему SOCKS прокси серверу"},
{"Cannot negotiate with SOCKS proxy", "Не удается договориться с вышестоящим SOCKS прокси"},
{"CONNECT error", "Ошибка CONNECT запроса"},
{"Failed to Connect", "Не удалось подключиться"},
{"socks proxy error", "ошибка SOCKS прокси"},
{"failed to send request to upstream", "не удалось отправить запрос вышестоящему прокси"},
{"No Reply From socks proxy", "Нет ответа от SOCKS прокси сервера"},
{"cannot connect", "не удалось подключиться"},
{"http out proxy not implemented", "поддержка внешнего HTTP прокси сервера не реализована"},
{"cannot connect to upstream http proxy", "не удалось подключиться к вышестоящему HTTP прокси серверу"},
{"Failed to connect", "Не удалось соединиться"},
{"SOCKS proxy error", "Ошибка SOCKS прокси"},
{"Failed to send request to upstream", "Не удалось отправить запрос вышестоящему прокси серверу"},
{"No reply from SOCKS proxy", "Нет ответа от SOCKS прокси сервера"},
{"Cannot connect", "Не удалось подключиться"},
{"HTTP out proxy not implemented", "Поддержка внешнего HTTP прокси сервера не реализована"},
{"Cannot connect to upstream HTTP proxy", "Не удалось подключиться к вышестоящему HTTP прокси серверу"},
{"Host is down", "Узел недоступен"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному узлу, возможно он не в сети. Попробуйте повторить запрос позже."},
{"", ""},
@ -198,10 +206,10 @@ namespace russian // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"день", "дня", "дней"}},
{"hours", {"час", "часа", "часов"}},
{"minutes", {"минуту", "минуты", "минут"}},
{"seconds", {"секунду", "секунды", "секунд"}},
{"%d days", {"%d день", "%d дня", "%d дней"}},
{"%d hours", {"%d час", "%d часа", "%d часов"}},
{"%d minutes", {"%d минуту", "%d минуты", "%d минут"}},
{"%d seconds", {"%d секунду", "%d секунды", "%d секунд"}},
{"", {"", "", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,9 +31,9 @@ namespace spanish // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "pendiente"},
{"failed", "fallido"},
{"expiring", "expiró"},
@ -58,7 +58,6 @@ namespace spanish // language namespace
{"Unknown", "Desconocido"},
{"Proxy", "Proxy"},
{"Mesh", "Malla"},
{"Error", "Error"},
{"Clock skew", "Reloj desfasado"},
{"Offline", "Desconectado"},
{"Symmetric NAT", "NAT simétrico"},
@ -69,7 +68,7 @@ namespace spanish // language namespace
{"Family", "Familia"},
{"Tunnel creation success rate", "Tasa de éxito de creación de túneles"},
{"Received", "Recibido"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Enviado"},
{"Transit", "Tránsito"},
{"Data path", "Ruta de datos"},
@ -95,7 +94,7 @@ namespace spanish // language namespace
{"Type", "Tipo"},
{"EncType", "TipoEncrip"},
{"Inbound tunnels", "Túneles entrantes"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Túneles salientes"},
{"Tags", "Etiquetas"},
{"Incoming", "Entrante"},
@ -117,7 +116,6 @@ namespace spanish // language namespace
{"Gateway", "Puerta de enlace"},
{"TunnelID", "TunnelID"},
{"EndDate", "FechaVenc"},
{"not floodfill", "no inundado"},
{"Queue size", "Tamaño de cola"},
{"Run peer test", "Ejecutar prueba de par"},
{"Decline transit tunnels", "Rechazar túneles de tránsito"},
@ -147,8 +145,6 @@ namespace spanish // language namespace
{"Destination not found", "Destino no encontrado"},
{"StreamID can't be null", "StreamID no puede ser nulo"},
{"Return to destination page", "Volver a la página de destino"},
{"You will be redirected in 5 seconds", "Serás redirigido en 5 segundos"},
{"Transit tunnels count must not exceed 65535", "La cantidad de túneles de tránsito no puede exceder 65535"},
{"Back to commands list", "Volver a lista de comandos"},
{"Register at reg.i2p", "Registrar en reg.i2p"},
{"Description", "Descripción"},
@ -166,32 +162,24 @@ namespace spanish // language namespace
{"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"},
{"Invalid request", "Solicitud inválida"},
{"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"},
{"addresshelper is not supported", "ayudante de dirección no soportado"},
{"Host", "Dominio"},
{"added to router's addressbook from helper", "añadido a la libreta de direcciones desde el ayudante"},
{"Click here to proceed:", "Haga clic aquí para continuar:"},
{"Continue", "Continuar"},
{"Addresshelper found", "Se encontró ayudante de dirección"},
{"already in router's addressbook", "ya se encontró en libreta de direcciones"},
{"Click here to update record:", "Haga clic aquí para actualizar el registro:"},
{"invalid request uri", "uri de solicitud inválida"},
{"Invalid request URI", "URI de solicitud inválida"},
{"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"},
{"Outproxy failure", "Fallo en el proxy saliente"},
{"bad outproxy settings", "configuración de outproxy incorrecta"},
{"not inside I2P network, but outproxy is not enabled", "no está dentro de la red I2P, pero el proxy de salida no está activado"},
{"unknown outproxy url", "url de proxy outproxy desconocido"},
{"cannot resolve upstream proxy", "no se puede resolver el proxy de upstream"},
{"hostname too long", "nombre de dominio muy largo"},
{"cannot connect to upstream socks proxy", "no se puede conectar al proxy socks principal"},
{"Cannot negotiate with socks proxy", "No se puede negociar con el proxy socks"},
{"Bad outproxy settings", "Configuración de outproxy incorrecta"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Dominio %s no está dentro de la red I2P, pero el proxy de salida no está activado"},
{"Unknown outproxy URL", "URL de proxy outproxy desconocido"},
{"Cannot resolve upstream proxy", "No se puede resolver el proxy de upstream"},
{"Hostname is too long", "Nombre de dominio muy largo"},
{"Cannot connect to upstream SOCKS proxy", "No se puede conectar al proxy SOCKS principal"},
{"Cannot negotiate with SOCKS proxy", "No se puede negociar con el proxy SOCKS"},
{"CONNECT error", "Error de CONNECT"},
{"Failed to Connect", "Error al Conectar"},
{"socks proxy error", "error de proxy socks"},
{"failed to send request to upstream", "no se pudo enviar petición al principal"},
{"No Reply From socks proxy", "Sin respuesta del proxy socks"},
{"cannot connect", "no se puede conectar"},
{"http out proxy not implemented", "proxy externo http no implementado"},
{"cannot connect to upstream http proxy", "no se puede conectar al proxy http principal"},
{"Failed to connect", "Error al conectar"},
{"SOCKS proxy error", "Error de proxy SOCKS"},
{"Failed to send request to upstream", "No se pudo enviar petición al principal"},
{"No reply from SOCKS proxy", "Sin respuesta del proxy SOCKS"},
{"Cannot connect", "No se puede conectar"},
{"HTTP out proxy not implemented", "Proxy externo HTTP no implementado"},
{"Cannot connect to upstream HTTP proxy", "No se puede conectar al proxy HTTP principal"},
{"Host is down", "Servidor caído"},
{"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."},
{"", ""},
@ -199,10 +187,10 @@ namespace spanish // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"día", "días"}},
{"hours", {"hora", "horas"}},
{"minutes", {"minuto", "minutos"}},
{"seconds", {"segundo", "segundos"}},
{"%d days", {"%d día", "%d días"}},
{"%d hours", {"%d hora", "%d horas"}},
{"%d minutes", {"%d minuto", "%d minutos"}},
{"%d seconds", {"%d segundo", "%d segundos"}},
{"", {"", ""}},
};

@ -0,0 +1,220 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Swedish localization file
namespace i2p
{
namespace i18n
{
namespace swedish // language namespace
{
// language name in lowercase
static std::string language = "swedish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "bygger"},
{"failed", "misslyckad"},
{"expiring", "utgår"},
{"established", "upprättad"},
{"unknown", "okänt"},
{"exploratory", "utforskande"},
{"Purple I2P Webconsole", "Purple I2P Webbkonsoll"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b>-Webbkonsoll"},
{"Main page", "Huvudsida"},
{"Router commands", "Routerkommandon"},
{"Local Destinations", "Lokala Platser"},
{"LeaseSets", "Hyresuppsättningar"},
{"Tunnels", "Tunnlar"},
{"Transit Tunnels", "Förmedlande Tunnlar"},
{"Transports", "Transporter"},
{"I2P tunnels", "I2P-tunnlar"},
{"SAM sessions", "SAM-perioder"},
{"ERROR", "FEL"},
{"OK", "OK"},
{"Testing", "Prövar"},
{"Firewalled", "Bakom Brandvägg"},
{"Unknown", "Okänt"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"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"},
{"Stopping in", "Avstängd om"},
{"Family", "Familj"},
{"Tunnel creation success rate", "Andel framgångsrika tunnlar"},
{"Received", "Mottaget"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Skickat"},
{"Transit", "Förmedlat"},
{"Data path", "Sökväg"},
{"Hidden content. Press on text to see.", "Dolt innehåll. Tryck för att visa."},
{"Router Ident", "Routeridentitet"},
{"Router Family", "Routerfamilj"},
{"Router Caps", "Routerbegränsningar"},
{"Version", "Version"},
{"Our external address", "Vår externa adress"},
{"supported", "stöds"},
{"Routers", "Routrar"},
{"Floodfills", "Översvämningsfyllare"},
{"Client Tunnels", "Klienttunnlar"},
{"Services", "Tjänster"},
{"Enabled", "Påslaget"},
{"Disabled", "Avslaget"},
{"Encrypted B33 address", "Krypterad B33-Adress"},
{"Address registration line", "Adressregistreringsrad"},
{"Domain", "Domän"},
{"Generate", "Skapa"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Uppmärksamma:</b> den resulterande strängen kan enbart användas för att registrera 2LD-domäner (exempel.i2p). För att registrera underdomäner, vänligen använd i2pd-tools."},
{"Address", "Adress"},
{"Type", "Typ"},
{"EncType", "EncTyp"},
{"Inbound tunnels", "Ingående Tunnlar"},
{"%dms", "%dms"},
{"Outbound tunnels", "Utgående Tunnlar"},
{"Tags", "Taggar"},
{"Incoming", "Ingående"},
{"Outgoing", "Utgående"},
{"Destination", "Plats"},
{"Amount", "Mängd"},
{"Incoming Tags", "Ingående Taggar"},
{"Tags sessions", "Tagg-perioder"},
{"Status", "Tillstånd"},
{"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"},
{"Store type", "Lagringstyp"},
{"Expires", "Utgångsdatum"},
{"Non Expired Leases", "Ickeutgångna Hyresuppsättningar"},
{"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"},
{"Start graceful shutdown", "Påbörja välvillig avstängning"},
{"Force shutdown", "Tvingad avstängning"},
{"Reload external CSS styles", "Ladda om externa CSS-stilar"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Uppmärksamma:</b> inga ändringar här är beständiga eller påverkar dina inställningsfiler."},
{"Logging level", "Protokollförningsnivå"},
{"Transit tunnels limit", "Begränsa förmedlande tunnlar"},
{"Change", "Ändra"},
{"Change language", "Ändra språk"},
{"no transit tunnels currently built", "inga förmedlande tunnlar har byggts"},
{"SAM disabled", "SAM avslaget"},
{"no sessions currently running", "inga perioder igång"},
{"SAM session not found", "SAM-perioder hittades ej"},
{"SAM Session", "SAM-period"},
{"Server Tunnels", "Värdtunnlar"},
{"Client Forwards", "Klientförpassningar"},
{"Server Forwards", "Värdförpassningar"},
{"Unknown page", "Okänd sida"},
{"Invalid token", "Ogiltig polett"},
{"SUCCESS", "FRAMGÅNG"},
{"Stream closed", "Ström stängd"},
{"Stream not found or already was closed", "Strömmen hittades inte eller var redan avslutad"},
{"Destination not found", "Plats hittades ej"},
{"StreamID can't be null", "Ström-ID kan inte vara null"},
{"Return to destination page", "Återvänd till platssidan"},
{"You will be redirected in %d seconds", "Du omdirigeras inom %d sekunder"},
{"Transit tunnels count must not exceed %d", "Förmedlande tunnlar får inte överstiga %d"},
{"Back to commands list", "Tillbaka till kommandolistan"},
{"Register at reg.i2p", "Registrera vid reg.i2p"},
{"Description", "Beskrivning"},
{"A bit information about service on domain", "Ett stycke information om domänens tjänst"},
{"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"},
{"Unknown command", "Okänt kommando"},
{"Command accepted", "Kommando accepterades"},
{"Proxy error", "Proxyfel"},
{"Proxy info", "Proxyinfo"},
{"Proxy error: Host not found", "Proxyfel: Värden hittades ej"},
{"Remote host not found in router's addressbook", "Främmande värd hittades inte i routerns adressbok"},
{"You may try to find this host on jump services below", "Du kan försöka att hitta värden genom hopptjänsterna nedan"},
{"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"},
{"Bad outproxy settings", "Ogiltig utproxyinställning"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Värd %s är inte inom I2P-näverket, men utproxy är inte påslaget"},
{"Unknown outproxy URL", "okänt Utproxy-URL"},
{"Cannot resolve upstream proxy", "Hittar inte uppströmsproxyt"},
{"Hostname is too long", "Värdnamnet är för långt"},
{"Cannot connect to upstream SOCKS proxy", "Kan inte ansluta till uppström SOCKS-proxy"},
{"Cannot negotiate with SOCKS proxy", "Kan inte förhandla med SOCKSproxyt"},
{"CONNECT error", "CONNECT-fel"},
{"Failed to connect", "Anslutningen misslyckades"},
{"SOCKS proxy error", "SOCKSproxyfel"},
{"Failed to send request to upstream", "Förfrågan uppströms kunde ej skickas"},
{"No reply from SOCKS proxy", "Fick inget svar från SOCKSproxyt"},
{"Cannot connect", "Kan inte ansluta"},
{"HTTP out proxy not implemented", "HTTP-Utproxy ej implementerat"},
{"Cannot connect to upstream HTTP proxy", "Kan inte ansluta till uppströms HTTP-proxy"},
{"Host is down", "Värden är nere"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Kan inte ansluta till värden, den kan vara nere. Vänligen försök senare."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d dag", "%d dagar"}},
{"%d hours", {"%d timme", "%d timmar"}},
{"%d minutes", {"%d minut", "%d minuter"}},
{"%d seconds", {"%d sekund", "%d sekunder"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

@ -0,0 +1,114 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Turkish localization file
namespace i2p
{
namespace i18n
{
namespace turkish // language namespace
{
// language name in lowercase
static std::string language = "turkish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "kuruluyor"},
{"failed", "başarısız"},
{"expiring", "süresi geçiyor"},
{"established", "kurulmuş"},
{"unknown", "bilinmeyen"},
{"Purple I2P Webconsole", "Mor I2P Webkonsolu"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsolu"},
{"Main page", "Ana sayfa"},
{"Router commands", "Router komutları"},
{"Local Destinations", "Yerel Hedefler"},
{"Tunnels", "Tüneller"},
{"Transit Tunnels", "Transit Tünelleri"},
{"Transports", "Taşıma"},
{"I2P tunnels", "I2P tünelleri"},
{"SAM sessions", "SAM oturumları"},
{"ERROR", "HATA"},
{"OK", "TAMAM"},
{"Testing", "Test ediliyor"},
{"Firewalled", "Güvenlik Duvarı Kısıtlaması"},
{"Unknown", "Bilinmeyen"},
{"Proxy", "Proxy"},
{"Clock skew", "Saat sorunu"},
{"Offline", "Çevrimdışı"},
{"Symmetric NAT", "Simetrik NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Tanımlayıcı Yok"},
{"Uptime", "Bağlantı süresi"},
{"Network status", "Ağ durumu"},
{"Network status v6", "Ağ durumu v6"},
{"Family", "Aile"},
{"Tunnel creation success rate", "Tünel oluşturma başarı oranı"},
{"Received", "Alındı"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Gönderildi"},
{"Transit", "Transit"},
{"Data path", "Veri yolu"},
{"Hidden content. Press on text to see.", "Gizlenmiş içerik. Görmek için yazıya tıklayınız."},
{"Router Family", "Router Familyası"},
{"Decline transit tunnels", "Transit tünellerini reddet"},
{"Accept transit tunnels", "Transit tünellerini kabul et"},
{"Cancel graceful shutdown", "Düzgün durdurmayı iptal Et"},
{"Start graceful shutdown", "Düzgün durdurmayı başlat"},
{"Force shutdown", "Durdurmaya zorla"},
{"Reload external CSS styles", "Harici CSS stilini yeniden yükle"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Not:</b> burada yapılan ayarların hiçbiri kalıcı değildir ve ayar dosyalarınızı değiştirmez."},
{"Logging level", "Kayıt tutma seviyesi"},
{"Transit tunnels limit", "Transit tünel limiti"},
{"Change", "Değiştir"},
{"Change language", "Dil değiştir"},
{"no transit tunnels currently built", "kurulmuş bir transit tüneli bulunmamakta"},
{"SAM disabled", "SAM devre dışı"},
{"no sessions currently running", "hiçbir oturum şu anda çalışmıyor"},
{"SAM session not found", "SAM oturumu bulunamadı"},
{"SAM Session", "SAM oturumu"},
{"Server Tunnels", "Sunucu Tünelleri"},
{"Unknown page", "Bilinmeyen sayfa"},
{"Invalid token", "Geçersiz token"},
{"SUCCESS", "BAŞARILI"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d gün", "%d gün"}},
{"%d hours", {"%d saat", "%d saat"}},
{"%d minutes", {"%d dakika", "%d dakika"}},
{"%d seconds", {"%d saniye", "%d saniye"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,15 +31,16 @@ namespace turkmen // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "bina"},
{"failed", "şowsuz"},
{"expiring", "möhleti gutarýar"},
{"established", "işleýär"},
{"unknown", "näbelli"},
{"exploratory", "gözleg"},
{"Purple I2P Webconsole", "Web konsoly Purple I2P"},
{"<b>i2pd</b> webconsole", "Web konsoly <b>i2pd</b>"},
{"Main page", "Esasy sahypa"},
{"Router commands", "Marşrutizator buýruklary"},
@ -57,7 +58,6 @@ namespace turkmen // language namespace
{"Unknown", "Näbelli"},
{"Proxy", "Proksi"},
{"Mesh", "MESH-tor"},
{"Error", "Ýalňyşlyk"},
{"Clock skew", "Takyk wagt däl"},
{"Offline", "Awtonom"},
{"Symmetric NAT", "Simmetriklik NAT"},
@ -68,7 +68,7 @@ namespace turkmen // language namespace
{"Family", "Maşgala"},
{"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"},
{"Received", "Alnan"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Ýerleşdirildi"},
{"Transit", "Tranzit"},
{"Data path", "Maglumat ýoly"},
@ -94,7 +94,7 @@ namespace turkmen // language namespace
{"Type", "Görnüş"},
{"EncType", "Şifrlemek görnüşi"},
{"Inbound tunnels", "Gelýän tuneller"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Çykýan tuneller"},
{"Tags", "Bellikler"},
{"Incoming", "Gelýän"},
@ -116,7 +116,6 @@ namespace turkmen // language namespace
{"Gateway", "Derweze"},
{"TunnelID", "Tuneliň ID"},
{"EndDate", "Gutarýar"},
{"not floodfill", "fludfil däl"},
{"Queue size", "Nobatyň ululygy"},
{"Run peer test", "Synag başlaň"},
{"Decline transit tunnels", "Tranzit tunellerini ret ediň"},
@ -146,8 +145,6 @@ namespace turkmen // language namespace
{"Destination not found", "Niýetlenen ýeri tapylmady"},
{"StreamID can't be null", "StreamID boş bolup bilmez"},
{"Return to destination page", "Barmaly nokadynyň nokadyna gaýdyp geliň"},
{"You will be redirected in 5 seconds", "5 sekuntdan soň täzeden ugrukdyrylarsyňyz"},
{"Transit tunnels count must not exceed 65535", "Tranzit tagtalaryň sany 65535-den geçmeli däldir"},
{"Back to commands list", "Topar sanawyna dolan"},
{"Register at reg.i2p", "Reg.i2P-de hasaba duruň"},
{"Description", "Beýany"},
@ -165,32 +162,24 @@ namespace turkmen // language namespace
{"You may try to find this host on jump services below", "Aşakdaky böküş hyzmatlarynda bu öý eýesini tapmaga synanyşyp bilersiňiz"},
{"Invalid request", "Nädogry haýyş"},
{"Proxy unable to parse your request", "Proksi haýyşyňyzy derňäp bilmeýär"},
{"addresshelper is not supported", "Salgylandyryjy goldanok"},
{"Host", "Adres"},
{"added to router's addressbook from helper", "marşruteriň adresini kömekçiden goşdy"},
{"Click here to proceed:", "Dowam etmek bu ýerde basyň:"},
{"Continue", "Dowam et"},
{"Addresshelper found", "Forgelper tapyldy"},
{"already in router's addressbook", "marşruteriň adres kitaby"},
{"Click here to update record:", "Recordazgyny täzelemek üçin bu ýerde basyň:"},
{"invalid request uri", "nädogry haýyş URI"},
{"Invalid request URI", "Nädogry haýyş URI"},
{"Can't detect destination host from request", "Haýyşdan barmaly ýerini tapyp bilemok"},
{"Outproxy failure", "Daşarky proksi ýalňyşlyk"},
{"bad outproxy settings", "daşarky daşarky proksi sazlamalary nädogry"},
{"not inside I2P network, but outproxy is not enabled", "I2P torunda däl, ýöne daşarky proksi goşulmaýar"},
{"unknown outproxy url", "näbelli daşarky proksi URL"},
{"cannot resolve upstream proxy", "has ýokary proksi kesgitläp bilmeýär"},
{"hostname too long", "hoster eýesi ady gaty uzyn"},
{"cannot connect to upstream socks proxy", "ýokary jorap SOCKS proksi bilen birigip bolmaýar"},
{"Cannot negotiate with socks proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"},
{"Bad outproxy settings", "Daşarky Daşarky proksi sazlamalary nädogry"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Adres %s I2P torunda däl, ýöne daşarky proksi goşulmaýar"},
{"Unknown outproxy URL", "Näbelli daşarky proksi URL"},
{"Cannot resolve upstream proxy", "Has ýokary proksi kesgitläp bilmeýär"},
{"Hostname is too long", "Hoster eýesi ady gaty uzyn"},
{"Cannot connect to upstream SOCKS proxy", "Ýokary jorap SOCKS proksi bilen birigip bolmaýar"},
{"Cannot negotiate with SOCKS proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"},
{"CONNECT error", "Bagyr haýyşy säwligi"},
{"Failed to Connect", "Birikdirip bilmedi"},
{"socks proxy error", "socks proksi ýalňyşlygy"},
{"failed to send request to upstream", "öý eýesi proksi üçin haýyş iberip bilmedi"},
{"No Reply From socks proxy", "Jorap proksi serwerinden hiç hili jogap ýok"},
{"cannot connect", "birikdirip bilmedi"},
{"http out proxy not implemented", "daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"},
{"cannot connect to upstream http proxy", "ýokary akym HTTP proksi serwerine birigip bilmedi"},
{"Failed to connect", "Birikdirip bilmedi"},
{"SOCKS proxy error", "SOCKS proksi ýalňyşlygy"},
{"Failed to send request to upstream", "Öý eýesi proksi üçin haýyş iberip bilmedi"},
{"No reply from SOCKS proxy", "Jorap SOCKS proksi serwerinden hiç hili jogap ýok"},
{"Cannot connect", "Birikdirip bilmedi"},
{"HTTP out proxy not implemented", "Daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"},
{"Cannot connect to upstream HTTP proxy", "Ýokary jorap HTTP proksi bilen birigip bolmaýar"},
{"Host is down", "Salgy elýeterli däl"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Talap edilýän salgyda birikmäni gurup bilmedim, onlaýn bolup bilmez. Soňra haýyşy soň gaýtalamaga synanyşyň."},
{"", ""},
@ -198,10 +187,10 @@ namespace turkmen // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"gün", "gün"}},
{"hours", {"sagat", "sagat"}},
{"minutes", {"minut", "minut"}},
{"seconds", {"sekunt", "sekunt"}},
{"%d days", {"%d gün", "%d gün"}},
{"%d hours", {"%d sagat", "%d sagat"}},
{"%d minutes", {"%d minut", "%d minut"}},
{"%d seconds", {"%d sekunt", "%d sekunt"}},
{"", {"", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,15 +31,16 @@ namespace ukrainian // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "КіБ"},
{"MiB", "МіБ"},
{"GiB", "ГіБ"},
{"%.2f KiB", "%.2f КіБ"},
{"%.2f MiB", "%.2f МіБ"},
{"%.2f GiB", "%.2f ГіБ"},
{"building", "будується"},
{"failed", "невдалий"},
{"expiring", "завершується"},
{"established", "працює"},
{"unknown", "невідомо"},
{"exploratory", "дослідницький"},
{"Purple I2P Webconsole", "Веб-консоль Purple I2P"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Головна"},
{"Router commands", "Команди маршрутизатора"},
@ -57,18 +58,20 @@ namespace ukrainian // language namespace
{"Unknown", "Невідомо"},
{"Proxy", "Проксі"},
{"Mesh", "MESH-мережа"},
{"Error", "Помилка"},
{"Clock skew", "Неточний час"},
{"Offline", "Офлайн"},
{"Symmetric NAT", "Симетричний NAT"},
{"Full cone NAT", "Повний NAT"},
{"No Descriptors", "Немає Описів"},
{"Uptime", "У мережі"},
{"Network status", "Мережевий статус"},
{"Network status v6", "Мережевий статус v6"},
{"Stopping in", "Зупинка через"},
{"Family", "Сімейство"},
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
{"Total tunnel creation success rate", "Загальна кількість створених тунелів"},
{"Received", "Отримано"},
{"KiB/s", "КіБ/с"},
{"%.2f KiB/s", "%.2f КіБ/с"},
{"Sent", "Відправлено"},
{"Transit", "Транзит"},
{"Data path", "Шлях до даних"},
@ -93,8 +96,9 @@ namespace ukrainian // language namespace
{"Address", "Адреса"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Завершити LeaseSet"},
{"Inbound tunnels", "Вхідні тунелі"},
{"ms", "мс"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Вихідні тунелі"},
{"Tags", "Теги"},
{"Incoming", "Вхідні"},
@ -107,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", "Некоректний"},
@ -116,9 +121,10 @@ namespace ukrainian // language namespace
{"Gateway", "Шлюз"},
{"TunnelID", "ID тунеля"},
{"EndDate", "Закінчується"},
{"not floodfill", "не флудфіл"},
{"floodfill mode is disabled", "режим floodfill вимкнено"},
{"Queue size", "Розмір черги"},
{"Run peer test", "Запустити тестування"},
{"Reload tunnels configuration", "Перезавантажити налаштування тунелів"},
{"Decline transit tunnels", "Відхиляти транзитні тунелі"},
{"Accept transit tunnels", "Ухвалювати транзитні тунелі"},
{"Cancel graceful shutdown", "Скасувати плавну зупинку"},
@ -146,8 +152,10 @@ namespace ukrainian // language namespace
{"Destination not found", "Точка призначення не знайдена"},
{"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"},
{"Return to destination page", "Повернутися на сторінку точки призначення"},
{"You will be redirected in 5 seconds", "Ви будете переадресовані через 5 секунд"},
{"Transit tunnels count must not exceed 65535", "Кількість транзитних тунелів не повинна перевищувати 65535"},
{"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"},
{"Description", "Опис"},
@ -155,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", "Помилка проксі"},
@ -165,32 +172,33 @@ namespace ukrainian // language namespace
{"You may try to find this host on jump services below", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"},
{"Invalid request", "Некоректний запит"},
{"Proxy unable to parse your request", "Проксі не може розібрати ваш запит"},
{"addresshelper is not supported", "addresshelper не підтримується"},
{"Host", "Адреса"},
{"added to router's addressbook from helper", "доданий в адресну книгу маршрутизатора через хелпер"},
{"Click here to proceed:", "Натисніть тут щоб продовжити:"},
{"Continue", "Продовжити"},
{"Addresshelper found", "Знайдено addresshelper"},
{"already in router's addressbook", "вже в адресній книзі маршрутизатора"},
{"Click here to update record:", "Натисніть тут щоб оновити запис:"},
{"invalid request uri", "некоректний URI запиту"},
{"Addresshelper is not supported", "Адресна книга не підтримується"},
{"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>.", "Хост %s <font color=red>вже в адресній книзі маршрутизатора</font>. <b>Будьте обережні: джерело цієї адреси може зашкодити!</b> Натисніть тут, щоб оновити запис: <a href=\"%s%s%s&update=true\">Продовжити</a>."},
{"Addresshelper forced update rejected", "Адресна книга відхилила примусове оновлення"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Щоб додати хост <b>%s</b> в адресі маршрутизатора, натисніть тут: <a href=\"%s%s%s\">Продовжити</a>."},
{"Addresshelper request", "Запит на адресну сторінку"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Хост %s доданий в адресну книгу маршрутизатора від помічника. Натисніть тут, щоб продовжити: <a href=\"%s\">Продовжити</a>."},
{"Addresshelper adding", "Адреса додана"},
{"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>.", "Хост %s <font color=red>вже в адресній книзі маршрутизатора</font>. Натисніть тут, щоб оновити запис: <a href=\"%s%s%s&update=true\">Продовжити</a>."},
{"Addresshelper update", "Оновлення адресної книги"},
{"Invalid request URI", "Некоректний URI запиту"},
{"Can't detect destination host from request", "Не вдалось визначити адресу призначення з запиту"},
{"Outproxy failure", "Помилка зовнішнього проксі"},
{"bad outproxy settings", "некоректні налаштування зовнішнього проксі"},
{"not inside I2P network, but outproxy is not enabled", "не в I2P мережі, але зовнішній проксі не включений"},
{"unknown outproxy url", "невідомий URL зовнішнього проксі"},
{"cannot resolve upstream proxy", "не вдається визначити висхідний проксі"},
{"hostname too long", "ім'я вузла надто довге"},
{"cannot connect to upstream socks proxy", "не вдається підключитися до висхідного SOCKS проксі"},
{"Cannot negotiate with socks proxy", "Не вдається домовитися з висхідним SOCKS проксі"},
{"Bad outproxy settings", "Некоректні налаштування зовнішнього проксі"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Адрес %s не в I2P мережі, але зовнішній проксі не включений"},
{"Unknown outproxy URL", "Невідомий URL зовнішнього проксі"},
{"Cannot resolve upstream proxy", "Не вдається визначити висхідний проксі"},
{"Hostname is too long", "Ім'я вузла надто довге"},
{"Cannot connect to upstream SOCKS proxy", "Не вдалося підключитися до висхідного SOCKS проксі сервера"},
{"Cannot negotiate with SOCKS proxy", "Не вдається домовитися з висхідним SOCKS проксі"},
{"CONNECT error", "Помилка CONNECT запиту"},
{"Failed to Connect", "Не вдалося підключитися"},
{"socks proxy error", "помилка SOCKS проксі"},
{"failed to send request to upstream", "не вдалося відправити запит висхідному проксі"},
{"No Reply From socks proxy", "Немає відповіді від SOCKS проксі сервера"},
{"cannot connect", "не вдалося підключитися"},
{"http out proxy not implemented", "підтримка зовнішнього HTTP проксі сервера не реалізована"},
{"cannot connect to upstream http proxy", "не вдалося підключитися до висхідного HTTP проксі сервера"},
{"Failed to connect", "Не вдалося підключитися"},
{"SOCKS proxy error", "Помилка SOCKS проксі"},
{"Failed to send request to upstream", "Не вдалося відправити запит висхідному проксі"},
{"No reply from SOCKS proxy", "Немає відповіді від SOCKS проксі сервера"},
{"Cannot connect", "Не вдалося підключитися"},
{"HTTP out proxy not implemented", "Підтримка зовнішнього HTTP проксі сервера не реалізована"},
{"Cannot connect to upstream HTTP proxy", "Не вдалося підключитися до висхідного HTTP проксі сервера"},
{"Host is down", "Вузол недоступний"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."},
{"", ""},
@ -198,10 +206,10 @@ namespace ukrainian // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"день", "дня", "днів"}},
{"hours", {"годину", "години", "годин"}},
{"minutes", {"хвилину", "хвилини", "хвилин"}},
{"seconds", {"секунду", "секунди", "секунд"}},
{"%d days", {"%d день", "%d дня", "%d днів"}},
{"%d hours", {"%d годину", "%d години", "%d годин"}},
{"%d minutes", {"%d хвилину", "%d хвилини", "%d хвилин"}},
{"%d seconds", {"%d секунду", "%d секунди", "%d секунд"}},
{"", {"", "", ""}},
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, The PurpleI2P Project
* Copyright (c) 2021-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,15 +31,16 @@ namespace uzbek // language namespace
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "yaratilmoqda"},
{"failed", "muvaffaqiyatsiz"},
{"expiring", "muddati tugaydi"},
{"established", "aloqa o'rnatildi"},
{"unknown", "noma'lum"},
{"exploratory", "tadqiqiy"},
{"Purple I2P Webconsole", "Veb-konsoli Purple I2P"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> veb-konsoli"},
{"Main page", "Asosiy sahifa"},
{"Router commands", "Router buyruqlari"},
@ -57,18 +58,20 @@ namespace uzbek // language namespace
{"Unknown", "Notanish"},
{"Proxy", "Proksi"},
{"Mesh", "Mesh To'r"},
{"Error", "Xato"},
{"Clock skew", "Aniq vaqt emas"},
{"Offline", "Oflayn"},
{"Symmetric NAT", "Simmetrik NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Deskriptorlar yo'q"},
{"Uptime", "Ish vaqti"},
{"Network status", "Tarmoq holati"},
{"Network status v6", "Tarmoq holati v6"},
{"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"},
{"KiB/s", "KiB/s"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Yuborilgan"},
{"Transit", "Tranzit"},
{"Data path", "Ma'lumotlar joylanishi"},
@ -93,8 +96,9 @@ namespace uzbek // language namespace
{"Address", "Manzil"},
{"Type", "Turi"},
{"EncType", "ShifrlashTuri"},
{"Expire LeaseSet", "LeaseSet muddati tugaydi"},
{"Inbound tunnels", "Kirish tunnellari"},
{"ms", "ms"},
{"%dms", "%dms"},
{"Outbound tunnels", "Chiquvchi tunnellar"},
{"Tags", "Teglar"},
{"Incoming", "Kiruvchi"},
@ -107,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"},
@ -116,9 +121,10 @@ namespace uzbek // language namespace
{"Gateway", "Kirish yo'li"},
{"TunnelID", "TunnelID"},
{"EndDate", "Tugash Sanasi"},
{"not floodfill", "floodfill emas"},
{"floodfill mode is disabled", "floodfill rejimi o'chirilgan"},
{"Queue size", "Navbat hajmi"},
{"Run peer test", "Sinovni boshlang"},
{"Reload tunnels configuration", "Tunnel konfiguratsiyasini qayta yuklash"},
{"Decline transit tunnels", "Tranzit tunnellarini rad etish"},
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"},
@ -146,8 +152,10 @@ namespace uzbek // language namespace
{"Destination not found", "Yo'nalish topilmadi"},
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
{"Return to destination page", "Manzilgoh sahifasiga qaytish"},
{"You will be redirected in 5 seconds", "Siz 5 soniya ichida qayta yo'naltirilasiz"},
{"Transit tunnels count must not exceed 65535", "Tranzit tunnellar soni 65535 dan oshmasligi kerak"},
{"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"},
{"Description", "Tavsif"},
@ -155,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"},
@ -165,32 +172,33 @@ namespace uzbek // language namespace
{"You may try to find this host on jump services below", "Siz xost quyida o'tish xizmatlari orqali topishga harakat qilishingiz mumkin"},
{"Invalid request", "Notogri sorov"},
{"Proxy unable to parse your request", "Proksi sizning so'rovingizni aniqlab ololmayapti"},
{"addresshelper is not supported", "addresshelper qo'llab -quvvatlanmaydi"},
{"Host", "Xost"},
{"added to router's addressbook from helper", "'helper'dan routerning 'addressbook'ga qo'shildi"},
{"Click here to proceed:", "Davom etish uchun shu yerni bosing:"},
{"Continue", "Davom etish"},
{"Addresshelper found", "Addresshelper topildi"},
{"already in router's addressbook", "allaqachon 'addressbook'da yozilgan"},
{"Click here to update record:", "Yozuvni yangilash uchun shu yerni bosing:"},
{"invalid request uri", "noto'g'ri URI so'rovi"},
{"Addresshelper is not supported", "Addresshelper qo'llab-quvvatlanmaydi"},
{"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>.", "%s xosti <font color=red>allaqachon routerning manzillar kitobida</font>. <b>Ehtiyot bo'ling: bu URL manbasi zararli bo'lishi mumkin!</b> Yozuvni yangilash uchun bu yerni bosing: <a href=\"%s%s%s&update=true\">Davom etish</a>."},
{"Addresshelper forced update rejected", "Addresshelperni majburiy yangilash rad etildi"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Routerning manzillar kitobiga <b>%s</b> xostini qo'shish uchun bu yerni bosing: <a href=\"%s%s%s\">Davom etish</a>."},
{"Addresshelper request", "Addresshelper so'rovi"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Yordamchidan router manzillar kitobiga %s xost qoshildi. Davom etish uchun bu yerga bosing: <a href=\"%s\">Davom etish</a>."},
{"Addresshelper adding", "Addresshelperni qo'shish"},
{"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>.", "%s xosti <font color=red>allaqachon routerning manzillar kitobida</font>. Yozuvni yangilash uchun shu yerni bosing: <a href=\"%s%s%s&update=true\">Davom etish</a>."},
{"Addresshelper update", "Addresshelperni yangilash"},
{"Invalid request URI", "Noto'g'ri URI so'rovi"},
{"Can't detect destination host from request", "Sorov orqali manzil xostini aniqlab bo'lmayapti"},
{"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"},
{"bad outproxy settings", "noto'g'ri tashqi proksi-server sozlamalari"},
{"not inside I2P network, but outproxy is not enabled", "I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"},
{"unknown outproxy url", "noma'lum outproxy url"},
{"cannot resolve upstream proxy", "yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"},
{"hostname too long", "xost nomi juda uzun"},
{"cannot connect to upstream socks proxy", "yuqori 'socks proxy'ga ulanib bo'lmayapti"},
{"Cannot negotiate with socks proxy", "'Socks proxy' bilan muzokara olib bo'lmaydi"},
{"Bad outproxy settings", "Noto'g'ri tashqi proksi-server sozlamalari"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Xost %s I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"},
{"Unknown outproxy URL", "Noma'lum outproxy URL"},
{"Cannot resolve upstream proxy", "Yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"},
{"Hostname is too long", "Xost nomi juda uzun"},
{"Cannot connect to upstream SOCKS proxy", "Yuqori 'SOCKS proxy'ga ulanib bo'lmayapti"},
{"Cannot negotiate with SOCKS proxy", "'SOCKS proxy' bilan muzokara olib bo'lmaydi"},
{"CONNECT error", "CONNECT xatosi"},
{"Failed to Connect", "Ulanib bo'lmayapti"},
{"socks proxy error", "'socks proxy' xatosi"},
{"failed to send request to upstream", "yuqori http proksi-serveriga so'rovni uborib bo'lmadi"},
{"No Reply From socks proxy", "'Socks proxy'dan javob yo'q"},
{"cannot connect", "ulanib bo'lmaydi"},
{"http out proxy not implemented", "tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"},
{"cannot connect to upstream http proxy", "yuqori http 'proxy-server'iga ulanib bo'lmayapti"},
{"Failed to connect", "Ulanib bo'lmayapti"},
{"SOCKS proxy error", "'SOCKS proxy' xatosi"},
{"Failed to send request to upstream", "Yuqori proksi-serveriga so'rovni uborib bo'lmadi"},
{"No reply from SOCKS proxy", "'SOCKS proxy'dan javob yo'q"},
{"Cannot connect", "Ulanib bo'lmaydi"},
{"HTTP out proxy not implemented", "Tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"},
{"Cannot connect to upstream HTTP proxy", "Yuqori 'HTTP proxy'ga ulanib bo'lmayapti"},
{"Host is down", "Xost ishlamayapti"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."},
{"", ""},
@ -198,10 +206,10 @@ namespace uzbek // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"kun", "kun"}},
{"hours", {"soat", "soat"}},
{"minutes", {"daqiqa", "daqiqa"}},
{"seconds", {"soniya", "soniya"}},
{"%d days", {"%d kun", "%d kun"}},
{"%d hours", {"%d soat", "%d soat"}},
{"%d minutes", {"%d daqiqa", "%d daqiqa"}},
{"%d seconds", {"%d soniya", "%d soniya"}},
{"", {"", ""}},
};

@ -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)

@ -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

@ -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)
#define bit_AES (1 << 25)
#endif
#ifndef bit_AVX
#define bit_AVX (1 << 28)
#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)) {
#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
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;
}
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"));
}
}
}

@ -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);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -45,7 +45,7 @@ namespace config {
("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)")
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
("host", value<std::string>()->default_value(""), "External IP")
("ifname", value<std::string>()->default_value(""), "Network interface to bind to")
("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4")
("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6")
@ -77,7 +77,8 @@ namespace config {
limits.add_options()
("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.transittunnels", value<uint32_t>()->default_value(10000), "Maximum active transit tunnels (default:10000)")
("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")
@ -95,6 +96,7 @@ namespace config {
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
("http.lang", value<std::string>()->default_value("english"), "WebUI language (default: english )")
("http.showTotalTCSR", value<bool>()->default_value(false), "Show additional value with total TCSR since router's start (default: false)")
;
options_description httpproxy("HTTP Proxy options");
@ -148,7 +150,8 @@ namespace config {
sam.add_options()
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen TCP port")
("sam.portudp", value<uint16_t>()->default_value(0), "SAM listen UDP port")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
;
@ -190,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),
@ -202,7 +205,7 @@ namespace config {
reseed.add_options()
("reseed.verify", value<bool>()->default_value(false), "Verify .su3 signature")
("reseed.threshold", value<uint16_t>()->default_value(25), "Minimum number of known routers before requesting reseed")
("reseed.floodfill", value<std::string>()->default_value(""), "Path to router info of floodfill to reseed from")
("reseed.floodfill", value<std::string>()->default_value(""), "Ignored. Always empty")
("reseed.file", value<std::string>()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from")
("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from")
("reseed.proxy", value<std::string>()->default_value(""), "url for reseed proxy, supports http/socks")
@ -214,10 +217,12 @@ namespace config {
"https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/,"
"https://reseed.i2pgit.org/,"
"https://i2p.novg.net/,"
"https://banana.incognet.io/,"
"https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/"
"https://www2.mk16.de/,"
"https://i2p.ghativega.in/,"
"https://i2p.novg.net/,"
"https://reseed.stormycloud.org/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/,"
@ -284,7 +289,7 @@ namespace config {
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.enabled", value<bool>()->default_value(false), "Enable NTP time sync (default: disabled)")
("nettime.ntpservers", value<std::string>()->default_value(
"0.pool.ntp.org,"
"1.pool.ntp.org,"
@ -304,7 +309,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")
;

@ -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

@ -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 ();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -19,7 +19,7 @@ namespace i2p
namespace datagram
{
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip)
{
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
@ -119,19 +119,79 @@ namespace datagram
void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
if (m_RawReceiver)
m_RawReceiver (fromPort, toPort, buf, len);
auto r = FindRawReceiver(toPort);
if (r)
r (fromPort, toPort, buf, len);
else
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
}
void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
m_ReceiversByPorts[port] = receiver;
if (!m_DefaultReceiver) {
m_DefaultReceiver = receiver;
m_DefaultReceiverPort = port;
}
}
void DatagramDestination::ResetReceiver (uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
m_ReceiversByPorts.erase (port);
if (m_DefaultReceiverPort == port) {
m_DefaultReceiver = nullptr;
m_DefaultReceiverPort = 0;
}
}
void DatagramDestination::SetRawReceiver (const RawReceiver& receiver, uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
m_RawReceiversByPorts[port] = receiver;
if (!m_DefaultRawReceiver) {
m_DefaultRawReceiver = receiver;
m_DefaultRawReceiverPort = port;
}
}
void DatagramDestination::ResetRawReceiver (uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
m_RawReceiversByPorts.erase (port);
if (m_DefaultRawReceiverPort == port) {
m_DefaultRawReceiver = nullptr;
m_DefaultRawReceiverPort = 0;
}
}
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
Receiver r = m_Receiver;
Receiver r = nullptr;
auto itr = m_ReceiversByPorts.find(port);
if (itr != m_ReceiversByPorts.end())
r = itr->second;
else {
r = m_DefaultReceiver;
}
return r;
}
DatagramDestination::RawReceiver DatagramDestination::FindRawReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
RawReceiver r = nullptr;
auto itr = m_RawReceiversByPorts.find(port);
if (itr != m_RawReceiversByPorts.end())
r = itr->second;
else {
r = m_DefaultRawReceiver;
}
return r;
}
@ -425,7 +485,7 @@ namespace datagram
if (m)
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
}
routingPath->outboundTunnel->SendTunnelDataMsg(send);
routingPath->outboundTunnel->SendTunnelDataMsgs(send);
}
m_SendQueue.clear();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -126,14 +126,12 @@ namespace datagram
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
void ResetReceiver () { m_Receiver = nullptr; };
void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; };
void ResetReceiver (uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); };
void SetReceiver (const Receiver& receiver, uint16_t port);
void ResetReceiver (uint16_t port);
void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
void ResetRawReceiver () { m_RawReceiver = nullptr; };
void SetRawReceiver (const RawReceiver& receiver, uint16_t port);
void ResetRawReceiver (uint16_t port);
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
@ -150,20 +148,26 @@ namespace datagram
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
Receiver FindReceiver(uint16_t port);
RawReceiver FindRawReceiver(uint16_t port);
private:
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
Receiver m_Receiver; // default
RawReceiver m_RawReceiver; // default
bool m_Gzip; // gzip compression of data messages
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
Receiver m_DefaultReceiver;
RawReceiver m_DefaultRawReceiver;
uint16_t m_DefaultReceiverPort;
uint16_t m_DefaultRawReceiverPort;
std::mutex m_ReceiversMutex;
std::map<uint16_t, Receiver> m_ReceiversByPorts;
std::mutex m_RawReceiversMutex;
std::unordered_map<uint16_t, Receiver> m_ReceiversByPorts;
std::unordered_map<uint16_t, RawReceiver> m_RawReceiversByPorts;
bool m_Gzip; // gzip compression of data messages
i2p::data::GzipInflator m_Inflator;
std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
std::vector<uint8_t> m_From, m_Signature;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -108,7 +108,7 @@ namespace client
if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
m_AuthType = authType;
else
LogPrint (eLogError, "Destination: Unknown auth type ", authType);
LogPrint (eLogError, "Destination: Unknown auth type: ", authType);
}
}
it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
@ -117,7 +117,7 @@ namespace client
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{
LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", it->second);
m_LeaseSetPrivKey.reset (nullptr);
}
}
@ -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;
}
@ -378,9 +367,12 @@ namespace client
HandleDataMessage (payload, len);
break;
case eI2NPDeliveryStatus:
// we assume tunnel tests non-encrypted
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
break;
case eI2NPTunnelTest:
if (m_Pool)
m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET));
break;
case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (payload, len);
break;
@ -399,6 +391,11 @@ namespace client
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
{
if (len < DATABASE_STORE_HEADER_SIZE)
{
LogPrint (eLogError, "Destination: Database store msg is too short ", len);
return;
}
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
size_t offset = DATABASE_STORE_HEADER_SIZE;
if (replyToken)
@ -406,8 +403,14 @@ namespace client
LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore");
offset += 36;
}
if (offset > len || len > i2p::data::MAX_LS_BUFFER_SIZE + offset)
{
LogPrint (eLogError, "Destination: Database store message is too long ", len);
return;
}
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
std::shared_ptr<LeaseSetRequest> request;
switch (buf[DATABASE_STORE_TYPE_OFFSET])
{
case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
@ -463,31 +466,59 @@ namespace client
case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
{
auto it2 = m_LeaseSetRequests.find (key);
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
{
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
if (ls2->IsValid ())
if (it2 != m_LeaseSetRequests.end ())
{
request = it2->second;
m_LeaseSetRequests.erase (it2);
if (request->requestedBlindedKey)
{
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
leaseSet = ls2;
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
if (ls2->IsValid () && !ls2->IsExpired ())
{
leaseSet = ls2;
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
}
else
LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
}
else
{
// publishing verification doesn't have requestedBlindedKey
auto localLeaseSet = GetLeaseSetMt ();
if (localLeaseSet->GetStoreHash () == key)
{
auto ls = std::make_shared<i2p::data::LeaseSet2> (i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2,
localLeaseSet->GetBuffer (), localLeaseSet->GetBufferLen (), false);
leaseSet = ls;
}
else
LogPrint (eLogWarning, "Destination: Encrypted LeaseSet2 received for request without blinded key");
}
}
else
LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
LogPrint (eLogWarning, "Destination: Couldn't find request for encrypted LeaseSet2");
break;
}
default:
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
}
auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ())
if (!request)
{
auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ())
{
request = it1->second;
m_LeaseSetRequests.erase (it1);
}
}
if (request)
{
it1->second->requestTimeoutTimer.cancel ();
if (it1->second) it1->second->Complete (leaseSet);
m_LeaseSetRequests.erase (it1);
request->requestTimeoutTimer.cancel ();
request->Complete (leaseSet);
}
}
@ -500,38 +531,43 @@ namespace client
if (it != m_LeaseSetRequests.end ())
{
auto request = it->second;
bool found = false;
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
for (int i = 0; i < num; i++)
{
for (int i = 0; i < num; i++)
{
i2p::data::IdentHash peerHash (buf + 33 + i*32);
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
{
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
}
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
if (floodfill)
i2p::data::IdentHash peerHash (buf + 33 + i*32);
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
{
LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
if (SendLeaseSetRequest (key, floodfill, request))
found = true;
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
}
}
if (!found)
{
LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
request->Complete (nullptr);
m_LeaseSetRequests.erase (key);
}
SendNextLeaseSetRequest (key, request);
}
else
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
}
void LeaseSetDestination::SendNextLeaseSetRequest (const i2p::data::IdentHash& key,
std::shared_ptr<LeaseSetRequest> request)
{
bool found = false;
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
{
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
if (floodfill)
{
LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
if (SendLeaseSetRequest (key, floodfill, request))
found = true;
}
}
if (!found)
{
LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
request->Complete (nullptr);
m_LeaseSetRequests.erase (key);
}
}
void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID)
{
if (msgID == m_PublishReplyToken)
@ -576,12 +612,7 @@ namespace client
shared_from_this (), std::placeholders::_1));
return;
}
if (!m_Pool->GetInboundTunnels ().size () || !m_Pool->GetOutboundTunnels ().size ())
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet. Destination is not ready");
return;
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetStoreHash (), m_ExcludedFloodfills);
if (!floodfill)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
@ -592,26 +623,39 @@ namespace client
auto inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!outbound || !inbound)
{
LogPrint (eLogInfo, "Destination: No compatible tunnels with ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another floodfill");
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
if (floodfill)
{
outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
if (outbound)
if (!m_Pool->GetInboundTunnels ().empty () && !m_Pool->GetOutboundTunnels ().empty ())
{
LogPrint (eLogInfo, "Destination: No compatible tunnels with ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another floodfill");
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetStoreHash (), m_ExcludedFloodfills);
if (floodfill)
{
inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!inbound)
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
if (outbound)
{
inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!inbound)
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
}
else
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
}
else
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
}
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
}
else
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
LogPrint (eLogDebug, "Destination: No tunnels in pool");
if (!floodfill || !outbound || !inbound)
{
// we can't publish now
m_ExcludedFloodfills.clear ();
m_PublishReplyToken = 1; // dummy non-zero value
// try again after a while
LogPrint (eLogInfo, "Destination: Can't publish LeasetSet because destination is not ready. Try publishing again after ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds");
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1));
return;
}
}
@ -619,10 +663,19 @@ namespace client
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
auto msg = WrapMessageForRouter (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound));
auto s = shared_from_this ();
msg->onDrop = [s]()
{
s->GetService ().post([s]()
{
s->m_PublishConfirmationTimer.cancel ();
s->HandlePublishConfirmationTimer (boost::system::error_code());
});
};
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg);
m_LastSubmissionTime = ts;
}
@ -635,7 +688,7 @@ namespace client
m_PublishReplyToken = 0;
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds or failed. will try again");
Publish ();
}
else
@ -748,7 +801,7 @@ namespace client
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey)
{
std::set<i2p::data::IdentHash> excluded;
std::unordered_set<i2p::data::IdentHash> excluded;
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
if (floodfill)
{
@ -763,9 +816,17 @@ namespace client
request->requestTime = ts;
if (!SendLeaseSetRequest (dest, floodfill, request))
{
// request failed
m_LeaseSetRequests.erase (ret.first);
if (requestComplete) requestComplete (nullptr);
// try another
LogPrint (eLogWarning, "Destination: Couldn't send LeaseSet request to ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another");
request->excluded.insert (floodfill->GetIdentHash ());
floodfill = i2p::data::netdb.GetClosestFloodfill (dest, request->excluded);
if (!SendLeaseSetRequest (dest, floodfill, request))
{
// request failed
LogPrint (eLogWarning, "Destination: LeaseSet request for ", dest.ToBase32 (), " was not sent");
m_LeaseSetRequests.erase (ret.first);
if (requestComplete) requestComplete (nullptr);
}
}
}
else // duplicate
@ -792,11 +853,11 @@ namespace client
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
{
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true));
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false)); // outbound from floodfill
if (!request->replyTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible inbound tunnels found");
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false));
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true)); // inbound from floodfill
if (!request->outboundTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible outbound tunnels found");
if (request->replyTunnel && request->outboundTunnel)
{
@ -812,9 +873,18 @@ namespace client
AddECIESx25519Key (replyKey, replyTag);
else
AddSessionKey (replyKey, replyTag);
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
request->outboundTunnel->SendTunnelDataMsg (
auto msg = WrapMessageForRouter (nextFloodfill,
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
auto s = shared_from_this ();
msg->onDrop = [s, dest, request]()
{
s->GetService ().post([s, dest, request]()
{
s->SendNextLeaseSetRequest (dest, request);
});
};
request->outboundTunnel->SendTunnelDataMsgs (
{
i2p::tunnel::TunnelMessageBlock
{
@ -909,7 +979,7 @@ namespace client
bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service)
{
@ -979,7 +1049,7 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ())
m_IsStreamingAnswerPings = (it->second == "true");
m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
@ -993,12 +1063,12 @@ namespace client
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
else
LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
LogPrint (eLogError, "Destination: Unexpected auth type: ", authType);
if (m_AuthKeys->size ())
LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
else
{
LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
LogPrint (eLogCritical, "Destination: No auth keys read for auth type: ", authType);
m_AuthKeys = nullptr;
}
}
@ -1007,7 +1077,7 @@ namespace client
}
catch (std::exception & ex)
{
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
LogPrint(eLogCritical, "Destination: Unable to parse parameters for destination: ", ex.what());
}
}
@ -1026,22 +1096,30 @@ 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 ();
//it.second->SetOwner (nullptr);
}
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)
@ -1061,9 +1139,15 @@ namespace client
case PROTOCOL_TYPE_STREAMING:
{
// streaming protocol
auto dest = GetStreamingDestination (toPort);
if (dest)
dest->HandleDataMessagePayload (buf, length);
if (toPort != m_LastPort || !m_LastStreamingDestination)
{
m_LastStreamingDestination = GetStreamingDestination (toPort);
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
LogPrint (eLogError, "Destination: Missing streaming destination");
}
@ -1087,7 +1171,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)
{
@ -1117,7 +1201,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)
{
@ -1136,35 +1220,41 @@ 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;
std::condition_variable streamRequestComplete;
std::mutex streamRequestCompleteMutex;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
CreateStream (
[&streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
[&done, &streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
{
stream = s;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
streamRequestComplete.notify_all ();
done = true;
},
dest, port);
streamRequestComplete.wait (l);
while (!done)
{
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
if (!done)
streamRequestComplete.wait (l);
}
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);
@ -1201,7 +1291,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)
{
@ -1209,8 +1299,9 @@ namespace client
if (it != m_StreamingDestinationsByPorts.end ())
return it->second;
}
// if port is zero or not found, use default destination
return m_StreamingDestination;
else // if port is zero, use default destination
return m_StreamingDestination;
return nullptr;
}
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
@ -1238,7 +1329,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)
@ -1248,7 +1339,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)
{
@ -1309,7 +1400,7 @@ namespace client
f1.write ((char *)keys->priv, 256);
return;
}
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
LogPrint(eLogCritical, "Destinations: Can't save keys to ", path);
}
void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
@ -1386,7 +1477,7 @@ namespace client
if (pubKey.FromBase64 (it.second.substr (pos+1)))
m_AuthKeys->push_back (pubKey);
else
LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1));
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2024, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -14,7 +14,8 @@
#include <mutex>
#include <memory>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <functional>
#include <boost/asio.hpp>
@ -96,7 +97,7 @@ namespace client
struct LeaseSetRequest
{
LeaseSetRequest (boost::asio::io_service& service): requestTime (0), requestTimeoutTimer (service) {};
std::set<i2p::data::IdentHash> excluded;
std::unordered_set<i2p::data::IdentHash> excluded;
uint64_t requestTime;
boost::asio::deadline_timer requestTimeoutTimer;
std::list<RequestComplete> requestComplete;
@ -175,6 +176,7 @@ namespace client
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets ();
@ -184,8 +186,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;
@ -193,7 +195,7 @@ namespace client
bool m_IsPublic;
uint32_t m_PublishReplyToken;
uint64_t m_LastSubmissionTime; // in seconds
std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
std::unordered_set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer;
@ -241,15 +243,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 +287,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:
@ -297,6 +299,7 @@ namespace client
bool m_IsStreamingAnswerPings;
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
std::shared_ptr<i2p::stream::StreamingDestination> m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels
i2p::datagram::DatagramDestination * m_DatagramDestination;
int m_RefCounter; // how many clients(tunnels) use this destination

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

Loading…
Cancel
Save