Compare commits

...

554 Commits

Author SHA1 Message Date
R4SAS
b7e20b9b86 2.41.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-20 16:57:58 +03:00
R4SAS
a5d6972913 [win] update build script license year
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-20 12:54:48 +03:00
R4SAS
e4cb42c599 [win] add binary signing support
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-20 12:53:31 +03:00
orignal
0a34f1f3ad 2.41.0 2022-02-19 17:21:11 -05:00
orignal
7bdeaa9611 don't pick own router for peer test 2022-02-19 08:15:49 -05:00
R4SAS
ab2577ce0a [daemon] print errors to stdout
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-18 21:00:16 +03:00
orignal
34544be423 Merge pull request #1732 from PurpleI2P/patch-1
Set of updates
2022-02-18 10:13:33 -05:00
R4SAS
6bf0fdd344 [webserver] use cancel instead shutdown for acceptor
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-18 09:45:35 +03:00
R4SAS
6a177cdd1c fix incorrect change in year
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-18 09:29:28 +03:00
R4SAS
a51ef0cfc6 set of updates:
* [webconsole] change error handling code to restart acceptor after any
error
* [webconsole] call shutdown vefore stopping acceptor on exit
* update license headers for modified files, change year to file
  creation year, not 2013 (when project started)

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-18 09:20:06 +03:00
orignal
48374d97df always use TCP/IP sockets for I2CP 2022-02-16 15:32:13 -05:00
R4SAS
bf3d7e74f5 [i2cp] use tcp/ip socket on android
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-16 16:27:59 +03:00
R4SAS
ab3f3890e4 [i2cp] use tcp/ip socket on android
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-16 16:13:15 +03:00
R4SAS
dceb0fb8c5 [cmake] add warning about MESHNET option
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-16 11:39:09 +03:00
R4SAS
05c1856389 [cmake] do not use CMAKE_OSX_ARCHITECTURES for check
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-14 23:53:55 +03:00
R4SAS
dc5cba60d1 [cmake] add MAC_OSX define for Mac
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-14 22:58:56 +03:00
orignal
70409dcdcc Merge pull request #1728 from eyedeekay/swig-binding-cleanup
Removes workaround for passing string arguments from Go
2022-02-14 14:32:23 -05:00
orignal
a92c29e04c drop routers older than 6 months on start 2022-02-13 15:42:06 -05:00
idk
c4b4dc79cf Remove janky workaround for argument passing from Go. This should allow other languages to use the binding more easily, and go-i2pd doesn't need the workaround anymore 2022-02-13 13:21:18 -05:00
orignal
510fe43ec4 create and encrypt SessionRequest 2022-02-11 19:21:04 -05:00
R4SAS
73e572b66b disable thread naming for PowerPC (#1726)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 22:17:38 +03:00
R4SAS
a272a2cb7e [cmake] update min version, drop PCH
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 07:23:33 +03:00
R4SAS
43b990afe6 [cmake] disable deprecation warning when OpenSSL 3 is used
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 07:00:30 +03:00
R4SAS
90130b5492 fix exception printing
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 00:38:29 +03:00
R4SAS
f22faaefeb remove duplicate definition
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 00:27:19 +03:00
R4SAS
ac25649425 cast pthread name to char* for apple sdk
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-11 00:05:07 +03:00
orignal
04388325a8 KDF and encryption for SessionRequest 2022-02-10 14:03:09 -05:00
orignal
61ec873842 fixed incorrect ret code 2022-02-10 13:07:29 -05:00
orignal
ea1f2d4e26 use i for intro key for SSU 2022-02-06 10:17:35 -05:00
orignal
4211c733a2 s and i keys for all addresses 2022-02-05 17:14:25 -05:00
orignal
450266818a Noise XK for SSU2 2022-02-05 15:58:39 -05:00
orignal
1e019157bb SSU2 initial commit 2022-02-04 15:01:18 -05:00
orignal
c9a1066f02 send SessionCreated before connection close if slock skew 2022-02-03 14:49:36 -05:00
R4SAS
0062f7d764 [reseed] dont do yggdrasill address check if option disabled
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-03 14:49:24 +03:00
orignal
95e994e171 pass incomplete I2NP message by move 2022-02-02 17:33:33 -05:00
R4SAS
31242401e5 [cmake] update TargetArch.cmake (#1724)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-02 06:07:01 +03:00
orignal
19cc1c3b3f adjust clock from SSU SessionCreated is time difference exceeds 15 seconds 2022-02-01 18:43:11 -05:00
R4SAS
03bcdceb9b [gha] add ucrt windows build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-01 15:42:57 +03:00
R4SAS
33ca836ad0 [gha] add ucrt windows build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-01 15:36:35 +03:00
R4SAS
53f19e4050 Use builtin bitswap for endian on windows
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-29 22:09:27 +03:00
R4SAS
54b7d46f5a reseeds update
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-28 18:39:21 +03:00
orignal
40e6d675c5 I2NP messages pool for I2CP 2022-01-25 13:02:27 -05:00
orignal
73b77c83b8 select compatible outbound tunnel 2022-01-24 13:25:47 -05:00
R4SAS
632d41e50c [rpm] try to fix fedora copr build [3]
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-24 03:20:43 +03:00
R4SAS
17acadbfb9 [rpm] try to fix fedora copr build [2]
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-24 03:14:50 +03:00
R4SAS
2ab5924ec9 [rpm] try to fix fedora copr build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-24 02:56:41 +03:00
R4SAS
ac09a4cf0f [i18n] update german translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-23 03:18:11 +03:00
orignal
c10ee59de3 cleanup memrory pools if no more streams 2022-01-21 21:34:50 -05:00
orignal
afad405ed9 check for duplicate destination 2022-01-19 12:08:56 -05:00
R4SAS
5a35de8dc9 [i18n] update uzbek translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-19 00:38:33 +03:00
orignal
58cf26c304 cleanup properties before update 2022-01-15 19:26:11 -05:00
orignal
a2de5564ac moved m_Properties to LocalRouterInfo 2022-01-15 18:54:02 -05:00
orignal
338b17ccf1 LocalRouterInfo for own router 2022-01-15 12:48:49 -05:00
orignal
843a968959 integer uptime 2022-01-09 19:07:10 -05:00
R4SAS
dc45c13eef [i18n] added german translation (thanks to mark22k@crowdin)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-09 23:42:13 +03:00
R4SAS
0d6e801595 [webconsole] change dark style colors
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-01-09 20:54:18 +03:00
orignal
2cd50ebaee fixed race condition 2022-01-07 13:39:12 -05:00
orignal
cb6f6a6596 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2022-01-03 16:28:17 -05:00
orignal
e4ab0acc92 create RouterInfo from shared pointer to Buffer 2022-01-03 16:27:28 -05:00
R4SAS
10237c41d3 Merge pull request #1717 from rex4539/typos
Fix typo
2022-01-03 20:23:09 +03:00
Dimitris Apostolou
ac2c6c6010 Fix typo 2022-01-02 12:14:12 +02:00
orignal
c6b2ce93c4 Memory pool for RouterInfo address 2022-01-01 15:12:59 -05:00
orignal
401b7fe883 send error message in quotes 2021-12-31 08:48:21 -05:00
orignal
f567417bb3 memory pool for RouterInfo buffer 2021-12-30 15:16:13 -05:00
orignal
ae5cb3bbe7 rollback 2021-12-28 08:00:03 -05:00
orignal
0eb8e15796 allocated actual buffer size for RouterInfo 2021-12-27 13:02:06 -05:00
orignal
1c95c7856f avoid duplicated addresses. Check presence of netId and version 2021-12-24 18:58:20 -05:00
orignal
daf7551e59 try another fllodfill if no compatible tunnels 2021-12-18 17:55:26 -05:00
orignal
5b63d3692e HidUser0's yggdrasil reseed added 2021-12-13 13:47:59 -05:00
R4SAS
5f9972af78 [addressbook] fix loading subscriptions from config
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-12-07 23:00:52 +03:00
R4SAS
1be4cce074 [addressbook] fix loading subscriptions from config
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-12-07 22:59:11 +03:00
orignal
935e93eb36 minimal send ack interval 2021-12-05 17:54:34 -05:00
orignal
5d924cd35a don't copy received datagram 2021-12-04 19:32:18 -05:00
R4SAS
27116b9f30 2.40.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-28 04:26:44 +03:00
R4SAS
8ac2ee49a8 [gha] fix build without pushing tag for pre-release debian packages
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-28 04:00:03 +03:00
R4SAS
8a8e328fcf [build] include contrib/webconsole to windows packages
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-28 03:50:05 +03:00
R4SAS
c4207e7672 [webconsole] update css
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-28 03:49:08 +03:00
R4SAS
73642703bd 2.40.0
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-28 03:46:53 +03:00
orignal
b3bd175e64 2.40.0 2021-11-27 18:01:13 -05:00
R4SAS
742032907a [gha] update freebsd action
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-27 23:46:03 +03:00
R4SAS
edc0162163 clean line trailing spaces and tabs
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-27 23:30:35 +03:00
R4SAS
94661f697b [log] update log messages (closes #1693)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-27 22:53:53 +03:00
R4SAS
4ecf36fab6 update bandwidth option description (closes #1704)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-27 21:08:05 +03:00
R4SAS
96cdb3bca3 reseeds update
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-21 20:20:23 +03:00
orignal
6c57ba36f7 lazy initialization or tunnel gateway's random buffer 2021-11-20 18:31:18 -05:00
orignal
cb61897236 Merge pull request #1708 from acetoneRu/openssl
--help small correction
2021-11-20 08:39:43 -05:00
acetone
8b931dd40b Transit traffic bandwidth limit 2021-11-20 08:37:36 -05:00
acetone
6b81478bd2 Merge branch 'PurpleI2P:openssl' into openssl 2021-11-20 05:47:32 -05:00
acetone
9d94eb83c1 --help
Traffic bandwidth -> Transit traffic bandwidth
2021-11-20 05:46:44 -05:00
R4SAS
13374f8b7b [gha] publish windows artifacts separately (#1707) 2021-11-18 16:17:28 +03:00
R4SAS
7bf7aae3d1 [i18n] fix type in translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-18 15:23:09 +03:00
R4SAS
e5f39d0caf [i18n] add armenian translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-18 15:15:34 +03:00
R4SAS
174983548d Merge pull request #1705 from rex4539/typos
Fix typos
2021-11-14 20:37:33 +03:00
orignal
a9ec4d916b Merge pull request #1706 from acetoneRu/openssl
Transit traffic bandwidth configuration
2021-11-14 08:21:16 -05:00
acetone
a55c346af5 Bandwidth configuration
Changed to 'Transit traffic bandwidth configuration'
2021-11-14 08:17:53 -05:00
acetone
8e0d8c96bb Merge branch 'PurpleI2P:openssl' into openssl 2021-11-14 08:16:36 -05:00
orignal
9abd383014 eliminate extra pointers for tunnel hops 2021-11-13 15:11:59 -05:00
Dimitris Apostolou
8ee9c437e1 Fix typos 2021-11-13 19:07:50 +02:00
orignal
4052b1ea6d pick compatible outbound tunnel for datagrams 2021-11-08 18:23:26 -05:00
R4SAS
fdde197c58 [webconsole] update stylesheet
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-08 07:40:39 +03:00
R4SAS
49883dc3ac [webconsole] update stylesheet (closes #1699)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-08 07:02:11 +03:00
orignal
d798faa1ca pick compatible ooutbound tunnel 2021-11-07 17:18:31 -05:00
orignal
3f63f15b16 copy compatible transports to new tunnel 2021-11-06 19:16:45 -04:00
orignal
f8c390cdd3 pick compatible tunnels 2021-11-06 15:44:56 -04:00
orignal
8f0978cfd6 all transports by default 2021-11-06 10:49:18 -04:00
orignal
1a8a32a773 select next tunnel with compatible transports 2021-11-05 14:51:24 -04:00
orignal
c0400bfd07 virtual destructor for TunnelConfig 2021-10-31 22:14:59 -04:00
R4SAS
c6e4758187 Revert "Merge pull request #1703 from simonvetter/simon/memory-and-multithreading-fixes"
This reverts commit 67863cfcf9, reversing
changes made to 4c5ec68ff1.

That change completly bloking transports thread on windows.

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-01 05:03:34 +03:00
orignal
56ec8fe95b eliminate local destination mutex 2021-10-31 21:20:16 -04:00
orignal
67863cfcf9 Merge pull request #1703 from simonvetter/simon/memory-and-multithreading-fixes
memory leak and concurrency fixes
2021-10-31 21:08:11 -04:00
R4SAS
4c5ec68ff1 [win] add menu item for opening datadir
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-11-01 02:47:53 +03:00
Simon Vetter
58b7b7d731 libi2pd: add missing locks to i2p::tunnel::TunnelPool 2021-10-31 23:26:52 +01:00
Simon Vetter
1de1c79d4f libi2pd: add missing locks to i2p::tunnel::Tunnels
m_InboundTunnelsMutex, m_OutboundTunnelsMutex and m_PoolsMutex
have been changed to recursive_mutexes since they can be
acquired multiple times by the same thread.
2021-10-31 23:14:28 +01:00
Simon Vetter
7073a6bf38 libi2pd: make Tunnel and TunnelConfig destructors virtual 2021-10-31 14:02:25 +01:00
orignal
26db88d89b check if sip key is available 2021-10-27 22:33:37 -04:00
orignal
876e98d91e check if sip key is available 2021-10-27 22:23:32 -04:00
orignal
8566f6c127 don't store EVP_PKEY sip keys 2021-10-27 21:18:21 -04:00
orignal
bb8dc67942 don't use openssl's SipHash from 3.0.0 due regression 2021-10-27 19:05:16 -04:00
orignal
9965d72990 don't store EVP_PKEY with EdDSA signer and verifier 2021-10-26 21:36:34 -04:00
orignal
921ec9ec12 fix build with openssl 3.0.0 2021-10-23 18:10:02 -04:00
orignal
f1990bc2ab use tunnel endpoint memroy pool to split to tunnel messages at gateway 2021-10-22 21:08:20 -04:00
orignal
cdc8e463b7 use memory pool for outgoing tunnel gateway messages 2021-10-22 19:18:45 -04:00
R4SAS
0a62a962d7 [debian] update upnp patch
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-10-22 05:57:04 +03:00
R4SAS
b0f043ec86 [make] USE_GIT_VERSION option to use commit info in version (closes #1702)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-10-22 05:35:01 +03:00
orignal
ae0cf2e831 use memory pool for tunnel messages 2021-10-20 21:05:22 -04:00
orignal
4ce7e192d6 Merge pull request #1701 from simonvetter/openssl
fix a few undefined behaviour/out of bounds issues
2021-10-19 18:25:06 -04:00
R4SAS
04ca916aac Merge pull request #1700 from xanoni/set-default-make-target
Makefile: set default target ("all")
2021-10-19 23:56:41 +03:00
Simon Vetter
a348e10620 libi2pd: fix undefined behaviour and memory overruns
This fixes the following issues (flagged by cppcheck):
[libi2pd/ECIESX25519AEADRatchetSession.cpp:537]: (error) Buffer is accessed out of bounds: m_NSREncodedKey
[libi2pd/Identity.cpp:22]: (error) Buffer is accessed out of bounds: keys.publicKey
[libi2pd/Identity.cpp:22]: (error) Buffer is accessed out of bounds: publicKey
[libi2pd/NetDb.cpp:70] -> [libi2pd/NetDb.cpp:69]: (error) Iterator 'it' used after element has been erased
[libi2pd/SSUData.cpp:186] -> [libi2pd/SSUData.cpp:187]: (warning) Shifting 32-bit value by 63 bits is undefined behaviour.
2021-10-19 22:27:12 +02:00
Simon Vetter
af794f901f libi2pd: minor logging fixes 2021-10-19 22:27:06 +02:00
R4SAS
8a58572b34 [webconsole] upload example dark style
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-10-19 18:24:49 +03:00
R4SAS
0c25e8f1eb [build] changes in windows build script
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-10-19 18:24:18 +03:00
xanoni
ff3d2db85e Darwin: allow calling make install more than once
This commit ensures that `gzip` does not overwrite any of the repo
files, because that prevents `make install` from executing more than
once.
2021-10-18 22:33:32 -04:00
xanoni
efd84a2404 Makefile: set default target ("all")
Fixes compilation on Darwin, see:
https://github.com/PurpleI2P/i2pd/pull/1698#issuecomment-946304938
2021-10-18 22:11:27 -04:00
orignal
278fd2d8d5 create tunnel I2NP message for tunnel data 2021-10-18 19:03:08 -04:00
orignal
197882a4c9 create I2NP depending on type in I2NP block 2021-10-17 15:30:24 -04:00
orignal
d310efcb5c pass I2NPMessage by move 2021-10-17 11:31:37 -04:00
orignal
1af9117b80 don't create new tunnel message for encryption/decryption 2021-10-15 14:01:41 -04:00
orignal
44e01b41f8 reserve address for 3 introducers 2021-10-12 13:28:16 -04:00
orignal
7def2fa6a3 use std::vector for address list 2021-10-10 09:53:21 -04:00
orignal
48131f4597 don't store full path with RouterInfo 2021-10-07 15:08:33 -04:00
orignal
49e8cf89d8 don't send short tunnel build messages for ElGamal only destinations 2021-10-06 12:42:32 -04:00
orignal
e6bcd04a36 short build message for re-created tunnels and far end transports 2021-10-05 19:38:33 -04:00
orignal
af133f4968 fixed crash if incorrect blinded signature type 2021-09-29 12:38:38 -04:00
R4SAS
d723faaaa3 [UDPTunnel] restart local listener on error
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-28 14:27:35 +03:00
orignal
cc75efcbca fixed build for C++11 2021-09-27 18:25:15 -04:00
orignal
2eded7cdd7 send ping every keealive interval for client tunnels 2021-09-26 16:25:12 -04:00
orignal
b10e5ce358 send ping 2021-09-26 11:20:20 -04:00
orignal
1bb1d89fab change back to map and unodered_map 2021-09-25 18:30:17 -04:00
orignal
b9dd4aee8d use flat_map for incompete messages 2021-09-24 19:12:12 -04:00
orignal
518e53a61c use flat_map for smaller tables 2021-09-24 14:23:39 -04:00
orignal
18b6ba80f2 cleanup RelayRequests 2021-09-22 19:09:56 -04:00
orignal
8debdc264c use common cleanup timer for all SSU sessions 2021-09-21 22:13:34 -04:00
orignal
31bdce1f1f cleanup received messages list by timestamp 2021-09-21 19:01:22 -04:00
orignal
317d8cdc48 don't allocate separate buffers for SessionRequest and SessionCreated 2021-09-18 15:44:43 -04:00
orignal
5b2b9e00a2 reuse receive buffer 2021-09-17 21:52:39 -04:00
R4SAS
3dd9e81296 [addressbook] check domain ending when processing subscriptions
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-17 02:53:30 +03:00
R4SAS
d2faec70be [gzip] do not initialize deflator if gzip is not enabled for tunnel
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-14 14:48:21 +03:00
R4SAS
e5c773a3eb [webconsole] move resources to separate header file
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-13 23:16:18 +03:00
R4SAS
ec86c4611d disable reload checks for UDP tunnels (TODO)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-13 23:16:18 +03:00
orignal
247b6a0ed2 memory pool for SSU packets 2021-09-13 13:13:27 -04:00
orignal
f7f36568ef set gzip compression to false by default 2021-09-12 14:29:43 -04:00
orignal
e054c6e82c memory pool for SSU messages and fragments 2021-09-11 18:58:27 -04:00
orignal
5e2e1a1e3d don't include old tunnel to LeaseSet if recreated 2021-09-10 19:57:38 -04:00
orignal
ad036de69d eliminate allocation of m_ExtendedBuffer 2021-09-09 21:19:52 -04:00
orignal
20652f7995 resseed if too few floodfills 2021-09-09 15:12:53 -04:00
R4SAS
2f88a75325 Merge pull request #1688 from yangfl/openssl
disable pthread_setname_np on GNU/Hurd
2021-09-05 21:00:19 +00:00
orignal
292fe94352 RouterContext is always ECIES 2021-09-05 11:16:41 -04:00
orignal
76dca1b46b don't handle ElGamal build record 2021-09-05 09:10:13 -04:00
orignal
a54b5c18c6 fixed crash 2021-09-05 09:08:29 -04:00
orignal
c763472914 select ECIES routers only for peer tests and introducers 2021-09-05 08:41:32 -04:00
orignal
3a77e7ba2d remove dependancy from localization 2021-09-04 18:55:51 -04:00
orignal
41d6c117ee make sure server tunnel is published 2021-09-04 18:45:32 -04:00
orignal
e8f4c42bfb moved current language from RouterContext to ClientContext 2021-09-04 14:01:57 -04:00
orignal
bce8469e59 eliminate extra error message 2021-09-04 08:53:39 -04:00
yangfl
3f46ca41ca disable pthread_setname_np on GNU/Hurd
which does not exist on GNU/Hurd
2021-09-04 15:07:09 +08:00
R4SAS
6b1ef6e1b9 tunnels reload changes: fix tcp tunnels reload
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-09-04 04:02:27 +03:00
orignal
349022ae42 don't select ElGamal routers for tunnels 2021-09-03 13:30:01 -04:00
orignal
bb518d3d51 don't pass BN_CTX to encrypt/decrypt functions 2021-08-31 18:51:40 -04:00
orignal
c45e202fab removed ElGamal encryption support for own router 2021-08-29 14:22:01 -04:00
orignal
541464b705 don't delete floodfill if number of remaining floodfills is less than minimal 2021-08-26 15:13:58 -04:00
R4SAS
c762acd780 Merge pull request #1687 from dbermond/fix-test-blinding
[tests] fix compilation of test-blinding
2021-08-24 10:24:31 +00:00
R4SAS
ec98ff297c Make blinding test runnable 2021-08-24 13:23:10 +03:00
R4SAS
af2c6c5575 [rpm] change if statement to cover fedora 35
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-24 03:16:28 +03:00
Daniel Bermond
7d220fb2eb [tests] fix compilation of test-blinding
test-blinding currently fails to build with the following error:

In file included from ../libi2pd/Timestamp.cpp:19:
../libi2pd/RouterContext.h:21:10: fatal error:
I18N_langs.h: No such file or directory
   21 | #include "I18N_langs.h"
      |          ^~~~~~~~~~~~~~
compilation terminated.
2021-08-23 17:22:28 -03:00
R4SAS
f0c49b58fb suppress inconsistent-missing-override warning message
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-23 19:29:55 +03:00
R4SAS
24eeadea76 [rpm] add changelog note
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-23 17:03:26 +03:00
R4SAS
455c71ff25 fix warning about ifr_name size
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-23 17:00:57 +03:00
orignal
96850da31e 2.39.0 2021-08-23 06:58:36 -04:00
R4SAS
6ba992dabd [rpm] try fix build on fedora rawhide [try 3]
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-22 23:41:36 +03:00
R4SAS
2bdfcedd0e [docs] add comma to description
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-22 23:38:04 +03:00
R4SAS
c93ab8f829 update changelog, i2pd.conf
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-22 23:36:08 +03:00
orignal
8abd08bd1b change log for 2.39.0 2021-08-22 15:58:46 -04:00
R4SAS
33355c0abe [rpm] try fix build on fedora rawhide
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-22 22:44:04 +03:00
R4SAS
b830babcf4 [rpm] try fix build on fedora rawhide
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-22 22:32:03 +03:00
R4SAS
97765ef895 [i18n] add namespace
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-18 23:04:52 +03:00
R4SAS
8943d212ee [i18n] add Uzbek translation (partial)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-18 22:55:14 +03:00
R4SAS
86e118f2b7 [i18n] change string in HTTPProxy
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-18 22:23:39 +03:00
R4SAS
8c3823fc92 [gha] build docker containers for arm/arm64
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-15 16:53:10 +03:00
orignal
b0874410f1 take first avalable resolved address if local address is not specified 2021-08-13 13:54:23 -04:00
orignal
797f5eb714 select compatible resolved address for server tunnel 2021-08-13 13:31:04 -04:00
orignal
fc29911ffd rollback 2021-08-13 11:36:04 -04:00
R4SAS
1e17ef2f21 [webconsole] show v4 status only ipv4 is enabled
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-13 09:17:27 +03:00
R4SAS
b3e7b1b5ac Squashed commit of the following:
commit 40ec4e8b59e91efe2ef7654c8c0938facfddef1b
Author: Simon Vetter <simon.vetter@runbox.com>
Date:   Fri Jul 30 21:23:27 2021 +0200

    libi2pd: mark additional ipv6 addresses/nets as reserved

    This adds :: (undefined address), ::1 (loopback address) as well as
    ff00::/8 (multicast prefix) to reservedIPv6Ranges.

    A bunch of nodes seem to be publishing bogus addresses (mostly ::1)
    in the netDB, resulting in unnecessary tunnel build failures.

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-13 09:11:56 +03:00
orignal
38a2d45a3c close all existing streams when command SAM socket got closed 2021-08-11 12:31:46 -04:00
orignal
49b3ac7f77 don't reschedule resend timer for terminated streams 2021-08-11 12:23:43 -04:00
orignal
d124d4cace allow ipv6 adresses for UDP server tunnels 2021-08-10 11:36:12 -04:00
R4SAS
ba369d9b30 [webconsole] fix style in css
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-07 17:31:26 +03:00
R4SAS
bef8587d8f [makefile] create object dirs on windres (race condition)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-07 01:38:35 +03:00
R4SAS
fcbc16f2fd [webconsole] fix style issues, clean external style in file was not found on reload
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-07 01:37:45 +03:00
r4sas
a3b172bbcb [makefile] change back directories creation, create them before compiling object files 2021-08-06 21:19:05 +00:00
R4SAS
2f945a4fce [makefile] dont build .so and .dll on default target
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-06 21:19:05 +00:00
R4SAS
dc9e5dc2f1 [makefile] suffix, not prefix
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-06 21:19:05 +00:00
R4SAS
9396827379 [makefile] build libraries on default target
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-06 21:19:05 +00:00
R4SAS
28a055bd78 [webconsole] add external CSS support (#1682)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-06 20:42:08 +03:00
orignal
37f1a55147 encryption type 0,4 by default for server tunnel 2021-08-06 12:32:21 -04:00
orignal
64ec7dd559 narrow down random range 2021-08-03 19:26:09 -04:00
orignal
367df4d0db RAND_bytes from random router selection 2021-08-03 15:43:58 -04:00
orignal
da7e41c188 use Tag<64> for ratechet tags 2021-08-01 18:42:13 -04:00
R4SAS
d88fe203e1 [tunnels] count outbound traffic for zero-hop tunnels
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-08-01 09:25:02 +03:00
orignal
1e01c30e63 set pool for zero-hops tunnels 2021-07-30 14:12:50 -04:00
TomasGl
b16b753ed2 Change default irc server to IRC ILITA (#1677) 2021-07-30 17:49:19 +03:00
orignal
7a55d1fc38 don't insert garlic tag for short tunnel build reply if the same router 2021-07-28 21:14:03 -04:00
orignal
f8623b6121 consistent path for explicit peers 2021-07-28 19:08:55 -04:00
orignal
9a3c22f47d don't encrypt ShortTunnelBuild and ShortTunnelBuildReply if on the same router 2021-07-28 15:06:24 -04:00
orignal
e68cff8bba try routers before random router 2021-07-27 18:35:30 -04:00
orignal
513493fa78 fixed typo 2021-07-26 18:46:29 -04:00
orignal
a6937c792f more precise router selection 2021-07-26 17:51:32 -04:00
orignal
99c7d5c23a don't create enryptor for ECIES record encryption 2021-07-25 22:30:54 -04:00
orignal
cd8e8970de NTP request through compatible address 2021-07-24 16:01:11 -04:00
orignal
26d5ced2ef optimal padding for one-time messages 2021-07-23 20:28:55 -04:00
orignal
c7234f705a let NTCP sync through ipv6 2021-07-23 18:34:51 -04:00
orignal
c153471c49 use short tunnel build if possible 2021-07-22 20:58:35 -04:00
R4SAS
28369faa00 [debian] fix tabulation in patch 2021-07-22 13:35:58 +00:00
R4SAS
445c5f47ae [debian] update patch for upnp 2021-07-22 13:24:42 +00:00
R4SAS
7078ca53c3 [debian] update patch for upnp 2021-07-22 13:23:05 +00:00
orignal
d6ce5f9fa1 Merge pull request #1669 from eyedeekay/c-wrapper-libi2pd-api
C wrapper for part of the libi2pd api
2021-07-22 08:54:59 -04:00
orignal
f28024cfe8 decline transit tunnels from short tunnel build message 2021-07-21 18:12:37 -04:00
orignal
911ab9813e handle encrypteed I2NPShortTunnelBuildReply in destination 2021-07-21 14:55:38 -04:00
orignal
cfbf5862f9 set pool for tunnel before build 2021-07-21 13:08:12 -04:00
orignal
5cb1f5986d use msgID from ECIESx25519 block 2021-07-20 22:00:06 -04:00
orignal
0b14c810fb handle ShortTunnelBuildReply 2021-07-20 19:38:36 -04:00
orignal
c2334db8f8 correct reply key for short tunnel build record 2021-07-20 18:02:48 -04:00
orignal
4807092df6 fixed typo 2021-07-20 15:17:58 -04:00
orignal
bdc1107c96 correct message type for ShortTunnelBuild 2021-07-20 14:35:02 -04:00
orignal
db9223b0d5 set minimal version for floodfill to 0.9.38 2021-07-19 17:50:55 -04:00
orignal
6ecfe0789f don't allocate payload buffer for every single ECIESx25519 message 2021-07-18 18:45:08 -04:00
orignal
a37cf058cd router with expired introducer is still valid 2021-07-16 20:12:41 -04:00
orignal
f4902e6642 eligble floodfill must be reachable by ipv4 2021-07-16 13:53:12 -04:00
orignal
5d022c25ba don't send datetime for one time key message 2021-07-16 09:44:22 -04:00
orignal
0cd9f1b002 precalculate padding sizes 2021-07-15 19:01:43 -04:00
orignal
cd0751d3f1 padding block for message for router 2021-07-15 18:30:32 -04:00
orignal
a1d1a5df74 datetime block for message for router 2021-07-15 18:18:55 -04:00
orignal
197f13f9c0 rollback 2021-07-15 14:02:20 -04:00
orignal
41bfc7899d keep own RouterInfo in netdb 2021-07-14 14:46:56 -04:00
orignal
2c129b6d39 create and handle short tunnel build reply 2021-07-12 19:40:40 -04:00
orignal
dbe427d5eb set reply code for short tunnel build messages 2021-07-11 19:29:16 -04:00
R4SAS
3e281d4790 Update README.md 2021-07-11 23:10:53 +03:00
orignal
15c3d46492 encrypt inbound tunnel build message for short tunnel build only 2021-07-10 17:28:18 -04:00
orignal
6a467a09bd fixed build error 2021-07-10 16:47:28 -04:00
orignal
ba1b8c7c2b WrapECIESX25519MessageForRouter wihout session 2021-07-10 16:15:15 -04:00
orignal
1e9eb30aa3 garlic encryption of inbound tunnel build message 2021-07-10 14:33:23 -04:00
orignal
d47bf1bada different tunnel build record size 2021-07-09 19:26:14 -04:00
orignal
59dd60f5cb genarate keys in CreateBuildRequestRecord 2021-07-09 19:24:28 -04:00
orignal
c02a0c4da9 process DELAY_REQUESTED option 2021-07-08 22:22:00 -04:00
orignal
84f6024cc9 locate record to build inside CreateBuildRequestRecord 2021-07-08 19:00:25 -04:00
orignal
d73b42b726 extract ret code per hop 2021-07-08 16:39:38 -04:00
orignal
ed0c2e68a5 DecryptRecord per tunnel hop 2021-07-07 21:16:30 -04:00
orignal
847225c6bf more yggdrasil reseeds added 2021-07-07 08:24:01 -04:00
orignal
a6294df9e8 decrypt one-time message encrypted with tag on router 2021-07-06 20:15:55 -04:00
orignal
431265a86a update orignal's certificate 2021-07-06 18:22:08 -04:00
orignal
4255c4901d orignal's reseed ceritifcate 2021-07-06 17:44:39 -04:00
orignal
9000b3df4e KDF for short tunnel build messages 2021-07-05 14:31:07 -04:00
orignal
a717542733 update yggdrasil reseed to 0.4 2021-07-04 07:33:28 -04:00
orignal
aace644815 added ShortECIESTunnelHopConfig 2021-07-02 22:06:24 -04:00
orignal
0ae170531e different ElGamal and ECIES hops configs 2021-07-02 15:41:33 -04:00
idk
5d01ee9581 Also add the languages to the linker flags in the api.go file 2021-07-02 13:20:28 -04:00
orignal
8b35ce3320 separate decryption between own record and other records 2021-07-02 13:20:24 -04:00
r4sas
ff0e23d2c4 [cmake] use GNUInstallDirs for libraries destination path (#1672)
Signed-off-by: r4sas <r4sas@i2pmail.org>
2021-07-02 16:43:41 +00:00
idk
d62d2ed269 resolve merge conflicts 2021-07-02 11:02:31 -04:00
idk
abee29719d fix go linking 2021-07-02 10:47:55 -04:00
orignal
5781335814 save and check last stream 2021-06-29 19:08:11 -04:00
R4SAS
f036b8df2d [i18n] update translatable strings (remove douplicates)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-28 12:45:28 +03:00
orignal
25f63ac22a create different I2NP tunnel messages for endpoint and non-endpoint 2021-06-27 15:49:57 -04:00
R4SAS
12d6f03dc9 [i18n] add language changing at runtime in webconsole
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-27 17:14:45 +03:00
R4SAS
6d2c9e367b remove unused CI and docker files
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-27 12:24:41 +03:00
orignal
66422d6d83 double size tunnel message 2021-06-26 21:44:51 -04:00
orignal
b9476791f4 eliminated extra I2NP messages for fragments 2021-06-26 17:40:25 -04:00
R4SAS
9fb8e8a582 [cmake] build translations as library
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-26 23:59:34 +03:00
R4SAS
377a50fa13 [make] build translations as library
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-26 23:45:55 +03:00
R4SAS
da20cae25c [webconsole] urldecode domain for registration string generator
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-26 18:59:48 +03:00
orignal
d0c5732e16 eliminate extra lookups for sequential fragments 2021-06-26 07:18:42 -04:00
idk
f9d9aa0306 move wrapper code to own directory 2021-06-24 09:35:42 -04:00
idk
f5db34b98b C_InitI2P is compatible with more things if it passes argv by reference, it would appear. So to pass arguments to InitI2P you need to turn them back into char* argv[] by tokenizing them and copying them into an array which you then pass to InitI2P from C_InitI2P. The Streaming and Destination Creation parts need to have wrappers for over Identity.h, Streaming.h to be useful so remove them. 2021-06-23 11:18:53 -04:00
orignal
3c07665479 use unordered_map for incomplete messages 2021-06-22 15:35:44 -04:00
orignal
f7f50d049b reduce short tunnel build record length 2021-06-22 13:11:02 -04:00
R4SAS
7d51b4c6ed [i18n] pull ukrainian translation from crowdin (closes #1666)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-21 21:16:46 +03:00
orignal
35ba16ff3b fixed #1665. cast to int64_t 2021-06-20 17:20:29 -04:00
R4SAS
6971b1e9da fix typo in config option description
Kudos @iBicha
https://github.com/PurpleI2P/i2pd/pull/1662#pullrequestreview-687850246

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-20 20:03:33 +03:00
R4SAS
84d987810f add afrikaans in config example 2021-06-20 09:36:14 +03:00
orignal
fed04c1a19 requsted router to send to if not in netdb 2021-06-19 14:44:33 -04:00
orignal
f5e7d87f5b don't disable floodfill if still reachable by ipv6 2021-06-19 14:25:50 -04:00
orignal
6ca28adcbb set address caps and available transports for new address 2021-06-18 18:19:05 -04:00
R4SAS
8e5d2e1b73 [readme] add gha container build badge 2021-06-18 17:26:18 +03:00
R4SAS
e8ad7b4f79 rework of storing certificates path (#1642)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-18 10:04:48 +03:00
R4SAS
d3a49e513c remove repeatable type definition, add include (#1642)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-18 06:45:12 +03:00
R4SAS
5bfab0a796 add certsdir option (#1642)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-18 06:38:10 +03:00
idk
739d1aa9e9 Merge branch 'c-wrapper-libi2pd-api' of github.com:eyedeekay/i2pd into c-wrapper-libi2pd-api 2021-06-17 23:32:47 -04:00
idk
e575c6e94d Merge branch 'PurpleI2P:openssl' into c-wrapper-libi2pd-api 2021-06-17 20:20:26 -07:00
idk
7bc2e74683 Get it to build from go build 2021-06-17 23:12:22 -04:00
orignal
2185019b59 check if router is reachable by transport before obtaining address 2021-06-17 19:46:05 -04:00
orignal
5d097651c1 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2021-06-17 19:11:28 -04:00
orignal
81c83f0d54 pick ECIES routers only for non-x64 2021-06-17 19:10:57 -04:00
idk
5013ce5649 Try and figure out why the C Compiler thinks it needs to find iostream when the C++ library has already been compiled. Make the makefile aware of variables in the environment 2021-06-17 18:25:55 -04:00
R4SAS
5e11a03f0a [docker] fallback to alpine 3.13
https://wiki.alpinelinux.org/wiki/Draft_Release_Notes_for_Alpine_3.14.0#faccessat2
2021-06-17 22:41:37 +03:00
R4SAS
e14d358420 [docker] add debug commands
Adding `g++ -dumpmachine` command on build stage to figure out why docker hub is unable to build container.
2021-06-17 22:11:46 +03:00
R4SAS
82bb3a9b25 [i18n] remove comment line in afrikaans
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-17 21:49:39 +03:00
R4SAS
669720d8f5 [gha] build and publish release containers 2021-06-17 21:37:48 +03:00
idk
45ef6cba9d Un-mangle Destination in case we need to somehow pass one to DestroyLocalDestination,RequestLeaseSet, etc 2021-06-17 13:46:57 -04:00
idk
3330d2bb0c Also Extern Identity, Destination, Streaming headers 2021-06-17 13:24:19 -04:00
R4SAS
a97d2bbb63 [gha] publish containers to docker hub 2021-06-17 20:07:10 +03:00
R4SAS
f56f75bb3f [gha] add docker building (#1664) 2021-06-17 19:37:47 +03:00
orignal
08a82a0bcd don't try to connect to a router not reachable from us 2021-06-17 12:12:06 -04:00
R4SAS
3dc19bfd31 [gha] docker - disable cache (test) 2021-06-17 11:07:56 +03:00
R4SAS
970f47ce33 [gha] remove context 2021-06-17 11:03:30 +03:00
R4SAS
2ee7ed8dda [gha] temporary build only amd64 container 2021-06-17 10:59:47 +03:00
R4SAS
d058b9a595 [gha] fix repository name to lowercase 2021-06-17 10:38:38 +03:00
R4SAS
1dda832e39 [gha] build docker containers
Build docker containers and publish them to GitHub Container Registry
2021-06-17 10:35:10 +03:00
orignal
a6af4908d5 use m_ReachableTransports bitmask 2021-06-16 18:14:33 -04:00
R4SAS
2c7fff077b [gha] add dist name in package changelog
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 22:06:48 +00:00
R4SAS
71df1fc4d6 [gha] do not check source archive for deb build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 21:45:14 +00:00
R4SAS
064ecdb5ec [gha] do no check source archive for deb build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 21:40:45 +00:00
R4SAS
8ec4783249 [gha] fetch all history of git repo for packages (needs for describe)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 21:34:59 +00:00
R4SAS
f9d378f1ce [gha] add deb building
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 21:19:19 +00:00
R4SAS
f07241bff7 add deb building
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 21:14:22 +00:00
R4SAS
a6be32392d update debian packaging files
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 20:41:41 +00:00
R4SAS
ac594dbd26 Update status badges in README 2021-06-16 19:12:05 +03:00
R4SAS
954711e980 [i18n] pull afrikaans translation from crowdin
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 17:57:20 +03:00
R4SAS
2ba3f4758a [i18n] move gettext translation template to contrib
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 17:57:20 +03:00
orignal
6be4d508f3 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2021-06-15 19:10:23 -04:00
orignal
dc75868bd3 check Alice's IP address in PeerTest 2021-06-15 19:09:36 -04:00
R4SAS
c06a560946 [i18n] use xgettext compatible function format for plural
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-16 00:13:26 +03:00
R4SAS
0bacd4df5f [i18n] update gettext description
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-15 23:44:23 +03:00
R4SAS
b91eaf5487 [i18n] update gettext description
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-15 23:30:28 +03:00
R4SAS
eebea7b342 [i18n] Add translation source in gettext format
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-15 23:22:59 +03:00
R4SAS
29c1173e14 [i18n] fixes in translations
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-15 23:22:11 +03:00
idk
b962a330ad Allow passing raw pointers to C wrapper functions, I think 2021-06-15 12:02:57 -04:00
R4SAS
1d973bc3ac [webconsole] remove extra line break
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-15 17:55:22 +03:00
orignal
631c8c9870 use correct address type for NTCP2 acceptors 2021-06-14 21:19:44 -04:00
orignal
bce6685d0c correct check of ipv4/ipv6 address 2021-06-14 12:36:54 -04:00
orignal
e412b17f70 don't publish slow tunnel in LeaseSet if possible 2021-06-11 08:34:56 -04:00
orignal
a92b93192d reg.i2p for subscriptions 2021-06-10 13:24:04 -04:00
R4SAS
8708a0076f fix build with boost < 1.55.0 (closes #1661)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-06-09 22:23:33 +03:00
orignal
83fd289e46 don't re-create noise state for every message 2021-06-09 12:49:50 -04:00
idk
ed53cbb7b7 OK that's my first working C wrapper, but I don't yet know how to do anything other than initialize, start, and stop a router 2021-06-08 16:25:45 -04:00
orignal
3b051dbba3 send OutboundTunnelBuildReply 2021-06-08 15:36:27 -04:00
acetone
8e4781b0f7 tbytes in WinApp (#1660) 2021-06-08 16:39:28 +03:00
acetone
d599502b1a 1000Gb+ display 2021-06-07 23:49:56 -04:00
orignal
8571830485 create transit tunnel and reply for short tunnel build 2021-06-07 18:28:36 -04:00
acetone
48d9a03aa8 tbytes in WinApp 2021-06-07 12:58:57 -04:00
orignal
5fb426b336 decrypt and encrypt reply for short tunnel build message 2021-06-06 13:55:38 -04:00
orignal
d752a83eb5 handle i2cp.dontPublishLeaseSet for all destinations 2021-06-04 18:28:30 -04:00
orignal
e740d5fc4f try to pick non-slow tunnel 2021-06-04 12:16:50 -04:00
orignal
8e3e35a36d decrypt short request record 2021-06-02 19:50:29 -04:00
orignal
5ce9c0f1e2 build new tunnels instead slow 2021-06-02 14:45:21 -04:00
orignal
ef8c4389e1 reachable transports added 2021-06-02 12:55:08 -04:00
R4SAS
0547d590e1 fix typo
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-31 00:24:54 +03:00
R4SAS
be31640010 fix ipv6 preference on linux
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-31 00:23:50 +03:00
R4SAS
39319853ab [i18n] add Turkmen translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-30 21:38:14 +03:00
R4SAS
ed42948051 prefer public ipv6 instead rfc4941 (closes #1251)
Wokrs only on linux-based systems. Not tested on other *nix systems, and
not works on windows.

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-30 03:25:13 +03:00
orignal
a0e545a6f1 always create new tunnel from exploratory pool 2021-05-28 12:11:24 -04:00
R4SAS
e77e383efa [docker] add UPnP at compile time (closes #1649) 2021-05-28 18:59:59 +03:00
orignal
8ce5ceef59 Correct transaltion for "Firewalled" 2021-05-27 17:47:59 -04:00
R4SAS
3a53e049bd [gha] switch ubuntu to 18.04
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 13:43:24 +03:00
R4SAS
5011ecaaa6 [i18n] fix language selection
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 13:27:13 +03:00
R4SAS
35b1842a72 [gha] add cmake build on ubuntu
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 13:21:15 +03:00
R4SAS
0292227a6b [cmake] switch to glob instead filling sources list
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 13:15:17 +03:00
R4SAS
ebce1e34d8 [i18n] enable Ukrainian in source
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 12:56:47 +03:00
R4SAS
cc1244126c [i18n] enable Ukrainian in source
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-26 10:50:02 +03:00
Artem M
bdf63cf82c [i18n] add Ukrainian (#1658) 2021-05-26 10:38:58 +03:00
Artem M
0275f7f574 [i18n] fix two typos in the russian translation (#1659) 2021-05-26 10:05:10 +03:00
R4SAS
779f2fa451 [i18n] rework localization system
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-25 22:03:29 +03:00
R4SAS
1a4250d8cc [i18n] update russian translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-25 00:22:35 +03:00
orignal
08fafe267a rekey all routers to ECIES 2021-05-23 17:27:14 -04:00
orignal
d06924b339 LeaseSet type 3 by default 2021-05-23 14:28:10 -04:00
orignal
585116a51f XMR added 2021-05-23 14:20:23 -04:00
R4SAS
b676d7034f [i18n] update translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 16:30:42 +03:00
orignal
69a0fe3040 pass arg as reference 2021-05-23 08:52:27 -04:00
R4SAS
5207dd4c9e [gha] update freebsd action 2021-05-23 15:43:04 +03:00
R4SAS
919bf4e144 [i18n] add cmake build
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 15:39:29 +03:00
orignal
7ed440ba75 Merge pull request #1657 from PurpleI2P/i18n
I18n
2021-05-23 08:26:11 -04:00
R4SAS
2db035d23c [i18n] fix addresshelper
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 13:16:52 +03:00
R4SAS
a4b84517dc [i18n] rename Russian translation, fix typo
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 10:56:20 +03:00
R4SAS
e687773b41 [18n] translate webconsole
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 10:50:26 +03:00
R4SAS
df66c2d2dc [i18n] translate HTTP proxy
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-23 06:06:04 +03:00
orignal
f321eb66c0 rename DatabaseLookupTageSet to SymmetricKeyTagset 2021-05-22 18:41:25 -04:00
R4SAS
80b44fc9a9 Support multilang, update code
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-22 18:29:05 +03:00
R4SAS
0e68fe4a57 [i18n] start multilang support for webconsole
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-22 08:39:29 +03:00
orignal
59b471b9a2 i2cp.leaseSetPrivKey for HTTP and SOCKS proxy 2021-05-20 14:10:31 -04:00
orignal
f22eaa6db5 2.38.0 2021-05-16 14:26:00 -04:00
R4SAS
e37244fa0d remove deprecated options from config file example
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-15 16:35:38 +03:00
R4SAS
c359c6e634 update config file example, add v6 status to windows daemon window, code cleanup
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-05-15 16:31:53 +03:00
orignal
d299cbaabd Add/Remove subsession 2021-05-13 19:30:54 -04:00
orignal
2b22bfadbc show version in hidden content 2021-05-12 11:48:27 -04:00
orignal
baec22610e always set expiration time for NSR tagset 2021-05-12 07:57:37 -04:00
orignal
43b587636b delete tags of termiated session right away 2021-05-11 18:49:17 -04:00
orignal
c6cdb26f47 reduce range for extra tags 2021-05-10 20:20:25 -04:00
orignal
1285e30b3e more pre-calculated x25519 2021-05-10 18:55:39 -04:00
orignal
a8e1cd9a13 don't throw exception if local bind fails 2021-05-10 11:04:08 -04:00
orignal
d6f5640685 attach updated LeaseSet to ECIESx25519 incoming sessions 2021-05-09 07:33:26 -04:00
orignal
79dbf2a43e request encrypted LeaseSet if expired 2021-05-07 22:15:12 -04:00
orignal
5ad4c2a65e run ipv6 peer test again if still testing 2021-05-04 14:59:25 -04:00
orignal
fffa550bb0 SAM subsessions 2021-05-04 14:27:06 -04:00
orignal
0b9cb4e75b check identity and signature length for SessionConfirmed 2021-05-03 19:05:25 -04:00
orignal
7f143a7f23 support EdDSA for blinding 2021-05-02 15:02:52 -04:00
orignal
d8d8a68814 rekey all routers but floodfills 2021-04-30 15:19:31 -04:00
orignal
4018cf9d76 SAM single and master sessions 2021-04-26 21:11:36 -04:00
orignal
bd33ac202f handle hostname for STREAM CREATE 2021-04-26 18:21:00 -04:00
orignal
e091eba831 don't cleanup ipv6 introducers list twice 2021-04-25 17:55:13 -04:00
orignal
4a0dbec4fb recognize non-published NTCP2 address 2021-04-25 16:42:09 -04:00
orignal
90dee900f0 fixed crash 2021-04-25 10:57:31 -04:00
orignal
94555b9c43 don't select next introducers from existing sessions 2021-04-24 14:56:34 -04:00
orignal
db93a7315f find new introducers to connect 2021-04-24 11:11:12 -04:00
orignal
7a19533380 reuse current introducers if no more available 2021-04-23 12:17:48 -04:00
orignal
9d79b26506 check if port if specified 2021-04-22 19:32:47 -04:00
orignal
b43a9cc80d handle master session creation 2021-04-21 19:30:20 -04:00
orignal
b5618af308 find all introducers at the time 2021-04-21 15:41:04 -04:00
orignal
9c8c3b9174 select few introducers at the time 2021-04-21 10:56:39 -04:00
orignal
01e591b261 find ipv6 intrioducer session 2021-04-21 09:55:36 -04:00
orignal
060e30d283 select ipv6 random introducer 2021-04-21 08:16:13 -04:00
orignal
ad019da553 publish ipv6 introducers 2021-04-20 20:02:30 -04:00
orignal
69afd3a1da Merge pull request #1651 from acetoneRu/openssl
Уточнение про логирование в Windows
2021-04-19 07:29:33 -04:00
acetone
7978adc577 Уточнение про логирование в Windows 2021-04-19 06:43:51 -04:00
orignal
ca77ca6ef0 reseed from compatible address 2021-04-18 17:27:50 -04:00
orignal
d5b61ed544 select different routers for peer test 2021-04-17 14:33:53 -04:00
orignal
5edb256990 check if our external IP is valid 2021-04-16 19:31:49 -04:00
orignal
74d0c04314 ipv6 address for relay reponse and relay intro 2021-04-15 16:06:02 -04:00
orignal
39d4464be0 make sure that introducer or peer test router is reachable by SSU 2021-04-15 11:43:43 -04:00
orignal
be48dc6e87 pick correct local address for intro key 2021-04-13 15:11:37 -04:00
orignal
2783337284 require ipv4 for IBGW 2021-04-13 09:16:52 -04:00
orignal
727743979c Merge pull request #1648 from acetoneRu/openssl
SAM section fixed
2021-04-13 07:33:07 -04:00
acetone
4543e14c57 SAM section fixed 2021-04-13 02:43:42 -04:00
orignal
83fc1b0b8e support b32 and b33 addresses in STREAM CONNECT 2021-04-11 17:26:45 -04:00
orignal
df858d9143 publish iexp 2021-04-09 13:29:07 -04:00
orignal
ac47c9c673 don't check U cap 2021-04-09 10:56:46 -04:00
orignal
b9a2d5df02 send HolePunch back based on actual address type 2021-04-08 21:07:14 -04:00
orignal
3e873f88c9 don't drop introducers without iExp 2021-04-07 15:55:38 -04:00
orignal
277cef5ec4 eliminate cost field 2021-04-07 13:05:38 -04:00
orignal
5c9b478e46 published field for SSU addresses 2021-04-05 21:45:48 -04:00
orignal
ff89edf127 pick random introducer 2021-04-05 18:22:48 -04:00
orignal
2cc9791bf2 exclude already expired introducers 2021-04-04 10:36:22 -04:00
orignal
67b32005f6 check if host if unspecified 2021-04-03 22:18:09 -04:00
orignal
0f166973ca check ureachable cap and actual introducers separately 2021-04-03 20:03:19 -04:00
orignal
4f3333c841 don't check range ffor unspecified address 2021-04-03 19:24:07 -04:00
orignal
bea384abea recongnize v4 and v6 SSU addresses without host 2021-04-03 18:56:50 -04:00
orignal
43033695f6 select apropriate address for peer test 2021-04-02 21:31:14 -04:00
orignal
51ef7ef61c don't publish LeaseSet without tunnels 2021-04-01 13:37:21 -04:00
orignal
823b499a02 remove already expired LeaseSets 2021-04-01 11:45:50 -04:00
orignal
bb5ed0b40c assign correct 6 or 4 cap to unpublished address 2021-04-01 11:02:29 -04:00
orignal
94ca2514af set zero expiration timeout if no tunnels 2021-04-01 10:29:03 -04:00
orignal
5412352dec publish ipv6 introducers for ipv6 addresses 2021-03-31 13:42:57 -04:00
orignal
c94e8c7df4 Merge pull request #1646 from acetoneRu/openssl
reg.i2p to subscriptions
2021-03-31 12:28:59 -04:00
acetone
094541caa6 reg.i2p to subscriptions 2021-03-31 12:16:06 -04:00
orignal
8c59977e34 Merge pull request #1645 from acetoneRu/openssl
Configuration file example updated
2021-03-31 12:13:17 -04:00
acetone
881bca6ae3 Depricated "nat" deleted 2021-03-31 12:09:06 -04:00
acetone
22865f8ee4 reseed.yggurl and persist.addressbook added 2021-03-31 12:05:23 -04:00
acetone
f3b728d828 Yggdrasil configuration added
[meshnets] section
2021-03-31 08:45:56 -04:00
orignal
bd7328345f Don't change Yddrasil address if router becomes unreachable through ipv6 2021-03-30 19:27:40 -04:00
orignal
25eae3c116 return relay tag for ipv6 introducer 2021-03-30 11:31:11 -04:00
orignal
5cca5472e6 don't handle unsilicited HolePunch 2021-03-29 15:50:33 -04:00
orignal
8462d382f4 don't create SSU session for HolePunch 2021-03-29 15:16:39 -04:00
orignal
2b0d18a6d7 don't change router status from ipv6 2021-03-29 14:44:50 -04:00
orignal
edf3b7e2fc set X bandiwth for floodfill by default 2021-03-28 13:13:00 -04:00
orignal
167d3a0e3c don't create BN_CTX for ECIES tunnel build record decryption 2021-03-28 12:14:02 -04:00
orignal
86415bc61f publish introducer cap for ipv6 address 2021-03-27 18:49:35 -04:00
orignal
a6ea37a21e set ipv6 address caps depending on peer test 2021-03-27 15:16:56 -04:00
orignal
3695aa924b doesn't send peer test to a reserved address 2021-03-24 10:32:15 -04:00
orignal
9e050d1a23 peer test for ipv6 2021-03-23 15:36:57 -04:00
orignal
34eee2fc26 fixed #1644. check leaseset buffer size 2021-03-22 20:12:58 -04:00
orignal
ac10f3055d pick correct local SSU address for sending peer test 2021-03-19 21:51:45 -04:00
orignal
991b74f036 bind ipv6 or yggdrasil acceptor to specified address 2021-03-19 13:10:24 -04:00
orignal
589049ef0f connect to ipv6 address through introducer 2021-03-19 10:20:02 -04:00
orignal
6b0c7c2313 handle ipv6 address in RelayResponse 2021-03-18 21:29:39 -04:00
orignal
a9c7d0d598 common ExtractIPAddressAndPort 2021-03-18 20:11:24 -04:00
orignal
ef1dfb153c handle ipv6 address for RelayIntro 2021-03-18 18:37:02 -04:00
orignal
ff9ee5873f post LeaseSet creation to I2CP destnation's thread 2021-03-17 15:10:14 -04:00
orignal
a7b56bbbb7 publish Yggdrasil address when enabled 2021-03-17 11:26:52 -04:00
orignal
820a365474 select random peer for first hop for outbound tunnel if number of connections < 100 2021-03-16 18:45:51 -04:00
orignal
1d5d06f731 find actual router for peer 2021-03-16 15:23:00 -04:00
orignal
43d458cf72 publish and upublish NTCP2 and yggdrasil addresses separatly 2021-03-16 13:08:10 -04:00
orignal
436a3e7f54 2.37.0 2021-03-15 09:00:25 -04:00
orignal
7015bad905 2.37.0 2021-03-15 08:30:04 -04:00
orignal
cf8665748b network sattus Mesh added 2021-03-13 10:28:03 -05:00
orignal
1b8da90cbb more precise compatibility check 2021-03-12 20:51:12 -05:00
orignal
6012585067 eliminate false positive symmetric NAT 2021-03-12 17:41:41 -05:00
orignal
f162876600 insert ipv4 address if enabled back 2021-03-12 16:13:01 -05:00
orignal
6555ae5b0a support authorization for reseed proxy 2021-03-11 17:02:56 -05:00
R4SAS
f5af059ef4 [webconsole] add submission of address registration line to reg.i2p
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-03-11 15:20:40 +03:00
R4SAS
cb8651ec68 [win32] drop service code, fix start with daemon option. Throw notification when unable to parse config
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-03-11 14:40:06 +03:00
orignal
7c0b0a4e3e common HTTP basic authorization string 2021-03-10 22:47:31 -05:00
orignal
880d1a7ccd NTCP2 proxy with authorization 2021-03-10 20:00:21 -05:00
orignal
744b25190a don't set proxy if ntcp2 is disabled 2021-03-10 15:36:10 -05:00
orignal
3792bb4928 delete sig buffer 2021-03-09 22:10:51 -05:00
R4SAS
9049902ced [webconsole] add address registration line generator
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-03-10 01:48:54 +03:00
orignal
5f93dc72fd convert ifname* params to address* 2021-03-09 15:28:07 -05:00
orignal
09dadd7e01 Merge pull request #1640 from brain5lug/openssl
logging opimization
2021-03-09 07:46:28 -05:00
orignal
60b92f98db OBEP must be ipv4 compatible 2021-03-08 18:54:17 -05:00
orignal
97f315d488 set correct 4 and 6 caps for unreachable addresses 2021-03-08 15:57:05 -05:00
brain5lug
f3676d7f18 logging opimization 2021-03-08 11:31:00 +03:00
orignal
742dbdb68a rekey low badwidth routers to ECIES 2021-03-07 10:07:51 -05:00
orignal
2d59c968ca don't publish NTCP2 address connected through proxy 2021-03-06 18:43:50 -05:00
orignal
ad22247c9e start other acceptors if connected through a proxy 2021-03-06 15:35:31 -05:00
orignal
f38920c338 Status: Proxy 2021-03-06 08:50:47 -05:00
orignal
8f90b21a5d fixed typo 2021-03-05 22:40:27 -05:00
orignal
ff0e6813c6 fixed typo 2021-03-05 21:53:19 -05:00
orignal
fa5e4d57fd correct caps for SSU address without host 2021-03-05 19:40:37 -05:00
orignal
876973f071 remove coreVersion 2021-03-05 09:29:28 -05:00
orignal
b994af9209 check reachability of floodfill to request from 2021-03-05 08:41:44 -05:00
orignal
1f6cde652e check caps for SSU address 2021-03-04 22:47:56 -05:00
R4SAS
3bf6db1c08 enable yggdrasil address finding for android
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-03-05 03:20:12 +03:00
orignal
e70ffc9d7c re-shedule introducers updates if router becomes firewalled 2021-03-04 15:55:51 -05:00
orignal
065cfe3b9d separate ratchet session for ECIES router 2021-03-03 15:30:13 -05:00
orignal
def9873a70 request multiple introducers at the time 2021-03-02 21:10:19 -05:00
orignal
618aa26454 allow some unreachable floodfills 2021-03-02 14:13:28 -05:00
orignal
924a7bc533 use connected peers if others not available 2021-03-02 12:29:51 -05:00
orignal
ef85277a1b select reachable routers for one hop tunnels 2021-03-02 08:46:13 -05:00
orignal
876375f2c3 precise bandwidth limit 2021-03-01 22:13:17 -05:00
orignal
f70ee480ba check connectivity between peers for tunnel 2021-03-01 19:02:27 -05:00
orignal
6d88c3ab05 Symmetric NAT error 2021-03-01 12:20:53 -05:00
orignal
57c969b0ed constants for cost 2021-03-01 11:09:25 -05:00
orignal
ae58a7007b different cost for direct or with introducers SSU address 2021-02-28 19:19:09 -05:00
orignal
11c924bbe7 publish and handle SSU addreses without host 2021-02-28 18:58:25 -05:00
orignal
8bab4f60ef open socket before bing 2021-02-28 09:04:34 -05:00
orignal
bef9a54f4a bind SSU socket to specified address 2021-02-27 16:13:12 -05:00
orignal
288b19c3f7 bind NTCP2 ipv4 acceptor to specified local address 2021-02-27 10:35:50 -05:00
orignal
40f7e9d33e separate decryptor for tunnel builds and floodfill requests 2021-02-26 21:02:51 -05:00
orignal
fab53dda66 fixed typo 2021-02-26 20:38:16 -05:00
orignal
a4e8bf9857 bind NTCP2 connections to specified address 2021-02-26 19:31:38 -05:00
R4SAS
2cdf84cdab [actions] upload windows artifacts 2021-02-26 21:09:01 +00:00
orignal
fbe83f729d don't try to send to unreachable router 2021-02-25 19:55:46 -05:00
R4SAS
4371a084ec check for pubkey in X25519Keys::Agree
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-02-26 03:20:06 +03:00
orignal
d13f58088a Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2021-02-24 18:41:31 -05:00
orignal
f75bef7c03 don't set local address if not specified 2021-02-24 18:40:24 -05:00
R4SAS
3d7e93a688 systemd: use SIGTERM instead SIGQUIT, indent UPNP code, make client target
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2021-02-25 00:37:41 +03:00
orignal
a4dda304d2 cancel connect timer upon SessionConfirmed 2021-02-24 10:03:23 -05:00
orignal
124c3ef2d7 always publish SSU port 2021-02-23 21:15:17 -05:00
orignal
c3a2fca76a 4 or 6 caps for non-published addresses 2021-02-23 19:59:35 -05:00
orignal
b60ebfe1c6 parse '4' and '6' address caps 2021-02-22 22:53:25 -05:00
orignal
1d7639b3f4 caps per address 2021-02-22 21:04:26 -05:00
orignal
2d972752ff lookuplocal 2021-02-21 16:20:57 -05:00
orignal
616f0b2a21 address parameter for server tunnels 2021-02-19 15:15:58 -05:00
orignal
94659ba890 create ipv4 and ipv6 NTCP2 addresses separately 2021-02-17 21:51:35 -05:00
orignal
d65bc068de create ipv4 and ipv6 NTCP2 addresses separately 2021-02-17 21:12:17 -05:00
orignal
1ca0354cf2 find NTCP2 address by static key. Don't make router unreachable if can't connect by NTCP2 2021-02-17 18:46:41 -05:00
orignal
b1fcd4d27b show actual IP addresses for proxy connections 2021-02-17 14:26:48 -05:00
169 changed files with 10460 additions and 5204 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
/build/build_mingw.cmd eol=crlf

View File

@@ -4,15 +4,16 @@ on: [push, pull_request]
jobs:
build:
runs-on: macos-latest
runs-on: macos-10.15
name: with UPnP
steps:
- uses: actions/checkout@v2
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.1.2
uses: vmactions/freebsd-vm@v0.1.5
with:
usesh: true
mem: 2048
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
run: |
cd build

View File

@@ -8,14 +8,15 @@ defaults:
jobs:
build:
name: Building for ${{ matrix.arch }}
name: Building using ${{ matrix.arch }} toolchain
runs-on: windows-latest
strategy:
fail-fast: true
matrix:
include: [
{ msystem: MINGW64, arch: x86_64 },
{ msystem: MINGW32, arch: i686 }
{ 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 }
]
steps:
- uses: actions/checkout@v2
@@ -25,7 +26,12 @@ jobs:
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
update: true
- name: build application
- name: Build application
run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no -j3
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: i2pd-${{ matrix.arch_short }}.exe
path: i2pd.exe

View File

@@ -3,9 +3,9 @@ name: Build on Ubuntu
on: [push, pull_request]
jobs:
build:
name: With USE_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-16.04
build-make:
name: Make with USE_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-18.04
strategy:
fail-fast: true
matrix:
@@ -19,3 +19,70 @@ jobs:
sudo apt-get install build-essential libboost1.74-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
strategy:
fail-fast: true
matrix:
with_upnp: ['ON', 'OFF']
steps:
- uses: actions/checkout@v2
- 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
- name: build application
run: |
cd build
cmake -DWITH_UPNP=${{ matrix.with_upnp }} .
make -j3
build-deb-stretch:
name: Build package for stretch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-stretch" -b -M --distribution stretch "trunk build"
- uses: singingwolfboy/build-dpkg-stretch@v1
id: build
with:
args: --unsigned-source --unsigned-changes -b
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename }}
path: ${{ steps.build.outputs.filename }}
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename-dbgsym }}
path: ${{ steps.build.outputs.filename-dbgsym }}
build-deb-buster:
name: Build package for buster
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-buster" -b -M --distribution buster "trunk build"
- uses: singingwolfboy/build-dpkg-buster@v1
id: build
with:
args: --unsigned-source --unsigned-changes -b
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename }}
path: ${{ steps.build.outputs.filename }}
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename-dbgsym }}
path: ${{ steps.build.outputs.filename-dbgsym }}

63
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Build containers
on: [push]
jobs:
docker:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push trunk container
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: docker/build-push-action@v2
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
push: true
tags: |
purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:latest
- name: Set env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Build and push release container
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: docker/build-push-action@v2
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
push: true
tags: |
purplei2p/i2pd:latest
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
ghcr.io/purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}

6
.gitignore vendored
View File

@@ -7,8 +7,13 @@ netDb
/i2pd
/libi2pd.a
/libi2pdclient.a
/libi2pdlang.a
/libi2pd.so
/libi2pdclient.so
/libi2pdlang.so
/libi2pd.dll
/libi2pdclient.dll
/libi2pdlang.dll
*.exe
@@ -255,6 +260,7 @@ docs/generated
build/Makefile
# debian stuff
debian/i2pd.1.gz
.pc/
# qt

0
.gitmodules vendored
View File

View File

@@ -1,54 +0,0 @@
language: cpp
cache:
apt: true
os:
- linux
#- osx
dist: xenial
sudo: required
compiler:
- g++
- clang++
env:
global:
- MAKEFLAGS="-j 2"
matrix:
- BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes
- BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no
- BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes
- BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no
matrix:
exclude:
- os: osx
env: BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes
- os: osx
env: BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no
- os: linux
compiler: clang++
env: BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes
- os: linux
compiler: clang++
env: BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no
addons:
apt:
packages:
- build-essential
- cmake
- g++
- clang
- libboost-chrono-dev
- libboost-date-time-dev
- libboost-filesystem-dev
- libboost-program-options-dev
- libboost-system-dev
- libboost-thread-dev
- libminiupnpc-dev
- libssl-dev
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libressl miniupnpc ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew outdated boost || brew upgrade boost ; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "cmake" ]]; then cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_UPNP=${UPNP} && make ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "make" ]]; then make USE_UPNP=${MAKE_UPNP} ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make HOMEBREW=1 USE_UPNP=${MAKE_UPNP} ; fi

178
ChangeLog
View File

@@ -1,6 +1,162 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.41.0] - 2022-02-20
### Added
- Clock syncronization through SSU
- Drop routers older than 6 months on start
- Localization to German
- Don't send streaming ack too frequently
- Select compatible outbound tunnel for I2CP messages
- Restart webconsole's acceptor in case of exception
### Changed
- Use builtin bitswap for endian on windows
- Send SessionCreated before connection close if clock skew
- Try another floodfill for publishing if no compatible tunnels found
- Reduce memory usage for RouterInfo structures
- Avoid duplicated addresses in RouterInfo. Check presence of netId and version
- Use TCP/IP sockets for I2CP on Android instead local sockets
- Return uptime as integer in I2PControl
- Reseed servers list/cerificates
- Webconsole's dark style colors
### Fixed
- Attempt to use Yggdrasil on start on Android
- Attempts to send peer tests to itself
- Severe packets drop in SSU
- Crash on tunnel tests
- Loading addressbook subscriptions from config
- Multiple I2CP session to the same destination
- Build on Apple Silicon
## [2.40.0] - 2021-11-29
### Added
- Keep alive parameter for client tunnels
- Support openssl 3.0.0
- Localization to Armenian
- Show git commit info in version
- Windows menu item for opening datadir
- Reseed if too few floodfills
- Don't publish old and replacing tunnel in LeaseSet
- Webconsole light/dark theme depending on system settings (via CSS)
### Changed
- Set gzip compression to false by default
- Build tunnel through ECIES routers only
- Removed ElGamal support for tunnels
- Moved webconsole resources to separate file
- Pick tunnels with compatible transport with another tunnel of floodfill
- Use common cleanup timer for all SSU sessions
- Reduced memory usage
- Reseed servers list
- i18n code called from ClientContext
### Fixed
- Tunnels reload
- Some typos in log messages
- Cleanup relay requests table
- Server tunnel is not published
- Build on GNU/Hurd. Disable pthread_setname_np
- Crash when incorrect sigtype used with blinding
## [2.39.0] - 2021-08-23
### Added
- Short tunnel build messages
- Localization. To: Russian, Ukrainian, Turkmen, Uzbek and Afrikaans
- Custom CSS styles for webconsole
- Avoid slow tunnels with more than 250 ms per hop
- Process DELAY_REQUESTED streaming option
- "certsdir" options for certificates location
- Keep own RouterInfo in NetBb
- Pick ECIES routers only for tunnels on non-x64
- NTP sync through ipv6
- Allow ipv6 addresses for UDP server tunnels
### Changed
- Rekey of all routers to ECIES
- Better distribution for random tunnel's peer selection
- Yggdrasil reseed for v0.4, added two more
- Encryption type 0,4 by default for server tunnels
- Handle i2cp.dontPublishLeaseSet param for all destinations
- reg.i2p for subscriptions
- LeaseSet type 3 by default
- Don't allocate payload buffer for every single ECIESx25519 message
- Prefer public ipv6 instead rfc4941
- Optimal padding for one-time ECIESx25519 message
- Don't send datetime block for one-time ECIESx25519 message with one-time key
- Router with expired introducer is still valid
- Don't disable floodfill if still reachable by ipv6
- Set minimal version for floodfill to 0.9.38
- Eliminate extra lookups for sequential fragments on tunnel endpoint
- Consistent path for explicit peers
- Always create new tunnel from exploratory pool
- Don't try to connect to a router not reachable from us
- Mark additional ipv6 addresses/nets as reserved (#1679)
### Fixed
- Zero-hop tunnels
- Crash upon SAM session termination
- Build with boost < 1.55.0
- Address type for NTCP2 acceptors
- Check of ipv4/ipv6 address
- Request router to send to if not in NetDb
- Count outbound traffic for zero-hop tunnels
- URLdecode domain for registration string generator in webconsole
## [2.38.0] - 2021-05-17
### Added
- Publish ipv6 introducers
- Bind ipv6 or yggdrasil NTCP2 acceptor to specified address
- Support .b32.i2p addresses and hostnames for SAM STREAM CREATE
- ipv6 peer tests
- Publish iexp param for introducers
- Show ipv6 network status on the webconsole
- EdDSA signing keys can also be blinded
- Show router version on the webconsole
### Changed
- Rekey of all routers but floodfills to ECIES
- Increased number of precalculated x25519 keys to 15
- Don't publish LeaseSet without inbound tunnels
- Reseed from compatible address(ipv4 or ipv6)
- Recongnize v4 and v6 SSU addresses without host
- Inbound tunnel gateway must be ipv4 compatible
- Don't select next introducers from existing sessions
- Set X bandwidth for floodfill by default
### Fixed
- Incoming ECIES-x25519 session doesn't send updated LeaseSet
- Unique local address for server tunnels
- Race condition for LeaseSet creation in I2CP
- Relay tag for ipv6 introducer
- Already expired introducers
- Find connected router for first peer in tunnel
- Failed outgoing ECIES-x25519 session's tagset stays forever
- Yggdrasil address disappears if router becomes unreachable through ipv6
- Ignore SSU address/introducers if port is not specified
- Check identity and signature length for SSU SessionConfirmed
## [2.37.0] - 2021-03-15
### Added
- Address registration line for reg.i2p and stats.i2p through the web console
- "4" and "6" caps for addresses without published IP address
- Mesh and Proxy network statuses
- Symmetric NAT network status error
- Bind server tunnel connection to specified address
- lookuplocal BOB extended command
- address4 and address6 parameters to bind outgoing connections to
- Rekey of low-bandwidth routers to ECIES
- Popup notification windows when unable to parse config for Windows
### Changed
- Floodfills with "U" cap are not ignored anymore
- Check transports reachability between tunnel peers and between router and floodfill
- NTCP2 and reseed HTTP proxy support authorization now
- Show actual IP addresses for proxy connections
- Publish and handle SSU addreses without host
- Outbound tunnel endpoint must be ipv4 compatible
- Logging optimization
- Removed Windows service
### Fixed
- Incoming SSU session terminates after 5 seconds
- Outgoing NTCP2 ipv4 session even if ipv4 is disabled
- No incoming Yggdrasil connection if connected through NTCP2 proxy
- Race condition between tunnel build and floodfill requests decryption for ECIES routers
- Numeric bandwidth limitation
- Yggdrasil for Android
## [2.36.0] - 2021-02-15
### Added
- Encrypted lookup and publications to ECIES-x25519 floodfiils
@@ -8,22 +164,22 @@
- Dump addressbook in hosts.txt format
- Request RouterInfo through exploratory tunnels if direct connection to fllodfill is not possible
- Threads naming
- Check if public x25519 key is valid
- Check if public x25519 key is valid
- ECIES-X25519-AEAD-Ratchet for shared local destination
- LeaseSet creation timeout for I2CP session
- Resend RouterInfo after some interval for longer NTCP2 sessions
- Select reachable router of inbound tunnel gateway
- Reseed if no compatible routers in netdb
- Reseed if no compatible routers in netdb
- Refresh on swipe in Android webconsole
### Changed
- reg.i2p for default addressbook instead inr.i2p
- ECIES-x25519 (crypto type 4) for new routers
- Try to connect to all compatible addresses from peer's RouterInfo
- Replace LeaseSet completely if store type changes
- Replace LeaseSet completely if store type changes
- Try ECIES-X25519-AEAD-Ratchet tag before ElGamal
- Don't detach ECIES-X25519-AEAD-Ratchet session from destination immediately
- Viewport and styles on error in HTTP proxy
- Don't create notification when Windows taskbar restarted
- Don't create notification when Windows taskbar restarted
- Cumulative SSU ACK bitfields
- limit tunnel length to 8 hops
- Limit tunnels quantity to 16
@@ -56,7 +212,7 @@
- Transient signature length, if different from identity
- Terminate I2CP session if destroyed
- RouterInfo publishing confirmation
- Check if ECIES-X25519-AEAD-Ratchet session expired before generating more tags
- Check if ECIES-X25519-AEAD-Ratchet session expired before generating more tags
- Correct block size for delivery type local for ECIES-X25519-AEAD-Ratchet
## [2.34.0] - 2020-10-27
@@ -67,7 +223,7 @@
- Single thread for I2CP
- Shared transient destination between proxies
- Database lookups from ECIES destinations with ratchets response
- Handle WebDAV HTTP methods
- Handle WebDAV HTTP methods
- Don't try to connect or build tunnels if offline
- Validate IP when trying connect to remote peer
- Handle ICMP responses and WinAPI errors for SSU
@@ -84,7 +240,7 @@
- Random crashes on I2CP session disconnect
- Stream through racthets hangs if first SYN was not acked
- Check "Last-Modified" instead "If-Modified-Since" for addressbook reponse
- Trim behind ECIESx25519 tags
- Trim behind ECIESx25519 tags
- Few bugs with Android main activity
- QT visual and layout issues
@@ -95,11 +251,11 @@
- Multiple encryption keys through I2CP
- Pre-calculated x25519 ephemeral keys
- Change datagram routing path if nothing comes back in 10 seconds
- Shared routing path for datagram session
- Shared routing path for datagram session
### Changed
- UDP tunnels send mix of repliable and raw datagrams in bulk
- Encrypt SSU packet again upon resend
- Start new tunnel message if remaining buffer is too small
- Start new tunnel message if remaining buffer is too small
- Use LeaseSet2 for ECIES-X25519-AEAD-Ratchet automatically
- Save new ECIES-X25519-AEAD-Ratchet session with NSR tagset
- Generate random padding lengths for ECIES-X25519-AEAD-Ratchet in bulk
@@ -107,11 +263,11 @@
- Reseed servers list
### Fixed
- Don't connect through terminated SAM destination
- Differentiate UDP server sessions by port
- Differentiate UDP server sessions by port
- ECIES-X25519-AEAD-Ratchet through I2CP
- Don't save invalid address to AddressBook
- ECDSA signatures names in SAM
- AppArmor profile
- AppArmor profile
## [2.32.1] - 2020-06-02
### Added

View File

@@ -1,22 +1,45 @@
.DEFAULT_GOAL := all
SYS := $(shell $(CXX) -dumpmachine)
SHLIB := libi2pd.so
ifneq (, $(findstring darwin, $(SYS)))
SHARED_SUFFIX = dylib
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
SHARED_SUFFIX = dll
else
SHARED_SUFFIX = so
endif
SHLIB := libi2pd.$(SHARED_SUFFIX)
ARLIB := libi2pd.a
SHLIB_CLIENT := libi2pdclient.so
SHLIB_LANG := libi2pdlang.$(SHARED_SUFFIX)
ARLIB_LANG := libi2pdlang.a
SHLIB_CLIENT := libi2pdclient.$(SHARED_SUFFIX)
ARLIB_CLIENT := libi2pdclient.a
SHLIB_WRAP := libi2pdwrapper.$(SHARED_SUFFIX)
ARLIB_WRAP := libi2pdwrapper.a
I2PD := i2pd
LIB_SRC_DIR := libi2pd
LIB_CLIENT_SRC_DIR := libi2pd_client
WRAP_SRC_DIR := libi2pd_wrapper
LANG_SRC_DIR := i18n
DAEMON_SRC_DIR := daemon
# import source files lists
include filelist.mk
USE_AESNI := yes
USE_STATIC := no
USE_MESHNET := no
USE_UPNP := no
DEBUG := yes
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
USE_MESHNET := $(or $(USE_MESHNET),no)
USE_UPNP := $(or $(USE_UPNP),no)
DEBUG := $(or $(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
# for MacOS only, waiting for "1", not "yes"
HOMEBREW := $(or $(HOMEBREW),0)
ifeq ($(DEBUG),yes)
CXX_DEBUG = -g
@@ -39,7 +62,7 @@ else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.bsd
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
include Makefile.mingw
else # not supported
$(error Not supported platform)
@@ -49,24 +72,36 @@ ifeq ($(USE_MESHNET),yes)
NEEDED_CXXFLAGS += -DMESHNET
endif
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR)
ifeq ($(USE_GIT_VERSION),yes)
GIT_VERSION := $(shell git describe --tags)
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
endif
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR)
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))
DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC))
DEPS += $(LIB_OBJS:.o=.d) $(LIB_CLIENT_OBJS:.o=.d) $(DAEMON_OBJS:.o=.d)
WRAP_LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(WRAP_LIB_SRC))
DEPS += $(LIB_OBJS:.o=.d) $(LIB_CLIENT_OBJS:.o=.d) $(LANG_OBJS:.o=.d) $(DAEMON_OBJS:.o=.d) $(WRAP_LIB_OBJS:.o=.d)
all: mk_obj_dir $(ARLIB) $(ARLIB_CLIENT) $(I2PD)
## Build all code (libi2pd, libi2pdclient, libi2pdlang), link it to .a and build binary
all: $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(I2PD)
mk_obj_dir:
@mkdir -p obj
@mkdir -p obj/Win32
@mkdir -p obj/$(LIB_SRC_DIR)
@mkdir -p obj/$(LIB_CLIENT_SRC_DIR)
@mkdir -p obj/$(LANG_SRC_DIR)
@mkdir -p obj/$(DAEMON_SRC_DIR)
@mkdir -p obj/$(WRAP_SRC_DIR)
@mkdir -p obj/Win32
api: mk_obj_dir $(SHLIB) $(ARLIB)
api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
api: $(SHLIB) $(ARLIB)
client: $(SHLIB_CLIENT) $(ARLIB_CLIENT)
lang: $(SHLIB_LANG) $(ARLIB_LANG)
api_client: api client lang
wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
## NOTE: The NEEDED_CXXFLAGS are here so that CXXFLAGS can be specified at build time
## **without** overwriting the CXXFLAGS which we need in order to build.
@@ -75,23 +110,33 @@ api_client: mk_obj_dir $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
## -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.
obj/%.o: %.cpp
obj/%.o: %.cpp | mk_obj_dir
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -c -o $@ $<
# '-' is 'ignore if missing' on first run
-include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS)
$(SHLIB): $(LIB_OBJS) $(SHLIB_LANG)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB_LANG)
endif
$(SHLIB_CLIENT): $(LIB_CLIENT_OBJS) $(SHLIB) $(SHLIB_LANG)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) $(SHLIB_LANG)
endif
$(SHLIB_WRAP): $(WRAP_LIB_OBJS)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
endif
$(SHLIB_CLIENT): $(LIB_CLIENT_OBJS)
$(SHLIB_LANG): $(LANG_OBJS)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
endif
$(ARLIB): $(LIB_OBJS)
@@ -100,12 +145,18 @@ $(ARLIB): $(LIB_OBJS)
$(ARLIB_CLIENT): $(LIB_CLIENT_OBJS)
$(AR) -r $@ $^
$(ARLIB_WRAP): $(WRAP_LIB_OBJS)
$(AR) -r $@ $^
$(ARLIB_LANG): $(LANG_OBJS)
$(AR) -r $@ $^
clean:
$(RM) -r obj
$(RM) -r docs/generated
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) $(SHLIB_WRAP) $(ARLIB_WRAP)
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
strip $^
LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl)
@@ -128,6 +179,8 @@ doxygen:
.PHONY: last-dist
.PHONY: api
.PHONY: api_client
.PHONY: client
.PHONY: lang
.PHONY: mk_obj_dir
.PHONY: install
.PHONY: strip

View File

@@ -44,7 +44,7 @@ install: all
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
@gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt

View File

@@ -3,9 +3,9 @@ USE_WIN32_APP := yes
WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -D_MT -DWIN32_LEAN_AND_MEAN -fPIC -msse
CXXFLAGS := $(CXX_DEBUG) -DWIN32_LEAN_AND_MEAN -fPIC -msse
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -Wl,-Bstatic -static-libgcc
LDFLAGS := ${LD_DEBUG} -static
# detect proper flag for c++11 support by compilers
CXXVER := $(shell $(CXX) -dumpversion)
@@ -61,5 +61,5 @@ ifeq ($(USE_ASLR),yes)
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
endif
obj/%.o : %.rc
obj/%.o : %.rc | mk_obj_dir
$(WINDRES) -i $< -o $@

View File

@@ -3,6 +3,7 @@
[![License](https://img.shields.io/github/license/PurpleI2P/i2pd.svg)](https://github.com/PurpleI2P/i2pd/blob/openssl/LICENSE)
[![Packaging status](https://repology.org/badge/tiny-repos/i2pd.svg)](https://repology.org/project/i2pd/versions)
[![Docker Pulls](https://img.shields.io/docker/pulls/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd)
[![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](https://crowdin.com/project/i2pd)
*note: i2pd for Android can be found in [i2pd-android](https://github.com/PurpleI2P/i2pd-android) repository and with Qt GUI in [i2pd-qt](https://github.com/PurpleI2P/i2pd-qt) repository*
@@ -68,15 +69,15 @@ Build instructions:
**Supported systems:**
* GNU/Linux - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* 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.
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
* Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/)
* Snap
* FreeBSD
* Android
* 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)
* 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)
* iOS
Using i2pd
@@ -85,6 +86,16 @@ Using i2pd
See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and
[example config file](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/i2pd.conf).
Localization
------------
You can help us with translation i2pd to your language using Crowdin platform!
Translation project can be found [here](https://crowdin.com/project/i2pd).
New languages can be requested on project's [discussion page](https://crowdin.com/project/i2pd/discussions).
Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](https://crowdin.com/project/i2pd)
Donations
---------
@@ -94,6 +105,7 @@ ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG
XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH
License
-------

View File

@@ -14,7 +14,6 @@
#include "Log.h"
#ifdef _WIN32
#include "Win32Service.h"
#ifdef WIN32_APP
#include <windows.h>
#include "Win32App.h"
@@ -35,45 +34,11 @@ namespace util
i2p::log::SetThrowFunction ([](const std::string& s)
{
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
});
}
);
if (!Daemon_Singleton::init(argc, argv))
return false;
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
if (serviceControl == "install")
{
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
InstallService(
SERVICE_NAME, // Name of service
SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
SERVICE_DEPENDENCIES, // Dependencies
SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
);
return false;
}
else if (serviceControl == "remove")
{
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
UninstallService(SERVICE_NAME);
return false;
}
if (isDaemon)
{
LogPrint(eLogDebug, "Daemon: running as service");
I2PService service((PSTR)SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
}
else
LogPrint(eLogDebug, "Daemon: running as user");
return true;
}
@@ -86,9 +51,6 @@ namespace util
setlocale(LC_TIME, "C");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App ()) return false;
// override log
i2p::config::SetOption("log", std::string ("file"));
#endif
bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile)

View File

@@ -25,7 +25,7 @@ BEGIN
VALUE "FileDescription", "C++ I2P daemon"
VALUE "FileVersion", I2PD_VERSION
VALUE "InternalName", CODENAME
VALUE "LegalCopyright", "Copyright (C) 2013-2020, The PurpleI2P Project"
VALUE "LegalCopyright", "Copyright (C) 2013-2022, The PurpleI2P Project"
VALUE "OriginalFilename", "i2pd"
VALUE "ProductName", "Purple I2P"
VALUE "ProductVersion", I2P_VERSION

View File

@@ -31,6 +31,7 @@
#define ID_RELOAD 2006
#define ID_ACCEPT_TRANSIT 2007
#define ID_DECLINE_TRANSIT 2008
#define ID_DATADIR 2009
#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)
@@ -49,7 +50,8 @@ namespace win32
{
HMENU hPopup = CreatePopupMenu();
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DATADIR, "Open &datadir");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "&Show app");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
if(!i2p::context.AcceptsTunnels())
@@ -131,7 +133,7 @@ namespace win32
transfer >>= 10;
auto mbytes = transfer & 0x03ff;
transfer >>= 10;
auto gbytes = transfer & 0x03ff;
auto gbytes = transfer;
if (gbytes)
s << gbytes << " GB, ";
@@ -142,25 +144,47 @@ namespace win32
s << bytes << " Bytes\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
{
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;
case eRouterStatusError:
{
s << "Err";
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
s << " - Clock skew";
break;
case eRouterErrorOffline:
s << " - Offline";
break;
case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT";
break;
default: ;
}
break;
}
default: s << "Unk";
}
}
static void PrintMainWindowText (std::stringstream& s)
{
s << "\n";
s << "Status: ";
switch (i2p::context.GetStatus())
ShowNetworkStatus (s, i2p::context.GetStatus ());
if (i2p::context.SupportsV6 ())
{
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Testing"; break;
case eRouterStatusFirewalled: s << "Firewalled"; break;
case eRouterStatusError:
{
switch (i2p::context.GetError())
{
case eRouterErrorClockSkew: s << "Clock skew"; break;
default: s << "Error";
}
break;
}
default: s << "Unknown";
s << " / ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
}
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
@@ -281,6 +305,12 @@ namespace win32
SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL);
return 0;
}
case ID_DATADIR:
{
std::string datadir(i2p::fs::GetUTF8DataDir());
ShellExecute(NULL, "explore", datadir.c_str(), NULL, NULL, SW_SHOWNORMAL);
return 0;
}
}
break;
}

View File

@@ -32,7 +32,7 @@ void SubscribeToEvents()
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
if (SUCCEEDED(Result)) {
i2p::transport::transports.SetOnline (true);
LogPrint(eLogInfo, "NetState: current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
}
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer);
@@ -79,7 +79,7 @@ void UnSubscribeFromEvents()
}
catch (std::exception& ex)
{
LogPrint (eLogError, "NetState: received exception: ", ex.what ());
LogPrint (eLogError, "NetState: Received exception: ", ex.what ());
}
}

View File

@@ -1,414 +0,0 @@
/*
* Copyright (c) 2013-2020, 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 _WIN32
#define _CRT_SECURE_NO_WARNINGS // to use freopen
#endif
#include "Win32Service.h"
#include <assert.h>
//#include <strsafe.h>
#include <windows.h>
#include "Daemon.h"
#include "Log.h"
I2PService *I2PService::s_service = NULL;
BOOL I2PService::isService()
{
BOOL bIsService = FALSE;
HWINSTA hWinStation = GetProcessWindowStation();
if (hWinStation != NULL)
{
USEROBJECTFLAGS uof = { 0 };
if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
{
bIsService = TRUE;
}
}
return bIsService;
}
BOOL I2PService::Run(I2PService &service)
{
s_service = &service;
SERVICE_TABLE_ENTRY serviceTable[] =
{
{ service.m_name, ServiceMain },
{ NULL, NULL }
};
return StartServiceCtrlDispatcher(serviceTable);
}
void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
{
assert(s_service != NULL);
s_service->m_statusHandle = RegisterServiceCtrlHandler(
s_service->m_name, ServiceCtrlHandler);
if (s_service->m_statusHandle == NULL)
{
throw GetLastError();
}
s_service->Start(dwArgc, pszArgv);
}
void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
{
switch (dwCtrl)
{
case SERVICE_CONTROL_STOP: s_service->Stop(); break;
case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
case SERVICE_CONTROL_INTERROGATE: break;
default: break;
}
}
I2PService::I2PService(PSTR pszServiceName,
BOOL fCanStop,
BOOL fCanShutdown,
BOOL fCanPauseContinue)
{
m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName;
m_statusHandle = NULL;
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_START_PENDING;
DWORD dwControlsAccepted = 0;
if (fCanStop)
dwControlsAccepted |= SERVICE_ACCEPT_STOP;
if (fCanShutdown)
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
if (fCanPauseContinue)
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
m_status.dwControlsAccepted = dwControlsAccepted;
m_status.dwWin32ExitCode = NO_ERROR;
m_status.dwServiceSpecificExitCode = 0;
m_status.dwCheckPoint = 0;
m_status.dwWaitHint = 0;
m_fStopping = FALSE;
// Create a manual-reset event that is not signaled at first to indicate
// the stopped signal of the service.
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hStoppedEvent == NULL)
{
throw GetLastError();
}
}
I2PService::~I2PService(void)
{
if (m_hStoppedEvent)
{
CloseHandle(m_hStoppedEvent);
m_hStoppedEvent = NULL;
}
}
void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
{
try
{
SetServiceStatus(SERVICE_START_PENDING);
OnStart(dwArgc, pszArgv);
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Start", dwError);
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_STOPPED);
}
}
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
{
LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE);
Daemon.start();
//i2p::util::config::OptionParser(dwArgc, pszArgv);
//i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
//i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
// i2p::util::config::GetArg("-port", 17070));
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
}
void I2PService::WorkerThread()
{
while (!m_fStopping)
{
::Sleep(1000); // Simulate some lengthy operations.
}
// Signal the stopped event.
SetEvent(m_hStoppedEvent);
}
void I2PService::Stop()
{
DWORD dwOriginalState = m_status.dwCurrentState;
try
{
SetServiceStatus(SERVICE_STOP_PENDING);
OnStop();
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
LogPrint(eLogInfo, "Win32Service Stop", dwError);
SetServiceStatus(dwOriginalState);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(dwOriginalState);
}
}
void I2PService::OnStop()
{
// Log a service stop message to the Application log.
LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE);
Daemon.stop();
m_fStopping = TRUE;
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
{
throw GetLastError();
}
_worker->join();
delete _worker;
}
void I2PService::Pause()
{
try
{
SetServiceStatus(SERVICE_PAUSE_PENDING);
OnPause();
SetServiceStatus(SERVICE_PAUSED);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Pause", dwError);
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_RUNNING);
}
}
void I2PService::OnPause()
{
}
void I2PService::Continue()
{
try
{
SetServiceStatus(SERVICE_CONTINUE_PENDING);
OnContinue();
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Continue", dwError);
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_PAUSED);
}
}
void I2PService::OnContinue()
{
}
void I2PService::Shutdown()
{
try
{
OnShutdown();
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Shutdown", dwError);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to shut down.", EVENTLOG_ERROR_TYPE);
}
}
void I2PService::OnShutdown()
{
}
void I2PService::SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint;
m_status.dwCheckPoint =
((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED)) ?
0 : dwCheckPoint++;
::SetServiceStatus(m_statusHandle, &m_status);
}
//*****************************************************************************
void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
{
if (schSCManager)
{
CloseServiceHandle(schSCManager);
schSCManager = NULL;
}
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
}
void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword)
{
printf("Try to install Win32Service (%s).\n", pszServiceName);
char szPath[MAX_PATH];
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
{
printf("GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
char SvcOpt[] = " --daemon";
strncat(szPath, SvcOpt, strlen(SvcOpt));
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL)
{
printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
// Install the service into SCM by calling CreateService
schService = CreateService(
schSCManager, // SCManager database
pszServiceName, // Name of service
pszDisplayName, // Name to display
SERVICE_QUERY_STATUS, // Desired access
SERVICE_WIN32_OWN_PROCESS, // Service type
dwStartType, // Service start type
SERVICE_ERROR_NORMAL, // Error control type
szPath, // Service's binary
NULL, // No load ordering group
NULL, // No tag identifier
pszDependencies, // Dependencies
pszAccount, // Service running account
pszPassword // Password of the account
);
if (schService == NULL)
{
printf("CreateService failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
printf("Win32Service is installed as %s.\n", pszServiceName);
// Centralized cleanup for all allocated resources.
FreeHandles(schSCManager, schService);
}
void UninstallService(PCSTR pszServiceName)
{
printf("Try to uninstall Win32Service (%s).\n", pszServiceName);
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
SERVICE_STATUS ssSvcStatus = {};
// Open the local default service control manager database
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (schSCManager == NULL)
{
printf("OpenSCManager failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
// Open the service with delete, stop, and query status permissions
schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
if (schService == NULL)
{
printf("OpenService failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
// Try to stop the service
if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
{
printf("Stopping %s.\n", pszServiceName);
Sleep(1000);
while (QueryServiceStatus(schService, &ssSvcStatus))
{
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
printf(".");
Sleep(1000);
}
else break;
}
if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
{
printf("\n%s is stopped.\n", pszServiceName);
}
else
{
printf("\n%s failed to stop.\n", pszServiceName);
}
}
// Now remove the service by calling DeleteService.
if (!DeleteService(schService))
{
printf("DeleteService failed w/err 0x%08lx\n", GetLastError());
FreeHandles(schSCManager, schService);
return;
}
printf("%s is removed.\n", pszServiceName);
// Centralized cleanup for all allocated resources.
FreeHandles(schSCManager, schService);
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifndef WIN_32_SERVICE_H__
#define WIN_32_SERVICE_H__
#include <thread>
#include <windows.h>
#ifdef _WIN32
// Internal name of the service
#define SERVICE_NAME "i2pdService"
// Displayed name of the service
#define SERVICE_DISPLAY_NAME "i2pd router service"
// Service start options.
#define SERVICE_START_TYPE SERVICE_DEMAND_START
// List of service dependencies - "dep1\0dep2\0\0"
#define SERVICE_DEPENDENCIES ""
// The name of the account under which the service should run
#define SERVICE_ACCOUNT "NT AUTHORITY\\LocalService"
// The password to the service account name
#define SERVICE_PASSWORD NULL
#endif
class I2PService
{
public:
I2PService(PSTR pszServiceName,
BOOL fCanStop = TRUE,
BOOL fCanShutdown = TRUE,
BOOL fCanPauseContinue = FALSE);
virtual ~I2PService(void);
static BOOL isService();
static BOOL Run(I2PService &service);
void Stop();
protected:
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
virtual void OnStop();
virtual void OnPause();
virtual void OnContinue();
virtual void OnShutdown();
void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode = NO_ERROR,
DWORD dwWaitHint = 0);
private:
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
void WorkerThread();
void Start(DWORD dwArgc, PSTR *pszArgv);
void Pause();
void Continue();
void Shutdown();
static I2PService* s_service;
PSTR m_name;
SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_statusHandle;
BOOL m_fStopping;
HANDLE m_hStoppedEvent;
std::thread* _worker;
};
void InstallService(
PCSTR pszServiceName,
PCSTR pszDisplayName,
DWORD dwStartType,
PCSTR pszDependencies,
PCSTR pszAccount,
PCSTR pszPassword
);
void UninstallService(PCSTR pszServiceName);
#endif // WIN_32_SERVICE_H__

View File

@@ -1,57 +0,0 @@
version: 2.36.0.{build}
pull_requests:
do_not_increment_build_number: true
branches:
only:
- openssl
skip_tags: true
os: Visual Studio 2015
shallow_clone: true
clone_depth: 1
# avoid building 32-bit if 64-bit failed already
matrix:
fast_finish: true
environment:
APPVEYOR_SAVE_CACHE_ON_ERROR: true
MSYS2_PATH_TYPE: inherit
CHERE_INVOKING: enabled_from_arguments
matrix:
- MSYSTEM: MINGW64
- MSYSTEM: MINGW32
cache:
- c:\msys64\var\cache\pacman\pkg\
install:
# install new signing keyring
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
- c:\msys64\usr\bin\bash -lc "curl -O https://mirror.selfnet.de/msys2/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
- c:\msys64\usr\bin\bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig"
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz"
# remove packages which can break build
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Rns gcc-fortran gcc mingw-w64-{i686,x86_64}-gcc-ada mingw-w64-{i686,x86_64}-gcc-objc"
# update runtime
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
# Kill bash before next try
- taskkill /T /F /IM bash.exe /IM gpg.exe /IM gpg-agent.exe | exit /B 0
# update packages and install required
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu $MINGW_PACKAGE_PREFIX-boost $MINGW_PACKAGE_PREFIX-miniupnpc"
build_script:
- c:\msys64\usr\bin\bash -lc "make USE_UPNP=yes DEBUG=no -j3"
# prepare archive for uploading
- set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
- echo This is development build, use it carefully! For running in portable mode, move all files from contrib directory here. > README.txt
- 7z a -tzip -mx9 -mmt i2pd-%APPVEYOR_BUILD_VERSION%-%APPVEYOR_REPO_COMMIT:~0,7%-mingw-win%MSYSTEM:~-2%.zip %FILELIST%
after_build:
- c:\msys64\usr\bin\bash -lc "pacman --noconfirm -Sc"
test: off
deploy: off
artifacts:
- path: i2pd-*.zip

3
build/.gitignore vendored
View File

@@ -3,6 +3,7 @@
/i2pd
/libi2pd.a
/libi2pdclient.a
/libi2pdlang.a
/cmake_install.cmake
/CMakeCache.txt
/CPackConfig.cmake
@@ -11,4 +12,4 @@
/arch.c
# windows build script
i2pd*.zip
build*.log
build*.log

View File

@@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 2.8.12)
# this addresses CMP0059 with CMake > 3.3 for PCH flags
cmake_policy(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.7)
cmake_policy(VERSION 3.7)
project("i2pd")
# for debugging
@@ -18,7 +17,6 @@ option(WITH_LIBRARY "Build library" ON)
option(WITH_BINARY "Build binary" ON)
option(WITH_STATIC "Static build" OFF)
option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_PCH "Use precompiled header" OFF)
option(WITH_MESHNET "Build for cjdns test network" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
@@ -27,102 +25,59 @@ option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "..")
#Handle paths nicely
include(GNUInstallDirs)
# 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_directories(${LIBI2PD_SRC_DIR})
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
include_directories(${LANG_SRC_DIR})
include_directories(${DAEMON_SRC_DIR})
set(LIBI2PD_SRC
"${LIBI2PD_SRC_DIR}/api.cpp"
"${LIBI2PD_SRC_DIR}/Base.cpp"
"${LIBI2PD_SRC_DIR}/Blinding.cpp"
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
"${LIBI2PD_SRC_DIR}/ChaCha20.cpp"
"${LIBI2PD_SRC_DIR}/Config.cpp"
"${LIBI2PD_SRC_DIR}/CPU.cpp"
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
"${LIBI2PD_SRC_DIR}/Datagram.cpp"
"${LIBI2PD_SRC_DIR}/Destination.cpp"
"${LIBI2PD_SRC_DIR}/ECIESX25519AEADRatchetSession.cpp"
"${LIBI2PD_SRC_DIR}/Ed25519.cpp"
"${LIBI2PD_SRC_DIR}/Elligator.cpp"
"${LIBI2PD_SRC_DIR}/Family.cpp"
"${LIBI2PD_SRC_DIR}/FS.cpp"
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
"${LIBI2PD_SRC_DIR}/Gost.cpp"
"${LIBI2PD_SRC_DIR}/Gzip.cpp"
"${LIBI2PD_SRC_DIR}/HTTP.cpp"
"${LIBI2PD_SRC_DIR}/I2NPProtocol.cpp"
"${LIBI2PD_SRC_DIR}/Identity.cpp"
"${LIBI2PD_SRC_DIR}/LeaseSet.cpp"
"${LIBI2PD_SRC_DIR}/Log.cpp"
"${LIBI2PD_SRC_DIR}/NetDb.cpp"
"${LIBI2PD_SRC_DIR}/NetDbRequests.cpp"
"${LIBI2PD_SRC_DIR}/NTCP2.cpp"
"${LIBI2PD_SRC_DIR}/Poly1305.cpp"
"${LIBI2PD_SRC_DIR}/Profiling.cpp"
"${LIBI2PD_SRC_DIR}/Reseed.cpp"
"${LIBI2PD_SRC_DIR}/RouterContext.cpp"
"${LIBI2PD_SRC_DIR}/RouterInfo.cpp"
"${LIBI2PD_SRC_DIR}/Signature.cpp"
"${LIBI2PD_SRC_DIR}/SSU.cpp"
"${LIBI2PD_SRC_DIR}/SSUData.cpp"
"${LIBI2PD_SRC_DIR}/SSUSession.cpp"
"${LIBI2PD_SRC_DIR}/Streaming.cpp"
"${LIBI2PD_SRC_DIR}/Timestamp.cpp"
"${LIBI2PD_SRC_DIR}/TransitTunnel.cpp"
"${LIBI2PD_SRC_DIR}/Transports.cpp"
"${LIBI2PD_SRC_DIR}/Tunnel.cpp"
"${LIBI2PD_SRC_DIR}/TunnelEndpoint.cpp"
"${LIBI2PD_SRC_DIR}/TunnelGateway.cpp"
"${LIBI2PD_SRC_DIR}/TunnelPool.cpp"
"${LIBI2PD_SRC_DIR}/TunnelConfig.cpp"
"${LIBI2PD_SRC_DIR}/util.cpp"
)
FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp)
add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "")
if(WITH_LIBRARY)
install(TARGETS libi2pd
EXPORT libi2pd
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
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()
set(CLIENT_SRC
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/BOB.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/ClientContext.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/MatchedDestination.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/I2PTunnel.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/I2PService.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/SAM.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/SOCKS.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/HTTPProxy.cpp"
"${LIBI2PD_CLIENT_SRC_DIR}/I2CP.cpp"
)
FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp)
add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
if(WITH_LIBRARY)
install(TARGETS libi2pdclient
EXPORT libi2pdclient
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Libraries)
endif()
FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp)
add_library(libi2pdlang ${LANG_SRC})
set_target_properties(libi2pdlang PROPERTIES PREFIX "")
if(WITH_LIBRARY)
install(TARGETS libi2pdlang
EXPORT libi2pdlang
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Libraries)
endif()
@@ -142,6 +97,10 @@ if(WITH_UPNP)
add_definitions(-DUSE_UPNP)
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.
@@ -243,21 +202,7 @@ else()
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
endif()
if(WITH_PCH)
include_directories(BEFORE ${CMAKE_BINARY_DIR})
add_library(stdafx STATIC "${LIBI2PD_SRC_DIR}/stdafx.cpp")
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
get_directory_property(DEFS DEFINITIONS)
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
add_custom_command(TARGET stdafx PRE_BUILD
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
)
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
target_link_libraries(libi2pd stdafx)
endif()
target_link_libraries(libi2pdclient libi2pd)
target_link_libraries(libi2pdclient libi2pd libi2pdlang)
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_INCLUDE_DIRS)
@@ -269,6 +214,10 @@ if(NOT DEFINED OPENSSL_INCLUDE_DIR)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
endif()
if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
endif()
if(WITH_UPNP)
find_package(MiniUPnPc REQUIRED)
if(NOT MINIUPNPC_FOUND)
@@ -292,9 +241,7 @@ if(WITH_MESHNET)
message(WARNING "This build will NOT work on mainline i2p")
endif()
if(NOT MSYS)
include(CheckAtomic)
endif()
include(CheckAtomic)
# show summary
message(STATUS "---------------------------------------")
@@ -311,14 +258,14 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
message(STATUS " BINARY : ${WITH_BINARY}")
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
message(STATUS " UPnP : ${WITH_UPNP}")
message(STATUS " PCH : ${WITH_PCH}")
message(STATUS " MESHNET : ${WITH_MESHNET}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------")
#Handle paths nicely
include(GNUInstallDirs)
if(WITH_MESHNET)
message(STATUS "WARNING: Using the MESHNET option will make it impossible to use the application with the main network!!!")
endif()
if(WITH_BINARY)
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
@@ -327,10 +274,6 @@ if(WITH_BINARY)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif()
if(WITH_PCH)
target_compile_options("${PROJECT_NAME}" PRIVATE -include libi2pd/stdafx.h)
endif()
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
endif()
@@ -351,7 +294,7 @@ if(WITH_BINARY)
endif()
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${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}")

View File

@@ -2,26 +2,25 @@
setlocal enableextensions enabledelayedexpansion
title Building i2pd
REM Copyright (c) 2013-2020, The PurpleI2P Project
REM Copyright (c) 2013-2022, The PurpleI2P Project
REM This file is part of Purple i2pd project and licensed under BSD3
REM See full license text in LICENSE file at top of project tree
REM To use that script, you must have installed in your MSYS installation these packages:
REM Base: git make zip
REM x86_64: mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc
REM i686: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc
REM UCRT64: mingw-w64-ucrt-x86_64-boost mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-gcc
REM MINGW32: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc
REM setting up variables for MSYS
REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\msys64 needed to edit)!
set "WD=C:\msys64\usr\bin\"
REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\msys64 needed to edit)
set MSYS2_PATH_TYPE=inherit
set CHERE_INVOKING=enabled_from_arguments
REM set MSYSTEM=MSYS
set MSYSTEM=MINGW32
set "WD=C:\msys64\usr\bin\"
set "xSH=%WD%bash -lc"
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d contrib/webconsole"
REM detecting number of processors
set /a threads=%NUMBER_OF_PROCESSORS%
@@ -34,38 +33,67 @@ del /S build_*.log >> nul 2>&1
echo Receiving latest commit and cleaning up...
%xSH% "git checkout contrib/* && git pull && make clean" > build\build.log 2>&1
echo.
REM set to variable current commit hash
FOR /F "usebackq" %%a IN (`%xSH% 'git describe --tags'`) DO (
for /F "usebackq" %%a in (`%xSH% "git describe --tags"`) DO (
set tag=%%a
)
REM set to variable latest released tag
for /F "usebackq" %%b in (`%xSH% "git describe --abbrev=0"`) DO (
set reltag=%%b
)
echo Preparing configuration files and README for packaging...
%xSH% "echo To use configs and certificates, move all files and certificates folder from contrib directory here. > README.txt" >> nul
REM converting configuration files to DOS format (usable in default notepad)
%xSH% "unix2dos contrib/i2pd.conf contrib/tunnels.conf contrib/tunnels.d/*" >> build\build.log 2>&1
REM converting configuration files to DOS format (make usable in Windows Notepad)
%xSH% "unix2dos contrib/i2pd.conf contrib/tunnels.conf contrib/tunnels.d/* contrib/webconsole/style.css" >> build\build.log 2>&1
REM Prepare binary signing command if signing key and password provided
if defined SIGNKEY (
if defined SIGNPASS (
echo Signing options found
for %%X in (signtool.exe) do (set xSIGNTOOL=%%~$PATH:X)
if not defined xSIGNTOOL (
if not defined SIGNTOOL (
echo Error: Can't find signtool. Please provide path to binary using SIGNTOOL variable.
exit /b 1
) else (
set "xSIGNTOOL=%SIGNTOOL%"
)
)
set "xSIGNOPTS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /f ^"%SIGNKEY%^" /p ^"%SIGNPASS%^""
)
)
REM starting building
set MSYSTEM=MINGW32
set bitness=32
call :BUILDING
set MSYSTEM=MINGW64
set MSYSTEM=UCRT64
set bitness=64
call :BUILDING
REM building for WinXP
set "WD=C:\msys64-xp\usr\bin\"
set MSYSTEM=MINGW32
set bitness=32
set "xSH=%WD%bash -lc"
call :BUILDING_XP
REM build for Windows XP
if exist C:\msys64-xp\ ( call :BUILDING_XP )
echo.
REM compile installer
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_TextVer="%tag%" /dI2Pd_Ver="%tag%.0" build\win_installer.iss >> build\build.log 2>&1
echo Building installer...
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_TextVer="%tag%" /dI2Pd_Ver="%reltag%.0" build\win_installer.iss >> build\build.log 2>&1
REM Sign binary
if defined xSIGNOPTS (
"%xSIGNTOOL%" %xSIGNOPTS% build\setup_i2pd_v%tag%.exe
)
%xSH% "git checkout contrib/*" >> build\build.log 2>&1
del README.txt i2pd_x32.exe i2pd_x64.exe i2pd_xp.exe >> nul
echo Build complete...
@@ -74,13 +102,42 @@ exit /b 0
:BUILDING
%xSH% "make clean" >> nul
echo Building i2pd %tag% for win%bitness%
%xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && cp i2pd.exe i2pd_x%bitness%.exe && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build\build_win%bitness%_%tag%.log 2>&1
echo Building i2pd %tag% for win%bitness%...
REM Build i2pd
%xSH% "make DEBUG=no USE_UPNP=yes -j%threads%" > build\build_win%bitness%_%tag%.log 2>&1
REM Sign binary
if defined xSIGNOPTS (
"%xSIGNTOOL%" %xSIGNOPTS% i2pd.exe
)
REM Copy binary for installer and create distribution archive
%xSH% "cp i2pd.exe i2pd_x%bitness%.exe && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST%" >> build\build_win%bitness%_%tag%.log 2>&1
REM Clean work directory
%xSH% "make clean" >> build\build_win%bitness%_%tag%.log 2>&1
goto EOF
:BUILDING_XP
%xSH% "make clean" >> nul
echo Building i2pd %tag% for winxp
%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads% && cp i2pd.exe i2pd_xp.exe && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST% && make clean" > build\build_winxp_%tag%.log 2>&1
set MSYSTEM=MINGW32
set bitness=32
set "WD=C:\msys64-xp\usr\bin\"
set "xSH=%WD%bash -lc"
:EOF
%xSH% "make clean" >> nul
echo Building i2pd %tag% for winxp...
%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads%" > build\build_winxp_%tag%.log 2>&1
REM Sign binary
if defined xSIGNOPTS (
"%xSIGNTOOL%" %xSIGNOPTS% i2pd.exe
)
REM Copy binary for installer and create distribution archive
%xSH% "cp i2pd.exe i2pd_xp.exe && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST%" >> build\build_winxp_%tag%.log 2>&1
REM Clean work directory
%xSH% "make clean" >> build\build_winxp_%tag%.log 2>&1
goto EOF
:EOF

View File

@@ -1,16 +1,30 @@
# Copyright (c) 2017-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
# Based on the Qt 5 processor detection code, so should be very accurate
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
# https://github.com/qt/qtbase/blob/dev/src/corelib/global/qprocessordetection.h
# Currently handles arm (v5, v6, v7, v8), x86 (32/64), ia64, mips (32/64, mipsel, mips64el) and ppc (32/64)
# Regarding POWER/PowerPC, just as is noted in the Qt source,
# "There are many more known variants/revisions that we do not handle/detect."
set(archdetect_c_code "
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)|| defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
#if defined(__ARM64_ARCH_8__) \\
|| defined(__aarch64__) \\
|| defined(__ARMv8__) \\
|| defined(__ARMv8_A__) \\
|| defined(_M_ARM64) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8)
#error cmake_ARCH arm64
#if defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\
|| defined(__ARM_ARCH_7S__) \\
|| defined(_ARM_ARCH_7) \\
|| defined(__CORE_CORTEXA__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
#error cmake_ARCH armv7
#elif defined(__ARM_ARCH_6__) \\
@@ -23,6 +37,7 @@ set(archdetect_c_code "
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
#error cmake_ARCH armv6
#elif defined(__ARM_ARCH_5TEJ__) \\
|| defined(__ARM_ARCH_5TE__) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
#error cmake_ARCH armv5
#else
@@ -34,6 +49,18 @@ set(archdetect_c_code "
#error cmake_ARCH x86_64
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
#error cmake_ARCH ia64
#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000)
#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
#if defined(__MIPSEL__)
#error cmake_ARCH mips64el
#else
#error cmake_ARCH mips64
#endif
#elif defined(__MIPSEL__)
#error cmake_ARCH mipsel
#else
#error cmake_ARCH mips
#endif
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|| defined(_M_MPPC) || defined(_M_PPC)
@@ -47,7 +74,7 @@ set(archdetect_c_code "
#error cmake_ARCH unknown
")
# Set ppc_support to TRUE before including this file or ppc and ppc64
# Set ppc_support to TRUE before including this file on ppc and ppc64
# will be treated as invalid architectures since they are no longer supported by Apple
function(target_architecture output_var)
@@ -67,12 +94,14 @@ function(target_architecture output_var)
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
set(osx_arch_ppc TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
elseif("${osx_arch}" STREQUAL "i386")
set(osx_arch_i386 TRUE)
elseif("${osx_arch}" STREQUAL "x86_64")
set(osx_arch_x86_64 TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
elseif("${osx_arch}" STREQUAL "arm64")
set(osx_arch_arm64 TRUE)
else()
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
endif()
@@ -83,6 +112,10 @@ function(target_architecture output_var)
list(APPEND ARCH ppc)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
endif()
if(osx_arch_i386)
list(APPEND ARCH i386)
endif()
@@ -91,8 +124,8 @@ function(target_architecture output_var)
list(APPEND ARCH x86_64)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
if(osx_arch_arm64)
list(APPEND ARCH arm64)
endif()
else()
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")

View File

@@ -1,34 +0,0 @@
Howto build & run
==================
**Build**
Assuming you're in the root directory of the anoncoin source code.
$ `cd build/docker`
$ `docker -t meeh/i2pd:latest .`
**Run**
To run either the local build, or if not found - fetched prebuild from hub.docker.io, run the following command.
$ `docker run --name anonnode -v /path/to/i2pd/datadir/on/host:/var/lib/i2pd -p 7070:7070 -p 4444:4444 -p 4447:4447 -p 7656:7656 -p 2827:2827 -p 7654:7654 -p 7650:7650 -d meeh/i2pd`
All the ports ( -p HOSTPORT:DOCKERPORT ) is optional. However the command above enable all features (Webconsole, HTTP Proxy, BOB, SAM, i2cp, etc)
The volume ( -v HOSTDIR:DOCKERDIR ) is also optional, but if you don't use it, your config, routerid and private keys will die along with the container.
**Options**
Options are set via docker environment variables. This can be set at run with -e parameters.
* **ENABLE_IPV6** - Enable IPv6 support. Any value can be used - it triggers as long as it's not empty.
* **LOGLEVEL** - Set the loglevel.
* **ENABLE_AUTH** - Enable auth for the webconsole. Username and password needs to be set manually in i2pd.conf cause security reasons.
**Logging**
Logging happens to STDOUT as the best practise with docker containers, since infrastructure systems like kubernetes with ELK integration can automatically forward the log to say, kibana or greylog without manual setup. :)

View File

@@ -1,11 +0,0 @@
FROM ubuntu
RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \
libboost-program-options-dev libboost-date-time-dev \
libssl-dev git build-essential
RUN git clone https://github.com/PurpleI2P/i2pd.git
WORKDIR /i2pd
RUN make
CMD ./i2pd

View File

@@ -1,2 +0,0 @@
i2pd:
build: .

View File

@@ -1,8 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_Publisher "PurpleI2P"
; Get application version from compiled binary
; Disabled to use definition from command line
;#define I2Pd_ver GetFileVersionString(AddBackslash(SourcePath) + "..\i2pd_x64.exe")
[Setup]
AppName={#I2Pd_AppName}
@@ -27,7 +24,7 @@ ExtraDiskSpaceRequired=15
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
AppVerName={#I2Pd_AppName}
AppCopyright=Copyright (c) 2013-2020, The PurpleI2P Project
AppCopyright=Copyright (c) 2013-2022, The PurpleI2P Project
AppPublisherURL=http://i2pd.website/
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
@@ -47,6 +44,7 @@ Source: ..\contrib\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyif
Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
Source: ..\contrib\webconsole\*; DestDir: {userappdata}\i2pd\webconsole; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
[Icons]
Name: {group}\I2Pd; Filename: {app}\i2pd.exe

View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFyzCCA7OgAwIBAgIRALWNWsnQ0Vmn/99iCNT7cdQwDQYJKoZIhvcNAQELBQAw
cTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGjAYBgNVBAMM
EWVjaGVsb24zQG1haWwuaTJwMB4XDTIxMTEyOTE5MzU1OVoXDTMxMTEyOTE5MzU1
OVowcTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwG
A1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGjAYBgNV
BAMMEWVjaGVsb24zQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEA3pccNiQWJUS1t3QHK7rBCNKAsM2dz4szN3+3SrDy1w+rOrK8Vt5aypPU
QYUQwG+odjEPacuoRtO/W14KJl5yAI3eQS+X/cYDXmxvfm4zx5JRumYptXwJD57G
rlPHnFvk8R+Hvh+/UyqgSAZ9ZaKjEzYK4AtbYEXtopaM4U2VYN8xKjvKyWlhPdxo
kI3//qcTlSqGHHeHrkItLG1LubM1EnPu+9zI2WN2zBBRcm8ZtWqHoqFJ1zgJr/49
nMK8Lnb3I54ctva8x5+gsSk4dbG/mMsOIZekFqYJJs3+u9w5fmOYI7v9GlQr7UhE
G3MwjJ5Cj1LmLVlz/4LApZrDSd2JvwIUdGL3UW8+blaTeCPKIRvmsTeRxo1gORMF
ZH0dg39722lK7ScwOlOUX9ggzRUlYCmvnjQJZGJEUoP68QxjlQfkXZyffmMfvm6K
V6mcZ5aHMGO1lYAl40kWNJ0jGpmxJqTDhNFDEKr0TlRGVxXGWzObEOrcJ8ysRMc1
x6oXQhh79HXZcKwhZaXLx23ZvVoTfhRm4JH0SSP6XqQm35j4NI1SllEsDns29wU3
Re4wOWJCCYlPG3CtY32CinwQRoVgtiJk18W8+Pxw7sBFq8sL5L0Z+5bB6nTkBfV6
7OrZGWL0i344zQE0e3yIsLih+5Wyqw6RSSMysenl3alnUB9EvE0CAwEAAaNeMFww
DgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAP
BgNVHRMBAf8EBTADAQH/MBoGA1UdDgQTBBFlY2hlbG9uM0BtYWlsLmkycDANBgkq
hkiG9w0BAQsFAAOCAgEAaUMnMYtNFBl9dFON6e4EjYo53Wknj61uIVO11dvLqjnh
7X6guPML+GgNZsPQGLu7Bqw4hVgy/cV5AlFc7SXOhzpaYo1ycpjg3Ws1VK2wrk7+
4bvUThNcS1KZVFDdRE62549rYNfYNfPxXvccOTW9meTCC1kLHerh65ySDr9J02O6
o5Mf685PgBasBH6dlosOLTtee2gRLNFcAluQYKerawS1gDys5239UNHPCqTgO+Od
FiKfl48OIOzPGLKEf4lXC+lkwZElewShrHhzd8aGueedTi0UHOtQuY7ocsofqXc8
OnyT/y2X6wn/YkzviKgfxYDSI7FJiUgXCPcT0jUNmuwR168yL5BfzoQmrCvlOOQg
P7ibdBJ6UkL8pRpv/SYpvaX/kf4agYtwh5IL9FzNCwNu54ZC6JilLUhYAU38Eolq
OZ/cGiMoSFQIeBPvB3cdsqEud9W4P+MqN5A76fMzdVV77lGsIS1eCGMceR3CjOiF
6SdAskcBZWhFiRNQweC0iv57/nPCeTCuNAqbZSHd7zC1AKhNmmsKSJUJQCGijcce
P8Gl0AFfZneN2bVEFvJ/zd71pD8ll1Gkju16bfdWn0V4NRaxFiXNr2bL+ah9blud
EXOomE3R6ow1QZk+Gnpy3wh9jfwlrJuFoANvHnv4WREbdjwr//71XjBri5p1wPE=
-----END CERTIFICATE-----

View File

@@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIESg3kkzANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls
LmkycDAeFw0xNDA3MzExNjQ3MDJaFw0yNDA3MzAxNjQ3MDJaMHAxCzAJBgNVBAYT
AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmcEgLwwhzLNe
XLOMSrhwB8hWpOhfjo4s6S/wjBtjjUc8nI3D0hSn3HY26p0rvcvNEWexPUpPULmC
exGkU463nu7PiFONiORI1eJAiUFHibRiaA7Wboyo38pO73KirwjG07Y+Ua0jp+HS
+4FQ/I/9H/bPplReTOU/6hmRbgQ69U8nE68HzZHQxP68yVJ2rPHSXMPhF4R1h0G1
1mCAT+TgTsnwHNGF77XHJnY4/M4e2cgycEZjZow36C3t2mNDVkMgF19QQeb9WmLR
zREn3nq9BJqHpUkn9yWw0kKXTZSds+7UxESfzf3BzK0+hky2fh5H+qbYAo2lz4yj
81MXTAu+4RRkg4DBLlF+2dkclhwQLxxzvkRC6tPkn5i33Yltg7EfzA9IoQ05potJ
I+iOcF+aStfFgFj9u3B5UkcF4P0cH1QD3c6BK4hIezQYqRoPly1gHqg+XdwjG/dr
4as7HA9FTz3p2E8nClpIC1x3hfgwAdfd29aeBxO1WW/z99iMF7TBAF+u5T86XEW1
WpknqCbTli36yJ8a5fPWxZHrryBRJT5yLxejjFeadtutBSwljiVFq+Y38VqwFivq
VLiBt7IxAsZ8iilgfnnnAvBH6chWfSKb4H7kB4TJvDiV96QmmvoEaWYNHZozMhyK
tO3b5w+xqbJXyCLA3Q75jD0km76hjcECAwEAAaMhMB8wHQYDVR0OBBYEFAHQcAam
QRS/EUhuCSr9pB4Ux0rYMA0GCSqGSIb3DQEBDQUAA4ICAQBq1+1QLmgLAjrTg3tb
4XKgAVICQRoBDNUEobQg3pYeUX9eFNya2RxNljuvYpwT80ilGMPOXcjddmr5ngiK
dbGRcuuJk9MPEHtPaPT3+JJlvKQ3B3g2wva2Wz2OAyLZUGQs389K4nTbwh4QF0n2
aHFL8BHiD62hiKnCoNaW4ZovUNNvOxo9lMyAiaFU2gqQNcdad8hP9EAllbvbxDx9
Tjww2UbwQUIHS9rna4Tlu+f0hDXTWIutc2A51W2fJCb7L3+lYO7Wv55ND/WtryLZ
XpMp27+MpuEnN3kQmz/l9R0hIJsWc/x9GQkjm5wEaIZEyTtenqwRKGmVCtAj0Pgv
jn1L3/lWmrNq+OZHb/QeyfKtA3nXfQKVmT98ewQiK/S5i1xIAXCJPytOD887b/o1
cdurTmCiZMwgiQ+HLJqCg3MDa5mvKqRkRdZXfE6aQWEcSbpAhpV15R17q7L+Fg0W
shLSNucxyGNU8PjiC/nOmqfqUiPiMltJjPmscxBLim8foyxjakC4+6N6m+Jzgznj
PocBehFAfKYj66XEwzIBN7Z2uuXoYH9YptkocFjTzvchcryVulDWZ4FWxreUMhpM
4oyjjhSB4tB9clXlwMqg577q3D6Ms0zLTqsztyPN3zr6jGev3jpVq7Q1GOlciHPv
JNJOWTH/Vas1W6XlwGcOOAARTQ==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFgTCCA2mgAwIBAgIETWAY1DANBgkqhkiG9w0BAQ0FADBxMQswCQYDVQQGEwJY
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEaMBgGA1UEAwwRaGlkdXNlcjBAbWFp
bC5pMnAwHhcNMjExMjEzMTU0MDI3WhcNMzExMjExMTU0MDI3WjBxMQswCQYDVQQG
EwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5v
bnltb3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEaMBgGA1UEAwwRaGlkdXNlcjBA
bWFpbC5pMnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXnjJ8UQ0f
lHHpfPMiHofBPSuL4sbOJY6fOXwPhSg/h6THh9DS/ZWmJXQ3qRD0glDVtv4/Dr/9
ldGQ5eltF9iCFXCQlMEy2HjQrBKq0nsl7RpYK12cyMaod0kkzCUk9ITLi9CmHM3Z
gQZcmG8TWjFEpDR+idx/QkQt2pcO4vzWlDit3Vh4ivnbX5jGQHbsVjQEMQWxr+pX
dsS+YQpjZ6RBmrooGTPO8QDOOeYLAn0lCjmffc/kzIH9E/p4/O0rOpyhVYbdxUD1
5wkqN9l4yrtxmORG/PudnRQQ0r4TUq8vsxfGY0Euo9IbhgXF2Parel1ZhDxB1WZV
VwWtgLIh9jGA1UMa8SYKnEfp8LWNZ3b3mUUnZb3kMrLk6jGYRWNsHmamhd4mC7AZ
qf/8lOkEIw3bPd3YguCDRVcLui5BwIEZmqXg8uoESxfO/sW3pBrN/8M7MkTex9kN
vjitGDDXvenK27qmNgZxbBlX72yTSfys7XTYTLnxZC8AwdAo2Wz9Z6HhGiPonf2h
vZkc9ZxuE0jFIrsbJra4X7iyjXgi4vV4ARNg/9Ft6F4/OIbECgeDcBQqq4TlT2bZ
EfWVrBbqXoj5vNsLigIkd+AyUNwPYEcB5IFSiiOh98pC7BH3pg0m8U5YBjxe1i+9
EQOOG0Qtx+JigXZHu6bGE0Twy9zy+UzoKQIDAQABoyEwHzAdBgNVHQ4EFgQUGK1b
0DkL6aLalcfBc/Uj/SF08C0wDQYJKoZIhvcNAQENBQADggIBAMpXM82bJDpH1TlH
TvhU3Z7nfZdvEhOQfujaFUYiuNripuEKcFGn948+DvAG0FUN+uNlJoqOVs8D7InD
gWlA9zpqw5Cl5Hij/Wns9QbXuAHJeA23fVUoaM2A6v9ifcIQ1A+rDuRQAo6/64KW
ChTg2e99RBpfGOyqgeh7tLLe0lPPekVpKHFuXabokaKRDuBcVHcUL4tWXe3dcyqa
Ej/PJrrS+nWL0EGZ4q80CEd2LPuDzPxNGCJt/R7ZfadENWajcgcXGceh1QBzozrB
SL/Ya6wF9SrsB7V/r5wX0LM4ZdDaLWbtmUe5Op0h/ZMH25Sa8xAXVz+O9L6sWSoO
FaiYTOvAiyyPz+nsxKa3xYryDHno7eKSt+hGOcaurhxbdZaEFY/CegEc73tCt9xK
e9qF8O/WkDLmixuErw3f5en4IfzGR7p3lJAwW/8WD8C6HS39h/eE7dVZNaWgtQnZ
SgGjgZMTJqTcQ3aZmfuCZefxGFok8w6AIkdbnd1pdMBRjYu8aXgl2hQSB9ZADDE9
R5d3rXi0PkSFLIvsNjVa5KXrZk/tB0Hpfmepq7CufBqjP/LG9TieRoXzLYUKFF74
QRwjP+y7AJ+VDUTpY1NV1P+k+2raubU2bOnLF3zL5DtyoyieGPhyeMMvp0fRIxdg
bSl5VHgPXHNM8mcnndMAuzvl7jEK
-----END CERTIFICATE-----

View File

@@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFfzCCA2egAwIBAgIEbNbRPjANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEZMBcGA1UEAwwQb3JpZ25hbEBtYWls
LmkycDAeFw0yMTA3MDYyMjExMDFaFw0zMTA3MDQyMjExMDFaMHAxCzAJBgNVBAYT
AlhYMQswCQYDVQQIDAJYWDELMAkGA1UEBwwCWFgxHjAcBgNVBAoMFUkyUCBBbm9u
eW1vdXMgTmV0d29yazEMMAoGA1UECwwDSTJQMRkwFwYDVQQDDBBvcmlnbmFsQG1h
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvNJz2KGuAkHP
tGFobfLvpybtxB50fkcEsTc9opmiy7wBKK9rSI01VS616IhABkWKZVfK2A9NqpGv
v/CyhTKoaeSNeXY7+zORUWgWK/zA9fA4GRZFqlW8j4tbompDwcLYNqRBCsn1C0OY
YA5JhXPBixMcnXl8N8x4sXhQ4l9R3+QrydhUHRvgDc8dOxRyIX7zuQAyf8tmA2Xo
xZLdvDcCJdLBIbFwxhIceIhgcOwaOx7oRkZDZdYcLJd3zjyPbu8JtOM2ZkwH7r+0
ro5PktuDp2LAS6SII5yYNcwcrvPZGPqhLdifIw1BrdTIb/rIkQZ5iXOOdyPmT7e8
IwAJcPFlfvrS4Vbi9oDqyx3aDUBoubgmFnO1TirL56ck83R/ubcKtdnyzAn5dp+f
ZNYW6/foSBpDDOCViylbFAR5H0HJEbBns7PZx6mGEEI4tUAJdNYl7Ly7Df60a9Rz
cD/gz08U9UwFXYKoT6roEjToADGAzb5MI4cVlAb2AmQaMNXNe04HcDL1bU50mkNU
amqPv8nxf72fBQCEmZz2G57T6QiYTtcCwiWS1QdWsuaOtCo9zO0MKcjzSdUxuxEc
dXhjQdNegsgg/Xk7bJ8lKOsACqMpFftdPmuyeZU2t+3RPuBpV/0j2qUfg/y6kb0z
CxAOYmlcL4kqw4VT+5V/EeZLIG0h9I0CAwEAAaMhMB8wHQYDVR0OBBYEFD/wJObg
CCDuhMJCVWTSTj+B3rsUMA0GCSqGSIb3DQEBDQUAA4ICAQC0PjsTSPWlGbLNeeI8
F0B5xAwXYJzZ7/LRxh8u42HDUqVIDjqkuls1l3v9D7htty2Gr3Ws2dcvcOr2KcOy
mEWg+jdP/N3vt9IkZeVS4YQoPgq6orn7lVkk00bcKb24f7ZnoQnnVV0/m42Y5P4j
LLh+8MBxsez9azXyZbDVEkgsMUAkdVO6KNz6scqz7wb8egV2GAMAp7cwChC6lanK
gv9ZyJhG/HdTv6VyuMZhJy6rX4geM97tm1iHu1VLsQcIzBKAdEvWJv8ofMeiyINe
hqAP9NYaeowKi975NOrmf+XZwxd0niApIohV684RCVUfL8H7HSPbdXhBJ/WslyDP
cTGhA2BLqEXZBn/nLQknlnl0SZTQxG2n4fEgD1E5YS/aoBrig/uXtWm2Zdf8U3mM
+bNXhbi9s7LneN2ye8LlNJBSRklNn/bNo8OmzLII1RQwf1+vaHT96lASbTVepMZ/
Y9VcC8fAmho/zfQEKueLEB03K+gr2dGD+1crmMtUBjWJ9vPjtooZArtkDbh+kVYA
cx4N4NXULRwxVWZe5wTQOqcZ3qSS1ClMwaziwychGaj8xRAirHMZnlPOZO1UK4+5
8F4RMJktyZjNgSLP76XPS4rJK5fobuPqFeA4OpDFn/5+/XeQFF6i6wntx1tzztzH
zc+BrVZOdcYPqu9iLXyRQ9JwwA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFxzCCA6+gAwIBAgIQfKAV7rmoWA8jWpLfMtDQqzANBgkqhkiG9w0BAQsFADBw
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ
cmFtYmxlckBtYWlsLmkycDAeFw0yMTExMDYwNzEwMzJaFw0zMTExMDYwNzEwMzJa
MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV
BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD
DBByYW1ibGVyQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
AgEAz4vQlIdjY56uqkFKWld9Oy3E8+06Ag9fUzBVleS2bdJfaFtmEa8xz6Pep7Bb
zJK0Q9t2CW7/xqIWuspWlYn5EYAS7BFiNOX70KX4PMpltj3C4Dpxpjll9LdydU2k
FquCflXNJESnBDdd0qDRMboMf4c9lTz0mTLwAtzInLwHGDrbxEiQ/YqPgPJreOXQ
anhjkpxJcgpLR+9od8EdLNKbShVWEeSBnYp0FcjnZKOb9KC2gjqP0sWdzlw3i1hh
CB38A7a03Q4yUcmxCw4ktM60d/2jCZ+G7KHwcbkfxDjl85r0UgEzgfF7LuIuxxmA
MNLH1eAACnLTl42O72EHdtD9VWWwZF2NuFgAzT3MEFnMKDk+OqZOeZQOEgkIfrNP
O5XYMYxHSWCf/dmSq36ZJwhC40k2S9ArS8BQNY8NvwZG5CSGDU52FKaHzFn6EwLE
4CpsrptUX2itXLaFUiNMw6I+eSgTO7x+gpahZVqpdRSQXmpE0xA5jP/DwPyt3ZVe
/4q4kn3imcSCxBP5NQHWfVszsruRkh9np4R0xVlT8UCwJmY8Yg8zwJG5UddTAck5
JavDsaXgWMwcZ/qQboZKlH/iAdQnbkte8Yd5GL5nmTeS+vwuluwmA/y9kUzSUhk+
86kA0eRJ1+e2HdA1/UOTRmyIoIeQ5/fhELMXzhksLcpMGTUCAwEAAaNdMFswDgYD
VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV
HRMBAf8EBTADAQH/MBkGA1UdDgQSBBByYW1ibGVyQG1haWwuaTJwMA0GCSqGSIb3
DQEBCwUAA4ICAQAxRdSTZGEblnNeVuRoEQq/a/6q4egFaOkzXCPKEnDzB5yvm83g
35ImquGFZkgaoc5qUAHVeBwOQrWgUI4xHPofnbM2VsgEUMz6h3ovobPNkN3+lRT5
30krd0y+A/Q895EHDu0lyf3BHMmtCWiKWQBttuc0dnmoLCRsQxgy+kYJCS/81jCM
4KNnyrtc6a/czqSq758CncjP2nErVucendsguQoA5JUw53YJ4FYHG/f9tYEkhm9C
D6u7L3vTUcMRUrRxSiJyNixH36nEwpM6DNHiPNc+CFKZ/Zx449R1GjcpDhTrXnWP
2H1r3cyKEM8a76VUEs2GQCaaglOR4N1goyqgYEjScf+/4VmARL3VUzfP8Oub70rM
t1fip5QD/4VDQuA/9C9g5Rr2nJ3K2jVnpSSKnBYFYf5z9RZdTOVXjXaEi72lWxpk
mjgK6c5EFOJxYoCaTbKX9Kz9ZIWVOVMrgHWwA/wDW+Qk5zgP9Ysau65xIp9P1RdB
qHgR5BcIrNky9RD8cIzxzMPCSMVgnf0eLFuHmG8uUl/xHHVRprf0pd7DYkQ44HWN
Z/g/gg3DaJdH7vvkShzgjt4iZrmOCHQIKkSGFRYZf0/Mpn6mgK9+grtO9osVgAQr
LBO+5LIxV/S5bcrzWQLOiMABTd2X/0PTOjuXpfinZ3rDSUiNFPq5kLLSlA==
-----END CERTIFICATE-----

View File

@@ -1,31 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFVDCCAzwCCQC2r1XWYtqtAzANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJY
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMRMwEQYDVQQKDApQdXJwbGUgSTJQ
MQ0wCwYDVQQLDARJMlBEMR8wHQYJKoZIhvcNAQkBFhBvcmlnbmFsQG1haWwuaTJw
MB4XDTE1MDIyMjEzNTgxOFoXDTI1MDIxOTEzNTgxOFowbDELMAkGA1UEBhMCWFgx
CzAJBgNVBAgMAlhYMQswCQYDVQQHDAJYWDETMBEGA1UECgwKUHVycGxlIEkyUDEN
MAsGA1UECwwESTJQRDEfMB0GCSqGSIb3DQEJARYQb3JpZ25hbEBtYWlsLmkycDCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALp3D/gdvFjrMm+IE8tHZCWE
hQ6Pp0CCgCGDBC3WQFLqR98bqVPl4UwRG/MKY/LY7Woai06JNmGcpfw0LMoNnHxT
bvKtDRe/8kQdhdLHhgIkWKSbMvTAl7uUdV6FzsPgDR0x7scoFVWEhkF0wfmzGF2V
yr/WCBQejFPu69z03m5tRQ8Xjp2txWV45RawUmFu50bgbZvLCSLfTkIvxmfJzgPN
pJ3sPa/g7TBZl2uEiAu4uaEKvTuuzStOWCGgFaHYFVlTfFXTvmhFMqHfaidtzrlu
H35WGrmIWTDl6uGPC5QkSppvkj73rDj5aEyPzWMz5DN3YeECoVSchN+OJJCM6m7+
rLFYXghVEp2h+T9O1GBRfcHlQ2E3CrWWvxhmK8dfteJmd501dyNX2paeuIg/aPFO
54/8m2r11uyF29hgY8VWLdXtqvwhKuK36PCzofEwDp9QQX8GRsEV4pZTrn4bDhGo
kb9BF7TZTqtL3uyiRmIyBXrNNiYlA1Xm4fyKRtxl0mrPaUXdgdnCt3KxOAJ8WM2B
7L/kk9U8C/nexHbMxIZfTap49XcUg5dxSO9kOBosIOcCUms8sAzBPDV2tWAByhYF
jI/Tutbd3F0+fvcmTcIFOlGbOxKgO2SfwXjv/44g/3LMK6IAMFB9UOc8KhnnJP0f
uAHvMXn1ahRs4pM1VizLAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAIOxdaXT+wfu
nv/+1hy5T4TlRMNNsuj79ROcy6Mp+JwMG50HjTc0qTlXh8C7nHybDJn4v7DA+Nyn
RxT0J5I+Gqn+Na9TaC9mLeX/lwe8/KomyhBWxjrsyWj1V6v/cLO924S2rtcfzMDm
l3SFh9YHM1KF/R9N1XYBwtMzr3bupWDnE1yycYp1F4sMLr5SMzMQ0svQpQEM2/y5
kly8+eUzryhm+ag9x1686uEG5gxhQ1eHQoZEaClHUOsV+28+d5If7cqcYx9Hf5Tt
CiVjJQzdxBF+6GeiJtKxnLtevqlkbyIJt6Cm9/7YIy/ovRGF2AKSYN6oCwmZQ6i1
8nRnFq5zE7O94m+GXconWZxy0wVqA6472HThMi7S+Tk/eLYen2ilGY+KCb9a0FH5
5MOuWSoJZ8/HfW2VeQmL8EjhWm5F2ybg28wgXK4BOGR3jQi03Fsc+AFidnWxSKo0
aiJoPgOsfyu8/fnCcAi07kSmjzUKIWskApgcpGQLNXHFK9mtg7+VA8esRnfLlKtP
tJf+nNAPY1sqHfGBzh7WWGWal5RGHF5nEm3ta3oiFF5sMKCJ6C87zVwFkEcRytGC
xOGmiG1O1RPrO5NG7rZUaQ4y1OKl2Y1H+nGONzZ3mvoAOvxEq6JtUnU2kZscpPlk
fpeOSDoGBYJGbIpzDreBDhxaZrwGq36k
-----END CERTIFICATE-----

View File

@@ -25,24 +25,25 @@ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
# 1. install deps, clone and build.
# 2. strip binaries.
# 3. Purge all dependencies and other unrelated packages, including build directory.
RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl git \
RUN apk update \
&& apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl miniupnpc-dev git \
&& mkdir -p /tmp/build \
&& cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \
&& cd i2pd \
&& if [ -n "${GIT_TAG}" ]; then git checkout tags/${GIT_TAG}; fi \
&& make \
&& make USE_UPNP=yes \
&& cp -R contrib/certificates /i2pd_certificates \
&& mkdir -p /usr/local/bin \
&& mv i2pd /usr/local/bin \
&& cd /usr/local/bin \
&& strip i2pd \
&& rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \
boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \
miniupnpc-dev boost-python3 python3 gdbm boost-unit_test_framework linux-headers boost-prg_exec_monitor \
boost-serialization boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre2 \
libtool g++ gcc
# 2. Adding required libraries to run i2pd to ensure it will run.
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl miniupnpc musl-utils libstdc++
COPY entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh

724
contrib/i18n/English.po Normal file
View File

@@ -0,0 +1,724 @@
# i2pd
# Copyright (C) 2021 PurpleI2P team
# This file is distributed under the same license as the i2pd package.
# R4SAS <r4sas@i2pmail.org>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: i2pd\n"
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
"POT-Creation-Date: 2021-08-06 17:12\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-KeywordsList: ;tr\n"
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
#: daemon/HTTPServer.cpp:177
msgid "day"
msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:181
msgid "hour"
msgid_plural "hours"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:185
msgid "minute"
msgid_plural "minutes"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:188
msgid "second"
msgid_plural "seconds"
msgstr[0] ""
msgstr[1] ""
#. tr: Kibibit
#: daemon/HTTPServer.cpp:196 daemon/HTTPServer.cpp:224
msgid "KiB"
msgstr ""
#. tr: Mebibit
#: daemon/HTTPServer.cpp:198
msgid "MiB"
msgstr ""
#. tr: Gibibit
#: daemon/HTTPServer.cpp:200
msgid "GiB"
msgstr ""
#: daemon/HTTPServer.cpp:217
msgid "building"
msgstr ""
#: daemon/HTTPServer.cpp:218
msgid "failed"
msgstr ""
#: daemon/HTTPServer.cpp:219
msgid "expiring"
msgstr ""
#: daemon/HTTPServer.cpp:220
msgid "established"
msgstr ""
#: daemon/HTTPServer.cpp:221
msgid "unknown"
msgstr ""
#: daemon/HTTPServer.cpp:223
msgid "exploratory"
msgstr ""
#: daemon/HTTPServer.cpp:259
msgid "<b>i2pd</b> webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:262
msgid "Main page"
msgstr ""
#: daemon/HTTPServer.cpp:263 daemon/HTTPServer.cpp:725
msgid "Router commands"
msgstr ""
#: daemon/HTTPServer.cpp:264 daemon/HTTPServer.cpp:448
#: daemon/HTTPServer.cpp:460
msgid "Local Destinations"
msgstr ""
#: daemon/HTTPServer.cpp:266 daemon/HTTPServer.cpp:418
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
#: daemon/HTTPServer.cpp:641 daemon/HTTPServer.cpp:684
#: daemon/HTTPServer.cpp:688
msgid "LeaseSets"
msgstr ""
#: daemon/HTTPServer.cpp:268 daemon/HTTPServer.cpp:694
msgid "Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:269 daemon/HTTPServer.cpp:425
#: daemon/HTTPServer.cpp:787 daemon/HTTPServer.cpp:803
msgid "Transit Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:270 daemon/HTTPServer.cpp:852
msgid "Transports"
msgstr ""
#: daemon/HTTPServer.cpp:271
msgid "I2P tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:914
#: daemon/HTTPServer.cpp:924
msgid "SAM sessions"
msgstr ""
#: daemon/HTTPServer.cpp:289 daemon/HTTPServer.cpp:1306
#: daemon/HTTPServer.cpp:1309 daemon/HTTPServer.cpp:1312
#: daemon/HTTPServer.cpp:1326 daemon/HTTPServer.cpp:1371
#: daemon/HTTPServer.cpp:1374 daemon/HTTPServer.cpp:1377
msgid "ERROR"
msgstr ""
#: daemon/HTTPServer.cpp:296
msgid "OK"
msgstr ""
#: daemon/HTTPServer.cpp:297
msgid "Testing"
msgstr ""
#: daemon/HTTPServer.cpp:298
msgid "Firewalled"
msgstr ""
#: daemon/HTTPServer.cpp:299 daemon/HTTPServer.cpp:320
#: daemon/HTTPServer.cpp:406
msgid "Unknown"
msgstr ""
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:435
#: daemon/HTTPServer.cpp:436 daemon/HTTPServer.cpp:982
#: daemon/HTTPServer.cpp:991
msgid "Proxy"
msgstr ""
#: daemon/HTTPServer.cpp:301
msgid "Mesh"
msgstr ""
#: daemon/HTTPServer.cpp:304
msgid "Error"
msgstr ""
#: daemon/HTTPServer.cpp:308
msgid "Clock skew"
msgstr ""
#: daemon/HTTPServer.cpp:311
msgid "Offline"
msgstr ""
#: daemon/HTTPServer.cpp:314
msgid "Symmetric NAT"
msgstr ""
#: daemon/HTTPServer.cpp:326
msgid "Uptime"
msgstr ""
#: daemon/HTTPServer.cpp:329
msgid "Network status"
msgstr ""
#: daemon/HTTPServer.cpp:334
msgid "Network status v6"
msgstr ""
#: daemon/HTTPServer.cpp:340 daemon/HTTPServer.cpp:347
msgid "Stopping in"
msgstr ""
#: daemon/HTTPServer.cpp:354
msgid "Family"
msgstr ""
#: daemon/HTTPServer.cpp:355
msgid "Tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:356
msgid "Received"
msgstr ""
#. tr: Kibibit/s
#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:361
#: daemon/HTTPServer.cpp:364
msgid "KiB/s"
msgstr ""
#: daemon/HTTPServer.cpp:359
msgid "Sent"
msgstr ""
#: daemon/HTTPServer.cpp:362
msgid "Transit"
msgstr ""
#: daemon/HTTPServer.cpp:365
msgid "Data path"
msgstr ""
#: daemon/HTTPServer.cpp:368
msgid "Hidden content. Press on text to see."
msgstr ""
#: daemon/HTTPServer.cpp:371
msgid "Router Ident"
msgstr ""
#: daemon/HTTPServer.cpp:373
msgid "Router Family"
msgstr ""
#: daemon/HTTPServer.cpp:374
msgid "Router Caps"
msgstr ""
#: daemon/HTTPServer.cpp:375
msgid "Version"
msgstr ""
#: daemon/HTTPServer.cpp:376
msgid "Our external address"
msgstr ""
#: daemon/HTTPServer.cpp:384
msgid "supported"
msgstr ""
#: daemon/HTTPServer.cpp:416
msgid "Routers"
msgstr ""
#: daemon/HTTPServer.cpp:417
msgid "Floodfills"
msgstr ""
#: daemon/HTTPServer.cpp:424 daemon/HTTPServer.cpp:968
msgid "Client Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:434
msgid "Services"
msgstr ""
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
msgid "Enabled"
msgstr ""
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
msgid "Disabled"
msgstr ""
#: daemon/HTTPServer.cpp:483
msgid "Encrypted B33 address"
msgstr ""
#: daemon/HTTPServer.cpp:492
msgid "Address registration line"
msgstr ""
#: daemon/HTTPServer.cpp:497
msgid "Domain"
msgstr ""
#: daemon/HTTPServer.cpp:498
msgid "Generate"
msgstr ""
#: daemon/HTTPServer.cpp:499
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:505
msgid "Address"
msgstr ""
#: daemon/HTTPServer.cpp:505
msgid "Type"
msgstr ""
#: daemon/HTTPServer.cpp:505
msgid "EncType"
msgstr ""
#: daemon/HTTPServer.cpp:515 daemon/HTTPServer.cpp:699
msgid "Inbound tunnels"
msgstr ""
#. tr: Milliseconds
#: daemon/HTTPServer.cpp:520 daemon/HTTPServer.cpp:530
#: daemon/HTTPServer.cpp:704 daemon/HTTPServer.cpp:714
msgid "ms"
msgstr ""
#: daemon/HTTPServer.cpp:525 daemon/HTTPServer.cpp:709
msgid "Outbound tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:537
msgid "Tags"
msgstr ""
#: daemon/HTTPServer.cpp:537
msgid "Incoming"
msgstr ""
#: daemon/HTTPServer.cpp:544 daemon/HTTPServer.cpp:547
msgid "Outgoing"
msgstr ""
#: daemon/HTTPServer.cpp:545 daemon/HTTPServer.cpp:561
msgid "Destination"
msgstr ""
#: daemon/HTTPServer.cpp:545
msgid "Amount"
msgstr ""
#: daemon/HTTPServer.cpp:552
msgid "Incoming Tags"
msgstr ""
#: daemon/HTTPServer.cpp:560 daemon/HTTPServer.cpp:563
msgid "Tags sessions"
msgstr ""
#: daemon/HTTPServer.cpp:561
msgid "Status"
msgstr ""
#: daemon/HTTPServer.cpp:570 daemon/HTTPServer.cpp:626
msgid "Local Destination"
msgstr ""
#: daemon/HTTPServer.cpp:580 daemon/HTTPServer.cpp:947
msgid "Streams"
msgstr ""
#: daemon/HTTPServer.cpp:602
msgid "Close stream"
msgstr ""
#: daemon/HTTPServer.cpp:631
msgid "I2CP session not found"
msgstr ""
#: daemon/HTTPServer.cpp:634
msgid "I2CP is not enabled"
msgstr ""
#: daemon/HTTPServer.cpp:660
msgid "Invalid"
msgstr ""
#: daemon/HTTPServer.cpp:663
msgid "Store type"
msgstr ""
#: daemon/HTTPServer.cpp:664
msgid "Expires"
msgstr ""
#: daemon/HTTPServer.cpp:669
msgid "Non Expired Leases"
msgstr ""
#: daemon/HTTPServer.cpp:672
msgid "Gateway"
msgstr ""
#: daemon/HTTPServer.cpp:673
msgid "TunnelID"
msgstr ""
#: daemon/HTTPServer.cpp:674
msgid "EndDate"
msgstr ""
#: daemon/HTTPServer.cpp:684
msgid "not floodfill"
msgstr ""
#: daemon/HTTPServer.cpp:695
msgid "Queue size"
msgstr ""
#: daemon/HTTPServer.cpp:726
msgid "Run peer test"
msgstr ""
#: daemon/HTTPServer.cpp:731
msgid "Decline transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:733
msgid "Accept transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:737 daemon/HTTPServer.cpp:742
msgid "Cancel graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:739 daemon/HTTPServer.cpp:744
msgid "Start graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:747
msgid "Force shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:748
msgid "Reload external CSS styles"
msgstr ""
#: daemon/HTTPServer.cpp:751
msgid ""
"<b>Note:</b> any action done here are not persistent and not changes your "
"config files."
msgstr ""
#: daemon/HTTPServer.cpp:753
msgid "Logging level"
msgstr ""
#: daemon/HTTPServer.cpp:761
msgid "Transit tunnels limit"
msgstr ""
#: daemon/HTTPServer.cpp:766 daemon/HTTPServer.cpp:778
msgid "Change"
msgstr ""
#: daemon/HTTPServer.cpp:770
msgid "Change language"
msgstr ""
#: daemon/HTTPServer.cpp:803
msgid "no transit tunnels currently built"
msgstr ""
#: daemon/HTTPServer.cpp:908 daemon/HTTPServer.cpp:931
msgid "SAM disabled"
msgstr ""
#: daemon/HTTPServer.cpp:924
msgid "no sessions currently running"
msgstr ""
#: daemon/HTTPServer.cpp:937
msgid "SAM session not found"
msgstr ""
#: daemon/HTTPServer.cpp:942
msgid "SAM Session"
msgstr ""
#: daemon/HTTPServer.cpp:999
msgid "Server Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:1015
msgid "Client Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1029
msgid "Server Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1227
msgid "Unknown page"
msgstr ""
#: daemon/HTTPServer.cpp:1246
msgid "Invalid token"
msgstr ""
#: daemon/HTTPServer.cpp:1304 daemon/HTTPServer.cpp:1361
#: daemon/HTTPServer.cpp:1401
msgid "SUCCESS"
msgstr ""
#: daemon/HTTPServer.cpp:1304
msgid "Stream closed"
msgstr ""
#: daemon/HTTPServer.cpp:1306
msgid "Stream not found or already was closed"
msgstr ""
#: daemon/HTTPServer.cpp:1309
msgid "Destination not found"
msgstr ""
#: daemon/HTTPServer.cpp:1312
msgid "StreamID can't be null"
msgstr ""
#: daemon/HTTPServer.cpp:1314 daemon/HTTPServer.cpp:1379
msgid "Return to destination page"
msgstr ""
#: daemon/HTTPServer.cpp:1315 daemon/HTTPServer.cpp:1328
#: daemon/HTTPServer.cpp:1403
msgid "You will be redirected in 5 seconds"
msgstr ""
#: daemon/HTTPServer.cpp:1326
msgid "Transit tunnels count must not exceed 65535"
msgstr ""
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1402
msgid "Back to commands list"
msgstr ""
#: daemon/HTTPServer.cpp:1363
msgid "Register at reg.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1364
msgid "Description"
msgstr ""
#: daemon/HTTPServer.cpp:1364
msgid "A bit information about service on domain"
msgstr ""
#: daemon/HTTPServer.cpp:1365
msgid "Submit"
msgstr ""
#: daemon/HTTPServer.cpp:1371
msgid "Domain can't end with .b32.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1374
msgid "Domain must end with .i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1377
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:1397
msgid "Unknown command"
msgstr ""
#: daemon/HTTPServer.cpp:1401
msgid "Command accepted"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:157
msgid "Proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:165
msgid "Proxy info"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:173
msgid "Proxy error: Host not found"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:174
msgid "Remote host not found in router's addressbook"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:175
msgid "You may try to find this host on jump services below"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:273 libi2pd_client/HTTPProxy.cpp:288
#: libi2pd_client/HTTPProxy.cpp:322 libi2pd_client/HTTPProxy.cpp:365
msgid "Invalid request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:273
msgid "Proxy unable to parse your request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:288
msgid "addresshelper is not supported"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:297 libi2pd_client/HTTPProxy.cpp:306
#: libi2pd_client/HTTPProxy.cpp:385
msgid "Host"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:297
msgid "added to router's addressbook from helper"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:298
msgid "Click here to proceed:"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:298 libi2pd_client/HTTPProxy.cpp:308
msgid "Continue"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:299 libi2pd_client/HTTPProxy.cpp:309
msgid "Addresshelper found"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:306
msgid "already in router's addressbook"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:307
msgid "Click here to update record:"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:322
msgid "invalid request uri"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:365
msgid "Can't detect destination host from request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:382 libi2pd_client/HTTPProxy.cpp:386
msgid "Outproxy failure"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:382
msgid "bad outproxy settings"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:385
msgid "not inside I2P network, but outproxy is not enabled"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:474
msgid "unknown outproxy url"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:480
msgid "cannot resolve upstream proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:488
msgid "hostname too long"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:515
msgid "cannot connect to upstream socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:521
msgid "Cannot negotiate with socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:563
msgid "CONNECT error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:563
msgid "Failed to Connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:574 libi2pd_client/HTTPProxy.cpp:600
msgid "socks proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:582
msgid "failed to send request to upstream"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:603
msgid "No Reply From socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:610
msgid "cannot connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:610
msgid "http out proxy not implemented"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:611
msgid "cannot connect to upstream http proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:644
msgid "Host is down"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:644
msgid ""
"Can't create connection to requested host, it may be down. Please try again "
"later."
msgstr ""

29
contrib/i18n/README.md Normal file
View File

@@ -0,0 +1,29 @@
`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\]\ \"(.*)\"\nmsgstr\[1\]\ \"(.*)\"\n(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
out: #{"$2", {"$3", "$4", "$6", "$8", "$10"}},\n
```
```
in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
out: {"$1", "$2"},\n
```
```
in: ^#[:.](.*)$\n
out: <to empty line>
```
```
in: \n\n
out: \n
```

View File

@@ -15,11 +15,16 @@
## Default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d
# tunnelsdir = /var/lib/i2pd/tunnels.d
## Path to certificates used for verifying .su3, families
## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates
# certsdir = /var/lib/i2pd/certificates
## Where to write pidfile (default: i2pd.pid, not used in Windows)
# pidfile = /run/i2pd.pid
## Logging configuration section
## By default logs go to stdout with level 'info' and higher
## For Windows OS by default logs go to file with level 'warn' and higher
##
## Logs destination (valid values: stdout, file, syslog)
## * stdout - print log entries to stdout
@@ -34,14 +39,30 @@
## Write full CLF-formatted date and time to log (default: write only time)
# logclftime = true
## Daemon mode. Router will go to background after start
## Daemon mode. Router will go to background after start. Ignored on Windows
# daemon = true
## Specify a family, router belongs to (default - none)
# family =
## External IP address to listen for connections
## Network interface to bind to
## Updates address4/6 options if they are not set
# ifname =
## You can specify different interfaces for IPv4 and IPv6
# ifname4 =
# ifname6 =
## Local address to bind transport sockets to
## Overrides host option if:
## For ipv4: if ipv4 = true and nat = false
## For ipv6: if 'host' is not set or ipv4 = true
# address4 =
# address6 =
## External IPv4 or IPv6 address to listen for connections
## By default i2pd sets IP automatically
## Sets published NTCP2v4/SSUv4 address to 'host' value if nat = true
## Sets published NTCP2v6/SSUv6 address to 'host' value if ipv4 = false
# host = 1.2.3.4
## Port to listen for connections
@@ -54,27 +75,15 @@ ipv4 = true
## Enable communication through ipv6
ipv6 = false
## Network interface to bind to
# ifname =
## You can specify different interfaces for IPv4 and IPv6
# ifname4 =
# ifname6 =
## Enable NTCP transport (default = true)
# ntcp = true
## If you run i2pd behind a proxy server, you can only use NTCP transport with ntcpproxy option
## Should be http://address:port or socks://address:port
# ntcpproxy = http://127.0.0.1:8118
## Enable SSU transport (default = true)
# ssu = true
## Should we assume we are behind NAT? (false only in MeshNet)
# nat = true
## Bandwidth configuration
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
## X - unlimited
## Default is X for floodfill, L for regular node
## 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
# bandwidth = L
## Max % of bandwidth limit for transit. 0-100. 100 by default
# share = 100
@@ -84,6 +93,7 @@ ipv6 = false
# notransit = true
## Router will be floodfill
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[http]
@@ -95,10 +105,14 @@ address = 127.0.0.1
port = 7070
## Path to web console, default "/"
# webroot = /
## Uncomment following lines to enable Web Console authentication
## Uncomment following lines to enable Web Console authentication
# auth = true
# user = i2pd
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, armenian, german, russian,
## turkmen, ukrainian and uzbek languages
# lang = english
[httpproxy]
## Uncomment and set to 'false' to disable HTTP Proxy
@@ -131,7 +145,7 @@ port = 4447
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
[sam]
## Uncomment and set to 'true' to enable SAM Bridge
## Comment or set to 'false' to disable SAM Bridge
enabled = true
## Address and port service will listen on
# address = 127.0.0.1
@@ -171,6 +185,13 @@ enabled = true
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
# name = I2Pd
[meshnets]
## Enable connectivity over the Yggdrasil network
# yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface
# yggaddress =
[reseed]
## Options for bootstrapping into I2P network, aka reseeding
## Enable or disable reseed data verification.
@@ -178,6 +199,8 @@ 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/
## Path to local reseed data file (.su3) for manual reseeding
# file = /path/to/i2pseeds.su3
## or HTTPS URL to reseed from
@@ -195,19 +218,15 @@ verify = true
## Default: reg.i2p at "mainline" I2P Network
# defaulturl = http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt
## Optional subscriptions URLs, separated by comma
# subscriptions = http://inr.i2p/export/alive-hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
[limits]
## Maximum active transit sessions (default:2500)
# transittunnels = 2500
## Limit number of open file descriptors (0 - use system limit)
## Limit number of open file descriptors (0 - use system limit)
# openfiles = 0
## Maximum size of corefile in Kb (0 - use system limit)
## Maximum size of corefile in Kb (0 - use system limit)
# coresize = 0
## Threshold to start probabalistic backoff with ntcp sessions (0 - use system limit)
# ntcpsoft = 0
## Maximum number of ntcp sessions (0 - use system limit)
# ntcphard = 0
[trust]
## Enable explicit trust options. false by default
@@ -215,13 +234,13 @@ verify = 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 =
# routers =
## Should we hide our router from other routers? false by default
# hidden = true
[exploratory]
## Exploratory tunnels settings with default values
# inbound.length = 2
# inbound.length = 2
# inbound.quantity = 3
# outbound.length = 2
# outbound.quantity = 3
@@ -229,6 +248,8 @@ verify = true
[persist]
## Save peer profiles on disk (default: true)
# profiles = true
## Save full addresses on disk (default: true)
# addressbook = true
[cpuext]
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)

View File

@@ -17,7 +17,12 @@ PIDFile=/run/i2pd/i2pd.pid
### Uncomment, if auto restart needed
#Restart=on-failure
KillSignal=SIGQUIT
# Use SIGTERM to stop i2pd immediately.
# Some cleanup processes can delay stopping, so we set 30 seconds timeout and then SIGKILL i2pd.
KillSignal=SIGTERM
TimeoutStopSec=30s
SendSIGKILL=yes
# If you have the patience waiting 10 min on restarting/stopping it, uncomment this.
# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die.
#KillSignal=SIGINT

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.36.0
Version: 2.41.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@@ -32,7 +32,7 @@ Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
C++ implementation of I2P.
%prep
%setup -q
%setup -q -n i2pd-openssl
%build
@@ -56,9 +56,14 @@ cd build
%endif
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia} > 7
pushd build
@@ -77,9 +82,13 @@ popd
%install
pushd build
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia}
pushd build
@@ -90,14 +99,14 @@ chrpath -d i2pd
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
%{__cp} -r %{_builddir}/i2pd-openssl/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
%{__cp} -r %{_builddir}/i2pd-openssl/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
@@ -137,6 +146,26 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0
- fixed build on Fedora Copr over openssl trunk code
* Mon Nov 29 2021 orignal <i2porignal@yandex.ru> - 2.40.0
- update to 2.40.0
* Tue Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
- changed if statements to cover fedora 35
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
- update to 2.39.0
- fixed build on fedora 36
* Mon May 17 2021 orignal <i2porignal@yandex.ru> - 2.38.0
- update to 2.38.0
* Mon Mar 15 2021 orignal <i2porignal@yandex.ru> - 2.37.0
- update to 2.37.0
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
- update to 2.36.0

View File

@@ -1,5 +1,5 @@
Name: i2pd
Version: 2.36.0
Version: 2.41.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -54,9 +54,13 @@ cd build
%endif
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia} > 7
pushd build
@@ -75,9 +79,13 @@ popd
%install
pushd build
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia}
pushd build
@@ -135,6 +143,25 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0
* Mon Nov 29 2021 orignal <i2porignal@yandex.ru> - 2.40.0
- update to 2.40.0
* Tue Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
- changed if statements to cover fedora 35
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
- update to 2.39.0
- fixed build on fedora 36
* Mon May 17 2021 orignal <i2porignal@yandex.ru> - 2.38.0
- update to 2.38.0
* Mon Mar 15 2021 orignal <i2porignal@yandex.ru> - 2.37.0
- update to 2.37.0
* Mon Feb 15 2021 orignal <i2porignal@yandex.ru> - 2.36.0
- update to 2.36.0

View File

@@ -1,16 +1,16 @@
[IRC-IRC2P]
[IRC-ILITA]
type = client
address = 127.0.0.1
port = 6668
destination = irc.postman.i2p
destination = irc.ilita.i2p
destinationport = 6667
keys = irc-keys.dat
#[IRC-ILITA]
#[IRC-IRC2P]
#type = client
#address = 127.0.0.1
#port = 6669
#destination = irc.ilita.i2p
#destination = irc.postman.i2p
#destinationport = 6667
#keys = irc-keys.dat

View File

@@ -0,0 +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;
}
}

View File

@@ -32,6 +32,7 @@
#include "UPnP.h"
#include "Timestamp.h"
#include "util.h"
#include "I18N.h"
namespace i2p
{
@@ -93,6 +94,11 @@ namespace util
i2p::config::GetOption("daemon", isDaemon);
std::string certsdir; i2p::config::GetOption("certsdir", certsdir);
i2p::fs::SetCertsDir(certsdir);
certsdir = i2p::fs::GetCertsDir();
std::string logs = ""; i2p::config::GetOption("log", logs);
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
@@ -102,30 +108,36 @@ namespace util
if (logclftime)
i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
#ifdef WIN32_APP
// Win32 app with GUI supports only logging to file
logs = "file";
#else
if (isDaemon && (logs == "" || logs == "stdout"))
logs = "file";
#endif
i2p::log::Logger().SetLogLevel(loglevel);
if (logstream) {
LogPrint(eLogInfo, "Log: will send messages to std::ostream");
LogPrint(eLogInfo, "Log: Sending messages to std::ostream");
i2p::log::Logger().SendTo (logstream);
} else if (logs == "file") {
if (logfile == "")
logfile = i2p::fs::DataDirPath("i2pd.log");
LogPrint(eLogInfo, "Log: will send messages to ", logfile);
LogPrint(eLogInfo, "Log: Sending messages to ", logfile);
i2p::log::Logger().SendTo (logfile);
#ifndef _WIN32
} else if (logs == "syslog") {
LogPrint(eLogInfo, "Log: will send messages to syslog");
LogPrint(eLogInfo, "Log: Sending messages to syslog");
i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
#endif
} else {
// use stdout -- default
}
LogPrint(eLogInfo, "i2pd v", VERSION, " starting");
LogPrint(eLogDebug, "FS: main config file: ", config);
LogPrint(eLogDebug, "FS: data directory: ", datadir);
LogPrint(eLogNone, "i2pd v", VERSION, " (", I2P_VERSION, ") starting...");
LogPrint(eLogDebug, "FS: Main config file: ", config);
LogPrint(eLogDebug, "FS: Data directory: ", datadir);
LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir);
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
@@ -137,13 +149,32 @@ namespace util
i2p::context.SetNetID (netID);
i2p::context.Init ();
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
#ifdef MESHNET
// manual override for meshnet
ipv4 = false;
ipv6 = true;
#endif
// ifname -> address
std::string ifname; i2p::config::GetOption("ifname", ifname);
if (ipv4 && i2p::config::IsDefault ("address4"))
{
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
if (!ifname4.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
else if (!ifname.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
}
if (ipv6 && i2p::config::IsDefault ("address6"))
{
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
if (!ifname6.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
else if (!ifname.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
}
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
boost::asio::ip::address_v6 yggaddr;
if (ygg)
@@ -173,7 +204,7 @@ namespace util
uint16_t port; i2p::config::GetOption("port", port);
if (!i2p::config::IsDefault("port"))
{
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
LogPrint(eLogInfo, "Daemon: Accepting incoming connections at port ", port);
i2p::context.UpdatePort (port);
}
i2p::context.SetSupportsV6 (ipv6);
@@ -186,10 +217,15 @@ namespace util
{
bool published; i2p::config::GetOption("ntcp2.published", published);
if (published)
{
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
if (!ntcp2proxy.empty ()) published = false;
}
if (published)
{
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
if (!ntcp2port) ntcp2port = port; // use standard port
i2p::context.PublishNTCP2Address (ntcp2port, true); // publish
i2p::context.PublishNTCP2Address (ntcp2port, true, ipv4, ipv6, false); // publish
if (ipv6)
{
std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
@@ -199,15 +235,16 @@ namespace util
}
}
else
i2p::context.PublishNTCP2Address (port, false); // unpublish
i2p::context.PublishNTCP2Address (port, false, ipv4, ipv6, false); // unpublish
}
if (ygg)
{
if (!ntcp2)
i2p::context.PublishNTCP2Address (port, true);
i2p::context.PublishNTCP2Address (port, true, false, false, true);
i2p::context.UpdateNTCP2V6Address (yggaddr);
}
if (!ipv4 && !ipv6)
i2p::context.SetStatus (eRouterStatusMesh);
}
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
@@ -215,7 +252,7 @@ namespace util
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) {
LogPrint(eLogInfo, "Daemon: router will be floodfill");
LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
i2p::context.SetFloodfill (true);
}
else
@@ -230,7 +267,7 @@ namespace util
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
{
i2p::context.SetBandwidth (bandwidth[0]);
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
}
else
{
@@ -238,19 +275,19 @@ namespace util
if (value > 0)
{
i2p::context.SetBandwidth (value);
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
}
else
{
LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'");
LogPrint(eLogInfo, "Daemon: Unexpected bandwidth ", bandwidth, ". Set to 'low'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
}
}
}
else if (isFloodfill)
{
LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1);
LogPrint(eLogInfo, "Daemon: Floodfill bandwidth set to 'extra'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2);
}
else
{
@@ -264,12 +301,12 @@ namespace util
std::string family; i2p::config::GetOption("family", family);
i2p::context.SetFamily (family);
if (family.length () > 0)
LogPrint(eLogInfo, "Daemon: family set to ", family);
LogPrint(eLogInfo, "Daemon: Router family set to ", family);
bool trust; i2p::config::GetOption("trust.enabled", trust);
if (trust)
{
LogPrint(eLogInfo, "Daemon: explicit trust enabled");
LogPrint(eLogInfo, "Daemon: Explicit trust enabled");
std::string fam; i2p::config::GetOption("trust.family", fam);
std::string routers; i2p::config::GetOption("trust.routers", routers);
bool restricted = false;
@@ -299,27 +336,31 @@ namespace util
pos = comma + 1;
}
while (comma != std::string::npos);
LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers");
LogPrint(eLogInfo, "Daemon: Setting restricted routes to use ", idents.size(), " trusted routers");
i2p::transport::transports.RestrictRoutesToRouters(idents);
restricted = idents.size() > 0;
}
if(!restricted)
LogPrint(eLogError, "Daemon: no trusted routers of families specified");
LogPrint(eLogError, "Daemon: No trusted routers of families specified");
}
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
if (hidden)
{
LogPrint(eLogInfo, "Daemon: using hidden mode");
LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
i2p::data::netdb.SetHidden(true);
}
std::string httpLang; i2p::config::GetOption("http.lang", httpLang);
i2p::i18n::SetLanguage(httpLang);
return true;
}
bool Daemon_Singleton::start()
{
i2p::log::Logger().Start();
LogPrint(eLogInfo, "Daemon: starting NetDB");
LogPrint(eLogInfo, "Daemon: Starting NetDB");
i2p::data::netdb.Start();
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
@@ -338,17 +379,17 @@ namespace util
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu; i2p::config::GetOption("ssu", ssu);
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
LogPrint(eLogInfo, "Daemon: Starting Transports");
if(!ssu) LogPrint(eLogInfo, "Daemon: SSU disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2 || i2p::context.SupportsMesh (), ssu);
i2p::transport::transports.Start(ntcp2, ssu);
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started");
else
{
LogPrint(eLogError, "Daemon: failed to start Transports");
LogPrint(eLogError, "Daemon: Failed to start Transports");
/** shut down netdb right away */
i2p::transport::transports.Stop();
i2p::data::netdb.Stop();
@@ -359,7 +400,7 @@ namespace util
if (http) {
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
LogPrint(eLogInfo, "Daemon: Starting Webconsole at ", httpAddr, ":", httpPort);
try
{
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
@@ -367,16 +408,16 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
LogPrint (eLogError, "Daemon: Failed to start Webconsole: ", ex.what ());
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
}
}
LogPrint(eLogInfo, "Daemon: starting Tunnels");
LogPrint(eLogInfo, "Daemon: Starting Tunnels");
i2p::tunnel::tunnels.Start();
LogPrint(eLogInfo, "Daemon: starting Client");
LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start ();
// I2P Control Protocol
@@ -384,7 +425,7 @@ namespace util
if (i2pcontrol) {
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
LogPrint(eLogInfo, "Daemon: Starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
try
{
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
@@ -392,7 +433,7 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
LogPrint (eLogError, "Daemon: Failed to start I2PControl: ", ex.what ());
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
}
}
@@ -401,10 +442,10 @@ namespace util
bool Daemon_Singleton::stop()
{
LogPrint(eLogInfo, "Daemon: shutting down");
LogPrint(eLogInfo, "Daemon: stopping Client");
LogPrint(eLogInfo, "Daemon: Shutting down");
LogPrint(eLogInfo, "Daemon: Stopping Client");
i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
i2p::tunnel::tunnels.Stop();
if (d.UPnP)
@@ -419,18 +460,18 @@ namespace util
d.m_NTPSync = nullptr;
}
LogPrint(eLogInfo, "Daemon: stopping Transports");
LogPrint(eLogInfo, "Daemon: Stopping Transports");
i2p::transport::transports.Stop();
LogPrint(eLogInfo, "Daemon: stopping NetDB");
LogPrint(eLogInfo, "Daemon: Stopping NetDB");
i2p::data::netdb.Stop();
if (d.httpServer) {
LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
LogPrint(eLogInfo, "Daemon: Stopping HTTP Server");
d.httpServer->Stop();
d.httpServer = nullptr;
}
if (d.m_I2PControlService)
{
LogPrint(eLogInfo, "Daemon: stopping I2PControl");
LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
d.m_I2PControlService->Stop ();
d.m_I2PControlService = nullptr;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2013-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
*/
#ifndef HTTP_SERVER_RESOURCES_H__
#define HTTP_SERVER_RESOURCES_H__
namespace i2p
{
namespace http
{
const std::string itoopieFavicon =
"data:image/png;base64,"
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACx"
"jwv8YQUAAAAJcEhZcwAALiIAAC4iAari3ZIAAAAHdElNRQfgCQsUNSZrkhi1AAAAGXRFWHRTb2Z0"
"d2FyZQBwYWludC5uZXQgNC4wLjEyQwRr7AAAAoJJREFUOE9jwAUqi4Q1oEwwcDTV1+5sETaBclGB"
"vb09C5QJB6kWpvFQJoOCeLC5kmjEHCgXE2SlyETLi3h6QrkM4VL+ssWSCZUgtopITLKqaOotRTEn"
"cbAkLqAkGtOqLBLVAWLXyWSVFkkmRiqLxuaqiWb/VBYJMAYrwgckJY25VEUzniqKhjU2y+RtCRSP"
"6lUXy/1jIBV5tlYxZUaFVMq2NInwIi9hO8fSfOEAqDZUoCwal6MulvOvyS7gi69K4j9zxZT/m0ps"
"/28ptvvvquXXryIa7QYMMdTwqi0WNtVi0GIDseXl7TnUxFKfnGlxAGp0+D8j2eH/8Ub7/9e7nf7X"
"+Af/B7rwt6pI0h0l0WhQADOC9DBkhSirpImHNVZKp24ukkyoshGLnN8d5fA/y13t/44Kq/8hlnL/"
"z7fZ/58f6vcxSNpbVUVFhV1RLNBVTsQzVYZPSwhsCAhkiIfpNMrkbO6TLf071Sfk/5ZSi/+7q6z/"
"P5ns+v9mj/P/CpuI/20y+aeNGYxZoVoYGmsF3aFMBAAZlCwftnF9ke3//bU2//fXWP8/UGv731Am"
"+V+DdNblSqnUYqhSTKAiYSOqJBrVqiaa+S3UNPr/gmyH/xuKXf63hnn/B8bIP0UxHfEyyeSNQKVM"
"EB1AEB2twhcTLp+gIBJUoyKasEpVJHmqskh8qryovUG/ffCHHRU2q/Tk/YuB6eGPsbExa7ZkpLu1"
"oLEcVDtuUCgV1w60rQzElpRUE1EVSX0BYidHiInXF4nagNhYQW60EF+ApH1ktni0A1SIITSUgVlZ"
"JHYnlIsfzJjIp9xZKswL5YKBHL+coKJoRDaUSzoozxHVrygQU4JykQADAwAT5b1NHtwZugAAAABJ"
"RU5ErkJggg==";
// bundled style sheet
const std::string internalCSS =
"<style>\r\n"
":root { --main-bg-color: #fafafa; --main-text-color: #103456; --main-link-color: #894c84; --main-link-hover-color: #fafafa; }\r\n"
"@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.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"
".menu { display: block; float: left; overflow: hidden; padding: 4px; max-width: 12em; white-space: nowrap; text-overflow: ellipsis ;}\r\n"
".listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
".tableitem { font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
".content { float: left; font-size: 1em; margin-left: 2em; padding: 4px; max-width: 50em; overflow: auto; }\r\n"
".tunnel.established { color: #56B734; }\r\n"
".tunnel.expiring { color: #D3AE3F; }\r\n"
".tunnel.failed { color: #D33F3F; }\r\n"
".tunnel.building { color: #434343; }\r\n"
"caption { font-size: 1.5em; text-align: center; color: var(--main-link-color); }\r\n"
"table { display: table; border-collapse: collapse; text-align: center; }\r\n"
"table.extaddr { text-align: left; }\r\n"
"table.services { width: 100%; }\r\n"
"textarea { background-color: var(--main-bg-color); color: var(--main-text-color); word-break: break-all; }\r\n"
".streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis; }\r\n"
".slide div.slidecontent, .slide [type=\"checkbox\"] { display: none; }\r\n"
".slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n"
".disabled { color: #D33F3F; }\r\n"
".enabled { color: #56B734; }\r\n"
"button[type=submit] { background-color: transparent; color: var(--main-link-color); text-decoration: none;\r\n"
" padding: 5px; border: 1px solid var(--main-link-color); font-size: 14px; }\r\n"
"input, select, select option { background-color: var(--main-bg-color); color: var(--main-link-color); padding: 5px;\r\n"
" border: 1px solid var(--main-link-color); font-size: 14px; }\r\n"
"input:focus, select:focus, select option:focus { outline: none; }\r\n"
"input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; }\r\n"
"@media screen and (max-width: 1150px) { /* adaptive style */\r\n"
" .wrapper { max-width: 58em; }\r\n"
" .content { max-width: 40em; }\r\n"
"}\r\n"
"@media screen and (max-width: 980px) { body { font: 100%/1.2em sans-serif; padding: 1.2em 0 0 0; }\r\n"
" .menu { width: 100%; max-width: unset; display: block; float: none; position: unset; font-size: 16px; text-align: center; }\r\n"
" .menu a, .commands a { display: inline-block; padding: 4px; }\r\n"
" .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%; text-align: center; }\r\n"
" a, .slide label { display: block; }\r\n"
" .header { margin: unset; font-size: 1.5em; }\r\n"
" small { display: block; }\r\n"
" a.button { appearance: button; text-decoration: none; margin-top: 10px; padding: 6px; border: 2px solid var(--main-link-color);\r\n"
" border-radius: 5px; width: -webkit-fill-available; }\r\n"
" input, select { width: 35%; text-align: center; padding: 5px; border: 2px solid var(--main-link-color); border-radius: 5px; font-size: 18px; }\r\n"
" table.extaddr { margin: auto; text-align: unset; }\r\n"
" textarea { width: -webkit-fill-available; height: auto; padding: 5px; border: 2px solid var(--main-link-color);\r\n"
" border-radius: 5px; font-size: 12px; }\r\n"
" button[type=submit] { padding: 5px 15px; background: transparent; border: 2px solid var(--main-link-color); cursor: pointer;\r\n"
" border-radius: 5px; position: relative; height: 36px; display: -webkit-inline-box; margin-top: 10px; }\r\n"
"}\r\n"
"</style>\r\n";
// for external style sheet
std::string externalCSS;
} // http
} // i2p
#endif /* HTTP_SERVER_RESOURCES_H__ */

View File

@@ -1,7 +1,19 @@
/*
* Copyright (c) 2013-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
*/
#include <stdio.h>
#include <sstream>
#include <openssl/x509.h>
#include <openssl/pem.h>
// Use global placeholders from boost introduced when local_time.hpp is loaded
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/lexical_cast.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
@@ -44,10 +56,10 @@ namespace client
if (i2pcp_key.at(0) != '/')
i2pcp_key = i2p::fs::DataDirPath(i2pcp_key);
if (!i2p::fs::Exists (i2pcp_crt) || !i2p::fs::Exists (i2pcp_key)) {
LogPrint (eLogInfo, "I2PControl: creating new certificate for control connection");
LogPrint (eLogInfo, "I2PControl: Creating new certificate for control connection");
CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str());
} else {
LogPrint(eLogDebug, "I2PControl: using cert from ", i2pcp_crt);
LogPrint(eLogDebug, "I2PControl: Using cert from ", i2pcp_crt);
}
m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use);
m_SSLContext.use_certificate_file (i2pcp_crt, boost::asio::ssl::context::pem);
@@ -138,7 +150,7 @@ namespace client
try {
m_Service.run ();
} catch (std::exception& ex) {
LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ());
LogPrint (eLogError, "I2PControl: Runtime exception: ", ex.what ());
}
}
}
@@ -156,10 +168,10 @@ namespace client
Accept ();
if (ecode) {
LogPrint (eLogError, "I2PControl: accept error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
return;
}
LogPrint (eLogDebug, "I2PControl: new request from ", socket->lowest_layer ().remote_endpoint ());
LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ());
Handshake (socket);
}
@@ -172,7 +184,7 @@ namespace client
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
{
if (ecode) {
LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Handshake error: ", ecode.message ());
return;
}
//std::this_thread::sleep_for (std::chrono::milliseconds(5));
@@ -198,7 +210,7 @@ namespace client
{
if (ecode)
{
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Read error: ", ecode.message ());
return;
}
else
@@ -221,7 +233,7 @@ namespace client
}
if (ss.eof ())
{
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected");
LogPrint (eLogError, "I2PControl: Malformed request, HTTP header expected");
return; // TODO:
}
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
@@ -246,7 +258,7 @@ namespace client
}
else
{
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
LogPrint (eLogWarning, "I2PControl: Unknown method ", method);
response << "{\"id\":null,\"error\":";
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
response << "\"jsonrpc\":\"2.0\"}";
@@ -255,7 +267,7 @@ namespace client
}
catch (std::exception& ex)
{
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
LogPrint (eLogError, "I2PControl: Exception when handle request: ", ex.what ());
std::ostringstream response;
response << "{\"id\":null,\"error\":";
response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},";
@@ -264,7 +276,7 @@ namespace client
}
catch (...)
{
LogPrint (eLogError, "I2PControl: handle request unknown exception");
LogPrint (eLogError, "I2PControl: Handle request unknown exception");
}
}
}
@@ -274,11 +286,16 @@ namespace client
ss << "\"" << name << "\":" << value;
}
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
{
ss << "\"" << name << "\":";
if (value.length () > 0)
ss << "\"" << value << "\"";
{
if (quotes)
ss << "\"" << value << "\"";
else
ss << value;
}
else
ss << "null";
}
@@ -325,7 +342,7 @@ namespace client
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
{
if (ecode) {
LogPrint (eLogError, "I2PControl: write error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Write error: ", ecode.message ());
}
}
@@ -375,7 +392,7 @@ namespace client
void I2PControlService::PasswordHandler (const std::string& value)
{
LogPrint (eLogWarning, "I2PControl: new password=", value, ", to make it persistent you should update your config!");
LogPrint (eLogWarning, "I2PControl: New password=", value, ", to make it persistent you should update your config!");
m_Password = value;
m_Tokens.clear ();
}
@@ -391,8 +408,8 @@ namespace client
auto it1 = m_RouterInfoHandlers.find (it->first);
if (it1 != m_RouterInfoHandlers.end ())
{
if (!first) results << ",";
else first = false;
if (!first) results << ",";
else first = false;
(this->*(it1->second))(results);
}
else
@@ -402,7 +419,7 @@ namespace client
void I2PControlService::UptimeHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000);
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
}
void I2PControlService::VersionHandler (std::ostringstream& results)
@@ -573,11 +590,11 @@ namespace client
// save cert
if ((f = fopen (crt_path, "wb")) != NULL) {
LogPrint (eLogInfo, "I2PControl: saving new cert to ", crt_path);
LogPrint (eLogInfo, "I2PControl: Saving new cert to ", crt_path);
PEM_write_X509 (f, x509);
fclose (f);
} else {
LogPrint (eLogError, "I2PControl: can't write cert: ", strerror(errno));
LogPrint (eLogError, "I2PControl: Can't write cert: ", strerror(errno));
}
// save key
@@ -586,12 +603,12 @@ namespace client
PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL);
fclose (f);
} else {
LogPrint (eLogError, "I2PControl: can't write key: ", strerror(errno));
LogPrint (eLogError, "I2PControl: Can't write key: ", strerror(errno));
}
X509_free (x509);
} else {
LogPrint (eLogError, "I2PControl: can't create RSA key for certificate");
LogPrint (eLogError, "I2PControl: Can't create RSA key for certificate");
}
EVP_PKEY_free (pkey);
}
@@ -714,8 +731,8 @@ namespace client
for (auto& it: sam->GetSessions ())
{
boost::property_tree::ptree sam_session, sam_session_sockets;
auto& name = it.second->localDestination->GetNickname ();
auto& ident = it.second->localDestination->GetIdentHash();
auto& name = it.second->GetLocalDestination ()->GetNickname ();
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
sam_session.put("name", name);
sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -65,7 +65,7 @@ namespace client
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
// methods

View File

@@ -29,7 +29,7 @@ namespace transport
{
if (m_IsRunning)
{
LogPrint(eLogInfo, "UPnP: stopping");
LogPrint(eLogInfo, "UPnP: Stopping");
m_IsRunning = false;
m_Timer.cancel ();
m_Service.stop ();
@@ -46,7 +46,7 @@ namespace transport
void UPnP::Start()
{
m_IsRunning = true;
LogPrint(eLogInfo, "UPnP: starting");
LogPrint(eLogInfo, "UPnP: Starting");
m_Service.post (std::bind (&UPnP::Discover, this));
std::unique_lock<std::mutex> l(m_StartedMutex);
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
@@ -72,7 +72,7 @@ namespace transport
}
catch (std::exception& ex)
{
LogPrint (eLogError, "UPnP: runtime exception: ", ex.what ());
LogPrint (eLogError, "UPnP: Runtime exception: ", ex.what ());
PortMapping ();
}
}
@@ -81,10 +81,10 @@ namespace transport
void UPnP::Discover ()
{
bool isError;
int err;
int err;
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNPDISCOVER_SUCCESS;
err = UPNPDISCOVER_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 14)
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
@@ -94,8 +94,8 @@ namespace transport
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;
#endif // MINIUPNPC_API_VERSION >= 8
{
@@ -106,33 +106,33 @@ namespace transport
if (isError)
{
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
LogPrint (eLogError, "UPnP: Unable to discover Internet Gateway Devices: error ", err);
return;
}
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
m_upnpUrlsInitialized=err!=0;
m_upnpUrlsInitialized=err!=0;
if (err == UPNP_IGD_VALID_CONNECTED)
{
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
LogPrint (eLogError, "UPnP: Unable to get external address: error ", err);
return;
}
else
{
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
LogPrint (eLogError, "UPnP: Found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0])
{
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
LogPrint (eLogError, "UPnP: Found Internet Gateway Device doesn't know our external address");
return;
}
}
}
else
{
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
LogPrint (eLogError, "UPnP: Unable to find valid Internet Gateway Device: error ", err);
return;
}
@@ -183,7 +183,7 @@ namespace transport
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
LogPrint (eLogDebug, "UPnP: Port ", strPort, " is possibly not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
@@ -192,18 +192,18 @@ namespace transport
#endif
if (err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
LogPrint (eLogError, "UPnP: Port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
return;
}
else
{
LogPrint (eLogInfo, "UPnP: port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
LogPrint (eLogInfo, "UPnP: Port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
return;
}
}
else
{
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
LogPrint (eLogDebug, "UPnP: External forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return;
}
}
@@ -220,14 +220,14 @@ namespace transport
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
if(!m_upnpUrlsInitialized) {
return;
}
if(!m_upnpUrlsInitialized) {
return;
}
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int err = UPNPCOMMAND_SUCCESS;
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS)
if (err == UPNPCOMMAND_SUCCESS)
{
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
@@ -238,11 +238,11 @@ namespace transport
{
freeUPNPDevlist (m_Devlist);
m_Devlist = 0;
if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
if(m_upnpUrlsInitialized){
FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{

View File

@@ -72,7 +72,8 @@ namespace i2p
if (pid < 0) // error
{
LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno));
LogPrint(eLogError, "Daemon: Could not fork: ", strerror(errno));
std::cerr << "i2pd: Could not fork: " << strerror(errno) << std::endl;
return false;
}
@@ -81,13 +82,15 @@ namespace i2p
int sid = setsid();
if (sid < 0)
{
LogPrint(eLogError, "Daemon: could not create process group.");
LogPrint(eLogError, "Daemon: Could not create process group.");
std::cerr << "i2pd: Could not create process group." << std::endl;
return false;
}
std::string d = i2p::fs::GetDataDir();
if (chdir(d.c_str()) != 0)
{
LogPrint(eLogError, "Daemon: could not chdir: ", strerror(errno));
LogPrint(eLogError, "Daemon: Could not chdir: ", strerror(errno));
std::cerr << "i2pd: Could not chdir: " << strerror(errno) << std::endl;
return false;
}
@@ -102,14 +105,14 @@ namespace i2p
uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles);
getrlimit(RLIMIT_NOFILE, &limit);
if (nfiles == 0) {
LogPrint(eLogInfo, "Daemon: using system limit in ", limit.rlim_cur, " max open files");
LogPrint(eLogInfo, "Daemon: Using system limit in ", limit.rlim_cur, " max open files");
} else if (nfiles <= limit.rlim_max) {
limit.rlim_cur = nfiles;
if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
LogPrint(eLogInfo, "Daemon: set max number of open files to ",
LogPrint(eLogInfo, "Daemon: Set max number of open files to ",
nfiles, " (system limit is ", limit.rlim_max, ")");
} else {
LogPrint(eLogError, "Daemon: can't set max number of open files: ", strerror(errno));
LogPrint(eLogError, "Daemon: Can't set max number of open files: ", strerror(errno));
}
} else {
LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max);
@@ -122,11 +125,11 @@ namespace i2p
if (cfsize <= limit.rlim_max) {
limit.rlim_cur = cfsize;
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
LogPrint(eLogError, "Daemon: can't set max size of coredump: ", strerror(errno));
LogPrint(eLogError, "Daemon: Can't set max size of coredump: ", strerror(errno));
} else if (cfsize == 0) {
LogPrint(eLogInfo, "Daemon: coredumps disabled");
} else {
LogPrint(eLogInfo, "Daemon: set max size of core files to ", cfsize / 1024, "Kb");
LogPrint(eLogInfo, "Daemon: Set max size of core files to ", cfsize / 1024, "Kb");
}
} else {
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
@@ -143,14 +146,16 @@ namespace i2p
pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600);
if (pidFH < 0)
{
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
LogPrint(eLogError, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno));
std::cerr << "i2pd: Could not create pid file " << pidfile << ": " << strerror(errno) << std::endl;
return false;
}
#ifndef ANDROID
if (lockf(pidFH, F_TLOCK, 0) != 0)
{
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
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
@@ -159,7 +164,8 @@ namespace i2p
ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 0)
{
LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno));
LogPrint(eLogError, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno));
std::cerr << "i2pd: Could not write pidfile " << pidfile << ": " << strerror(errno) << std::endl;
return false;
}
}

30
debian/changelog vendored
View File

@@ -1,3 +1,33 @@
i2pd (2.41.0-1) unstable; urgency=medium
* updated to version 2.41.0/0.9.53
-- r4sas <r4sas@i2pmail.org> Sun, 20 Feb 2022 13:00:00 +0000
i2pd (2.40.0-1) unstable; urgency=medium
* updated to version 2.40.0/0.9.52
-- orignal <orignal@i2pmail.org> Mon, 29 Nov 2021 16:00:00 +0000
i2pd (2.39.0-1) unstable; urgency=medium
* updated to version 2.39.0/0.9.51
-- orignal <orignal@i2pmail.org> Mon, 23 Aug 2021 16:00:00 +0000
i2pd (2.38.0-1) unstable; urgency=medium
* updated to version 2.38.0/0.9.50
-- orignal <orignal@i2pmail.org> Mon, 17 May 2021 16:00:00 +0000
i2pd (2.37.0-1) unstable; urgency=medium
* updated to version 2.37.0
-- orignal <orignal@i2pmail.org> Mon, 15 Mar 2021 16:00:00 +0000
i2pd (2.36.0-1) unstable; urgency=high
* updated to version 2.36.0/0.9.49

2
debian/compat vendored
View File

@@ -1 +1 @@
10
9

18
debian/control vendored
View File

@@ -3,30 +3,16 @@ Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.17.2~), gcc (>= 4.7) | clang (>= 3.3), 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.6
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: adduser
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.
.
This package contains the full-featured C++ implementation of I2P router.
Package: i2pd-dbg
Architecture: any
Priority: extra
Section: debug
Depends: i2pd (= ${binary:Version}), ${misc:Depends}
Description: i2pd debugging symbols
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.
.
This package contains symbols required for debugging.

29
debian/copyright vendored
View File

@@ -6,13 +6,6 @@ Files: *
Copyright: 2013-2020 PurpleI2P
License: BSD-3-clause
Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl
qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl
qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java
qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java
Copyright: 2011-2013 BogDan Vatra <bogdan@kde.org>
License: BSD-2-Clause
Files: debian/*
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
2014-2016 hagen <hagen@i2pmail.org>
@@ -49,28 +42,6 @@ License: BSD-3-clause
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: BSD-2-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

4
debian/docs vendored
View File

@@ -1,5 +1 @@
README.md
contrib/i2pd.conf
contrib/subscriptions.txt
contrib/tunnels.conf
contrib/tunnels.d

2
debian/i2pd.dirs vendored
View File

@@ -1,2 +0,0 @@
etc/i2pd
var/lib/i2pd

2
debian/i2pd.install vendored
View File

@@ -1,5 +1,5 @@
i2pd usr/sbin/
contrib/i2pd.conf etc/i2pd/
contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/
contrib/subscriptions.txt etc/i2pd/
contrib/certificates/ usr/share/i2pd/

View File

@@ -2,16 +2,16 @@ Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2021-01-16
Last-Update: 2021-10-22
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -15,7 +15,7 @@ include filelist.mk
USE_AESNI := yes
USE_STATIC := no
USE_MESHNET := no
-USE_UPNP := no
+USE_UPNP := yes
DEBUG := yes
@@ -32,7 +32,7 @@ include filelist.mk
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
USE_MESHNET := $(or $(USE_MESHNET),no)
-USE_UPNP := $(or $(USE_UPNP),no)
+USE_UPNP := $(or $(USE_UPNP),yes)
DEBUG := $(or $(DEBUG),yes)
ifeq ($(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string

3
debian/postinst vendored
View File

@@ -12,7 +12,6 @@ case "$1" in
# Create user and group as a system user.
if getent passwd $I2PDUSER > /dev/null 2>&1; then
groupadd -f $I2PDUSER || true
usermod -s "/bin/false" -e 1 $I2PDUSER > /dev/null || true
else
adduser --system --quiet --group --home $I2PDHOME $I2PDUSER
fi
@@ -23,7 +22,7 @@ case "$1" in
chmod 640 $LOGFILE
chown -f ${I2PDUSER}:adm $LOGFILE
mkdir -p -m0750 $I2PDHOME
chown -f -R -P ${I2PDUSER}:${I2PDUSER} ${I2PDHOME}
chown -f -P ${I2PDUSER}:${I2PDUSER} ${I2PDHOME}
;;
abort-upgrade|abort-remove|abort-deconfigure)
echo "Aborting upgrade"

26
debian/rules vendored
View File

@@ -1,22 +1,16 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow
#DPKG_EXPORT_BUILDFLAGS = 1
#include /usr/share/dpkg/buildflags.mk
#CXXFLAGS+=$(CPPFLAGS)
#PREFIX=/usr
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
include /usr/share/dpkg/architecture.mk
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic -O3
export DEB_LDFLAGS_MAINT_APPEND =
%:
dh $@ --parallel
# dh_apparmor --profile-name=usr.sbin.i2pd -pi2pd
override_dh_strip:
dh_strip --dbg-package=i2pd-dbg
## uncomment this if you have "missing info" problem when building package
#override_dh_shlibdeps:
# dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info

6
debian/watch vendored
View File

@@ -1,3 +1,3 @@
version=3
opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/i2pd-$1\.tar\.gz/ \
https://github.com/PurpleI2P/i2pd/tags .*/v?(\d\S*)\.tar\.gz
version=4 opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
https://github.com/PurpleI2P/i2pd/tags \
(?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate

View File

@@ -19,4 +19,8 @@ LIB_CLIENT_SRC = $(wildcard $(LIB_CLIENT_SRC_DIR)/*.cpp)
#DAEMON_SRC = \
# HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
LANG_SRC = $(wildcard $(LANG_SRC_DIR)/*.cpp)
WRAP_LIB_SRC = $(wildcard $(WRAP_SRC_DIR)/*.cpp)
DAEMON_SRC = $(wildcard $(DAEMON_SRC_DIR)/*.cpp)

81
i18n/Afrikaans.cpp Normal file
View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2021, 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"
// Afrikaans localization file
namespace i2p
{
namespace i18n
{
namespace afrikaans // language namespace
{
// language name in lowercase
static std::string language = "afrikaans";
// 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
{
{"failed", "Het misluk"},
{"unknown", "onbekend"},
{"Tunnels", "Tonnels"},
{"I2P tunnels", "I2P tonnels"},
{"SAM sessions", "SAM sessies"},
{"OK", "LEKKER"},
{"Testing", "Besig om te toets"},
{"Firewalled", "Vuurmuur'd"},
{"Unknown", "Onbekend"},
{"Error", "Fout"},
{"Offline", "Aflyn"},
{"Uptime", "Optyd"},
{"Network status", "Netwerk status"},
{"Network status v6", "Netwerk status v6"},
{"Family", "Familie"},
{"Received", "Ontvang"},
{"Sent", "Gestuur"},
{"Hidden content. Press on text to see.", "Hidden content. Druk om te sien."},
{"Router Ident", "Router Ident"},
{"Router Family", "Router Familie"},
{"Enabled", "Geaktiveer"},
{"Disabled", "Gedeaktiveer"},
{"Change", "Verander"},
{"Change language", "Verander taal"},
{"Description", "Beskrywing"},
{"Submit", "Stuur"},
{"Proxy error", "Proxy-fout"},
{"Host", "Gasheer"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"dag", "dae"}},
{"hours", {"uur", "ure"}},
{"minutes", {"minuut", "minute"}},
{"seconds", {"seconde", "sekondes"}},
{"", {"", ""}},
};
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

215
i18n/Armenian.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 2021, 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"
// Armenian localization file
namespace i2p
{
namespace i18n
{
namespace armenian // language namespace
{
// language name in lowercase
static std::string language = "armenian";
// 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
{
{"KiB", "ԿիԲ"},
{"MiB", "ՄիԲ"},
{"GiB", "ԳիԲ"},
{"building", "կառուցվում է"},
{"failed", "Անհաջող"},
{"expiring", "Լրանում է"},
{"established", "կարգավոյված է"},
{"unknown", "անհայտ"},
{"exploratory", "հետազոտոկան"},
{"<b>i2pd</b> webconsole", "Վեբ-կոնսոլ <b>i2pd</b>"},
{"Main page", "Գլխավոր էջ"},
{"Router commands", "Երթուղիչի հրահանգներ"},
{"Local Destinations", "Տեղական վերջնակետերը"},
{"LeaseSets", "ԼիզՍեթեր"},
{"Tunnels", "Թունելներ"},
{"Transit Tunnels", "Տարանցիկ թունելներ"},
{"Transports", "Տրանսպորտ"},
{"I2P tunnels", "I2P թունելներ"},
{"SAM sessions", "SAM նստաշրջաններ"},
{"ERROR", "ՍԽԱԼ"},
{"OK", "ԼԱՎ"},
{"Testing", "Փորձարկում"},
{"Firewalled", "Արգելափակված է դրսից"},
{"Unknown", "Անհայտ"},
{"Proxy", "Պրոկսի"},
{"Mesh", "MESH-ցանց"},
{"Error", "Սխալ"},
{"Clock skew", "Ոչ ճշգրիտ ժամանակ"},
{"Offline", "Օֆլայն"},
{"Symmetric NAT", "Սիմետրիկ NAT"},
{"Uptime", "Առկայություն"},
{"Network status", "Ցանցի կարգավիճակ"},
{"Network status v6", "Ցանցի կարգավիճակ v6"},
{"Stopping in", "Դադարում"},
{"Family", "Խմբատեսակ"},
{"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"},
{"Received", "Ստացվել է"},
{"KiB/s", "ԿիԲ/վ"},
{"Sent", "Ուղարկվել է"},
{"Transit", "Տարանցում"},
{"Data path", "Տվյալների ուղին"},
{"Hidden content. Press on text to see.", "Թաքցված բովանդակություն: Տեսնելու համար սեղմեկ տեքստին:"},
{"Router Ident", "Երթուղիչի նույնականացուցիչ"},
{"Router Family", "Երթուղիչի խումբը"},
{"Router Caps", "Երթուղիչի հատկություններ"},
{"Version", "Տարբերակ"},
{"Our external address", "Մեր արտաքին հասցեն"},
{"supported", "համատեղելի է"},
{"Routers", "Երթուղիչներ"},
{"Floodfills", "Floodfills-ներ"},
{"Client Tunnels", "Oգտատիրական թունելներ"},
{"Services", "Ծառայություններ"},
{"Enabled", "Միացված է"},
{"Disabled", "Անջատված է"},
{"Encrypted B33 address", "Գաղտնագրված B33 հասցեներ"},
{"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 գործիքակազմը"},
{"Address", "Հասցե"},
{"Type", "Տեսակը"},
{"EncType", "Գաղտնագրի տեսակը"},
{"Inbound tunnels", "Մուտքային թունելներ"},
{"ms", "մլվ"},
{"Outbound tunnels", "Ելքային թունելներ"},
{"Tags", "Թեգեր"},
{"Incoming", "Մուտքային"},
{"Outgoing", "ելքային"},
{"Destination", "Նշանակման վայր"},
{"Amount", "Քանակ"},
{"Incoming Tags", "Մուտքային պիտակներ"},
{"Tags sessions", "Նստաշրջանի պիտակներ"},
{"Status", "Կարգավիճակ"},
{"Local Destination", "Տեղական նշանակման կետ"},
{"Streams", "Հոսքեր"},
{"Close stream", "Փակել հոսքը"},
{"I2CP session not found", "I2CP նստաշրջանը գոյություն չունի"},
{"I2CP is not enabled", "I2CP միացված է"},
{"Invalid", "Անվավեր"},
{"Store type", "Պահեստավորման տեսակը"},
{"Expires", "Սպառվում է"},
{"Non Expired Leases", "Չսպառված Lease-եր"},
{"Gateway", "Դարպաս"},
{"TunnelID", "Թունելի ID"},
{"EndDate", "Ավարտ"},
{"not floodfill", "ոչ floodfill-ներ"},
{"Queue size", "Հերթի չափսը"},
{"Run peer test", "Գործարկել փորձարկումը"},
{"Decline transit tunnels", "Մերժել տարանցիկ թունելներ"},
{"Accept transit tunnels", "Ընդունել տարանցիկ թունելներ"},
{"Cancel graceful shutdown", "Չեղարկել սահուն անջատումը"},
{"Start graceful shutdown", "Սկսել սահուն անջատումը"},
{"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", "Գրառման աստիճանը"},
{"Transit tunnels limit", "Տարանցիկ թունելների սահմանափակում"},
{"Change", "Փոփոխել"},
{"Change language", "Փոփոխել լեզուն"},
{"no transit tunnels currently built", "ընթացիկ կառուցված տարանցիկ թունելներ գոյություն չունեն"},
{"SAM disabled", "SAM-ն անջատված է"},
{"no sessions currently running", "ներկայումս գործող նստաշրջաններ գոյություն չունեն"},
{"SAM session not found", "SAM նստաշրջան գոյություն չունի"},
{"SAM Session", "SAM նստաշրջան"},
{"Server Tunnels", "Սերվերային թունելներ"},
{"Client Forwards", "Օգտատիրական փոխանցումներ"},
{"Server Forwards", "Սերվերային փոխանցումներ"},
{"Unknown page", "Անհայտ էջ"},
{"Invalid token", "Սխալ տոկեն"},
{"SUCCESS", "ՀԱՋՈՂՎԱԾ"},
{"Stream closed", "Հոսքն անջատված է"},
{"Stream not found or already was closed", "Հոսքը գոյություն չունի կամ արդեն ավարտված է"},
{"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", "Ուղարկվել"},
{"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", "Ստորև Դուք կարող եք գտնել այս հոսթը 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 հարցում"},
{"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 պրոկսիի հետ"},
{"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 պրոկսի սերվերին"},
{"Host is down", "Հոսթն անհասանելի է"},
{"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", {"վարկյան", "վարկյան"}},
{"", {"", ""}},
};
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

50
i18n/English.cpp Normal file
View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, 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"
// English localization file
// This is an example translation file without strings in it.
namespace i2p
{
namespace i18n
{
namespace english // language namespace
{
// language name in lowercase
static std::string language = "english";
// 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
{
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"", {"", ""}},
};
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

215
i18n/German.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 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
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// German localization file
namespace i2p
{
namespace i18n
{
namespace german // language namespace
{
// language name in lowercase
static std::string language = "german";
// 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
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "In Bau"},
{"failed", "fehlgeschlagen"},
{"expiring", "läuft ab in"},
{"established", "hergestellt"},
{"unknown", "Unbekannt"},
{"exploratory", "erforschende"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> Webkonsole"},
{"Main page", "Startseite"},
{"Router commands", "Router Befehle"},
{"Local Destinations", "Lokale Destination"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Tunnel"},
{"Transit Tunnels", "Transittunnel"},
{"Transports", "Transporte"},
{"I2P tunnels", "I2P Tunnel"},
{"SAM sessions", "SAM Sitzungen"},
{"ERROR", "FEHLER"},
{"OK", "OK"},
{"Testing", "Testen"},
{"Firewalled", "Hinter eine Firewall"},
{"Unknown", "Unbekannt"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"Error", "Fehler"},
{"Clock skew", "Zeitabweichung"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symmetrisches NAT"},
{"Uptime", "Laufzeit"},
{"Network status", "Netzwerkstatus"},
{"Network status v6", "Netzwerkstatus v6"},
{"Stopping in", "Stoppt in"},
{"Family", "Familie"},
{"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"},
{"Received", "Eingegangen"},
{"KiB/s", "KiB/s"},
{"Sent", "Gesendet"},
{"Transit", "Transit"},
{"Data path", "Datenpfad"},
{"Hidden content. Press on text to see.", "Versteckter Inhalt. Klicke hier, um ihn zu sehen."},
{"Router Ident", "Routeridentität"},
{"Router Family", "Routerfamilie"},
{"Router Caps", "Routerattribute"},
{"Version", "Version"},
{"Our external address", "Unsere externe Adresse"},
{"supported", "unterstützt"},
{"Routers", "Router"},
{"Floodfills", "Floodfills"},
{"Client Tunnels", "Klienttunnel"},
{"Services", "Services"},
{"Enabled", "Aktiviert"},
{"Disabled", "Deaktiviert"},
{"Encrypted B33 address", "Verschlüsselte B33 Adresse"},
{"Address registration line", "Adresseregistrierungszeile"},
{"Domain", "Domain"},
{"Generate", "Generieren"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Hinweis:</b> Der resultierende String kann nur für die Registrierung einer 2LD Domain (beispiel.i2p) benutzt werden. Für die Registrierung von Subdomains kann i2pd-tools verwendet werden."},
{"Address", "Adresse"},
{"Type", "Typ"},
{"EncType", "Verschlüsselungstyp"},
{"Inbound tunnels", "Eingehende Tunnel"},
{"ms", "ms"},
{"Outbound tunnels", "Ausgehende Tunnel"},
{"Tags", "Tags"},
{"Incoming", "Eingehend"},
{"Outgoing", "Ausgehend"},
{"Destination", "Destination"},
{"Amount", "Anzahl"},
{"Incoming Tags", "Eingehende Tags"},
{"Tags sessions", "Tags Sitzungen"},
{"Status", "Status"},
{"Local Destination", "Lokale Destination"},
{"Streams", "Streams"},
{"Close stream", "Stream schließen"},
{"I2CP session not found", "I2CP Sitzung nicht gefunden"},
{"I2CP is not enabled", "I2CP ist nicht aktiviert"},
{"Invalid", "Ungültig"},
{"Store type", "Speichertyp"},
{"Expires", "Ablaufdatum"},
{"Non Expired Leases", "Nicht abgelaufene Leases"},
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Enddatum"},
{"not floodfill", "kein Floodfill"},
{"Queue size", "Warteschlangengröße"},
{"Run peer test", "Peer-Test ausführen"},
{"Decline transit tunnels", "Transittunnel ablehnen"},
{"Accept transit tunnels", "Transittunnel akzeptieren"},
{"Cancel graceful shutdown", "Beende das kontrollierte herunterfahren"},
{"Start graceful shutdown", "Starte das kontrollierte Herunterfahren"},
{"Force shutdown", "Herunterfahren erzwingen"},
{"Reload external CSS styles", "Lade externe CSS-Styles neu"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Hinweis:</b> Alle hier durchgeführten Aktionen sind nicht dauerhaft und ändern die Konfigurationsdateien nicht."},
{"Logging level", "Protokollierungslevel"},
{"Transit tunnels limit", "Limit für Transittunnel"},
{"Change", "Verändern"},
{"Change language", "Sprache ändern"},
{"no transit tunnels currently built", "derzeit keine Transittunnel aufgebaut"},
{"SAM disabled", "SAM deaktiviert"},
{"no sessions currently running", "Derzeit keine laufenden Sitzungen"},
{"SAM session not found", "SAM Sitzung nicht gefunden"},
{"SAM Session", "SAM Sitzung"},
{"Server Tunnels", "Servertunnel"},
{"Client Forwards", "Klient-Weiterleitungen"},
{"Server Forwards", "Server-Weiterleitungen"},
{"Unknown page", "Unbekannte Seite"},
{"Invalid token", "Ungültiger Token"},
{"SUCCESS", "ERFOLGREICH"},
{"Stream closed", "Stream geschlossen"},
{"Stream not found or already was closed", "Stream nicht gefunden oder bereits geschlossen"},
{"Destination not found", "Destination nicht gefunden"},
{"StreamID can't be null", "StreamID kann nicht null sein"},
{"Return to destination page", "Zurück zur Destination-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"},
{"Back to commands list", "Zurück zur Kommandoliste"},
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
{"Description", "Beschreibung"},
{"A bit information about service on domain", "Ein bisschen Informationen über den Service auf der Domain"},
{"Submit", "Einreichen"},
{"Domain can't end with .b32.i2p", "Domain kann nicht mit .b32.i2p enden"},
{"Domain must end with .i2p", "Domain muss mit .i2p enden"},
{"Such destination is not found", "Eine solche Destination konnte nicht gefunden werden"},
{"Unknown command", "Unbekannter Befehl"},
{"Command accepted", "Befehl akzeptiert"},
{"Proxy error", "Proxy-Fehler"},
{"Proxy info", "Proxy-Info"},
{"Proxy error: Host not found", "Proxy-Fehler: Host nicht gefunden"},
{"Remote host not found in router's addressbook", "Remote-Host nicht im Router Adressbuch gefunden"},
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einen der Jump-Services unten finden"},
{"Invalid request", "Ungültige Anfrage"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht interpretieren"},
{"addresshelper is not supported", "addresshelper 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"},
{"Can't detect destination host from request", "Kann Anhand der Anfrage den Destination-Host nicht erkennen"},
{"Outproxy failure", "Outproxy-Fehler"},
{"bad outproxy settings", "ungültige Outproxy-Einstellungen"},
{"not inside I2P network, but outproxy is not enabled", "nicht innerhalb 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"},
{"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"},
{"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 aufbaunen, vielleicht ist es offline. Versuche es später noch einmal."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"Tag", "Tage"}},
{"hours", {"Stunde", "Stunden"}},
{"minutes", {"Minute", "Minuten"}},
{"seconds", {"Sekunde", "Sekunden"}},
{"", {"", ""}},
};
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

45
i18n/I18N.h Normal file
View File

@@ -0,0 +1,45 @@
/*
* 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
*/
#ifndef __I18N_H__
#define __I18N_H__
#include "ClientContext.h"
namespace i2p
{
namespace i18n
{
inline void SetLanguage(const std::string &lang)
{
const auto it = i2p::i18n::languages.find(lang);
if (it == i2p::i18n::languages.end()) // fallback
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
else
i2p::client::context.SetLanguage (it->second.LocaleFunc());
}
inline std::string translate (const std::string& arg)
{
return i2p::client::context.GetLanguage ()->GetString (arg);
}
inline std::string translate (const std::string& arg, const std::string& arg2, const int& n)
{
return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n);
}
} // i18n
} // i2p
template<typename... TArgs>
std::string tr (TArgs&&... args)
{
return i2p::i18n::translate(std::forward<TArgs>(args)...);
}
#endif // __I18N_H__

101
i18n/I18N_langs.h Normal file
View File

@@ -0,0 +1,101 @@
/*
* 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
*/
#ifndef __I18N_LANGS_H__
#define __I18N_LANGS_H__
namespace i2p
{
namespace i18n
{
class Locale
{
public:
Locale (
const std::string& language,
const std::map<std::string, std::string>& strings,
const std::map<std::string, std::vector<std::string>>& plurals,
std::function<int(int)> formula
): m_Language (language), m_Strings (strings), m_Plurals (plurals), m_Formula (formula) { };
// Get activated language name for webconsole
std::string GetLanguage() const
{
return m_Language;
}
std::string GetString (const std::string& arg) const
{
const auto it = m_Strings.find(arg);
if (it == m_Strings.end())
{
return arg;
}
else
{
return it->second;
}
}
std::string GetPlural (const std::string& arg, const std::string& arg2, const int& n) const
{
const auto it = m_Plurals.find(arg2);
if (it == m_Plurals.end()) // not found, fallback to english
{
return n == 1 ? arg : arg2;
}
else
{
int form = m_Formula(n);
return it->second[form];
}
}
private:
const std::string m_Language;
const std::map<std::string, std::string> m_Strings;
const std::map<std::string, std::vector<std::string>> m_Plurals;
std::function<int(int)> m_Formula;
};
struct langData
{
std::string LocaleName; // localized name
std::string ShortCode; // short language code, like "en"
std::function<std::shared_ptr<const i2p::i18n::Locale> (void)> LocaleFunc;
};
// 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 english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { 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
*/
static std::map<std::string, langData> languages
{
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
{ "ukrainian", {"украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
{ "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} },
};
} // i18n
} // i2p
#endif // __I18N_LANGS_H__

215
i18n/Russian.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 2021, 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"
// Russian localization file
namespace i2p
{
namespace i18n
{
namespace russian // language namespace
{
// language name in lowercase
static std::string language = "russian";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
}
static std::map<std::string, std::string> strings
{
{"KiB", "КиБ"},
{"MiB", "МиБ"},
{"GiB", "ГиБ"},
{"building", "строится"},
{"failed", "неудачный"},
{"expiring", "истекает"},
{"established", "работает"},
{"unknown", "неизвестно"},
{"exploratory", "исследовательский"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Главная"},
{"Router commands", "Команды роутера"},
{"Local Destinations", "Локальные назначения"},
{"LeaseSets", "Лизсеты"},
{"Tunnels", "Туннели"},
{"Transit Tunnels", "Транзитные туннели"},
{"Transports", "Транспорты"},
{"I2P tunnels", "I2P туннели"},
{"SAM sessions", "SAM сессии"},
{"ERROR", "ОШИБКА"},
{"OK", "OK"},
{"Testing", "Тестирование"},
{"Firewalled", "Заблокировано извне"},
{"Unknown", "Неизвестно"},
{"Proxy", "Прокси"},
{"Mesh", "MESH-сеть"},
{"Error", "Ошибка"},
{"Clock skew", "Не точное время"},
{"Offline", "Оффлайн"},
{"Symmetric NAT", "Симметричный NAT"},
{"Uptime", "В сети"},
{"Network status", "Сетевой статус"},
{"Network status v6", "Сетевой статус v6"},
{"Stopping in", "Остановка через"},
{"Family", "Семейство"},
{"Tunnel creation success rate", "Успешно построенных туннелей"},
{"Received", "Получено"},
{"KiB/s", "КиБ/с"},
{"Sent", "Отправлено"},
{"Transit", "Транзит"},
{"Data path", "Путь к данным"},
{"Hidden content. Press on text to see.", "Скрытый контент. Нажмите на текст чтобы отобразить."},
{"Router Ident", "Идентификатор роутера"},
{"Router Family", "Семейство роутера"},
{"Router Caps", "Флаги роутера"},
{"Version", "Версия"},
{"Our external address", "Наш внешний адрес"},
{"supported", "поддерживается"},
{"Routers", "Роутеры"},
{"Floodfills", "Флудфилы"},
{"Client Tunnels", "Клиентские туннели"},
{"Services", "Сервисы"},
{"Enabled", "Включено"},
{"Disabled", "Выключено"},
{"Encrypted B33 address", "Шифрованные B33 адреса"},
{"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."},
{"Address", "Адрес"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Inbound tunnels", "Входящие туннели"},
{"ms", "мс"},
{"Outbound tunnels", "Исходящие туннели"},
{"Tags", "Теги"},
{"Incoming", "Входящие"},
{"Outgoing", "Исходящие"},
{"Destination", "Назначение"},
{"Amount", "Количество"},
{"Incoming Tags", "Входящие теги"},
{"Tags sessions", "Сессии тегов"},
{"Status", "Статус"},
{"Local Destination", "Локальное назначение"},
{"Streams", "Стримы"},
{"Close stream", "Закрыть стрим"},
{"I2CP session not found", "I2CP сессия не найдена"},
{"I2CP is not enabled", "I2CP не включен"},
{"Invalid", "Некорректный"},
{"Store type", "Тип хранилища"},
{"Expires", "Истекает"},
{"Non Expired Leases", "Не истекшие Lease-ы"},
{"Gateway", "Шлюз"},
{"TunnelID", "ID туннеля"},
{"EndDate", "Заканчивается"},
{"not floodfill", "не флудфил"},
{"Queue size", "Размер очереди"},
{"Run peer test", "Запустить тестирование"},
{"Decline transit tunnels", "Отклонять транзитные туннели"},
{"Accept transit tunnels", "Принимать транзитные туннели"},
{"Cancel graceful shutdown", "Отменить плавную остановку"},
{"Start graceful shutdown", "Запустить плавную остановку"},
{"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", "Уровень логирования"},
{"Transit tunnels limit", "Лимит транзитных туннелей"},
{"Change", "Изменить"},
{"Change language", "Изменение языка"},
{"no transit tunnels currently built", "нет построенных транзитных туннелей"},
{"SAM disabled", "SAM выключен"},
{"no sessions currently running", "нет запущенных сессий"},
{"SAM session not found", "SAM сессия не найдена"},
{"SAM Session", "SAM сессия"},
{"Server Tunnels", "Серверные туннели"},
{"Client Forwards", "Клиентские перенаправления"},
{"Server Forwards", "Серверные перенаправления"},
{"Unknown page", "Неизвестная страница"},
{"Invalid token", "Неверный токен"},
{"SUCCESS", "УСПЕШНО"},
{"Stream closed", "Стрим закрыт"},
{"Stream not found or already was closed", "Стрим не найден или уже закрыт"},
{"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", "Отправить"},
{"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", "Вы можете попробовать найти узел через джамп сервисы ниже"},
{"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 запроса"},
{"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 прокси"},
{"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 прокси серверу"},
{"Host is down", "Узел недоступен"},
{"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", {"секунду", "секунды", "секунд"}},
{"", {"", "", ""}},
};
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

215
i18n/Turkmen.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* 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
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Turkmen localization file
namespace i2p
{
namespace i18n
{
namespace turkmen // language namespace
{
// language name in lowercase
static std::string language = "turkmen";
// 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
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "bina"},
{"failed", "şowsuz"},
{"expiring", "möhleti gutarýar"},
{"established", "işleýär"},
{"unknown", "näbelli"},
{"exploratory", "gözleg"},
{"<b>i2pd</b> webconsole", "Web konsoly <b>i2pd</b>"},
{"Main page", "Esasy sahypa"},
{"Router commands", "Marşrutizator buýruklary"},
{"Local Destinations", "Ýerli ýerler"},
{"LeaseSets", "Lizset"},
{"Tunnels", "Tuneller"},
{"Transit Tunnels", "Tranzit Tunelleri"},
{"Transports", "Daşamak"},
{"I2P tunnels", "I2P tuneller"},
{"SAM sessions", "SAM Sessiýasy"},
{"ERROR", "Ýalňyşlyk"},
{"OK", "OK"},
{"Testing", "Synag etmek"},
{"Firewalled", "Daşynda petiklendi"},
{"Unknown", "Näbelli"},
{"Proxy", "Proksi"},
{"Mesh", "MESH-tor"},
{"Error", "Ýalňyşlyk"},
{"Clock skew", "Takyk wagt däl"},
{"Offline", "Awtonom"},
{"Symmetric NAT", "Simmetriklik NAT"},
{"Uptime", "Onlaýn onlaýn sözlügi"},
{"Network status", "Tor ýagdaýy"},
{"Network status v6", "Tor ýagdaýy v6"},
{"Stopping in", "Soň duruň"},
{"Family", "Maşgala"},
{"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"},
{"Received", "Alnan"},
{"KiB/s", "KiB/s"},
{"Sent", "Ýerleşdirildi"},
{"Transit", "Tranzit"},
{"Data path", "Maglumat ýoly"},
{"Hidden content. Press on text to see.", "Gizlin mazmun. Görkezmek üçin tekste basyň."},
{"Router Ident", "Marşrutly kesgitleýji"},
{"Router Family", "Marşrutler maşgalasy"},
{"Router Caps", "Baýdaklar marşruteri"},
{"Version", "Wersiýasy"},
{"Our external address", "Daşarky salgymyz"},
{"supported", "goldanýar"},
{"Routers", "Marşrutizatorlar"},
{"Floodfills", "Fludfillar"},
{"Client Tunnels", "Müşderi tunelleri"},
{"Services", "Hyzmatlar"},
{"Enabled", "Goşuldy"},
{"Disabled", "Öçürildi"},
{"Encrypted B33 address", "Şifrlenen B33 salgylar"},
{"Address registration line", "Hasaba alyş salgysy"},
{"Domain", "Domen"},
{"Generate", "Öndürmek"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Bellik:</b> Alnan setir diňe ikinji derejeli domenleri bellige almak üçin ulanylyp bilner (example.i2p). Subýutmalary hasaba almak üçin i2pd ulanyň-tools."},
{"Address", "Salgysy"},
{"Type", "Görnüş"},
{"EncType", "Şifrlemek görnüşi"},
{"Inbound tunnels", "Gelýän tuneller"},
{"ms", "ms"},
{"Outbound tunnels", "Çykýan tuneller"},
{"Tags", "Bellikler"},
{"Incoming", "Gelýän"},
{"Outgoing", "Çykýan"},
{"Destination", "Maksat"},
{"Amount", "Sany"},
{"Incoming Tags", "Gelýän bellikler"},
{"Tags sessions", "Sapaklar bellikler"},
{"Status", "Ýagdaýy"},
{"Local Destination", "Ýerli maksat"},
{"Streams", "Strimlary"},
{"Close stream", "Yap strim"},
{"I2CP session not found", "I2CP Sessiýa tapylmady"},
{"I2CP is not enabled", "I2CP goşulmaýar"},
{"Invalid", "Nädogry"},
{"Store type", "Ammar görnüşi"},
{"Expires", "Möhleti gutarýar"},
{"Non Expired Leases", "Möhleti gutarmady Lizsetlary"},
{"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ň"},
{"Accept transit tunnels", "Tranzit tunellerini alyň"},
{"Cancel graceful shutdown", "Tekiz durmagy ýatyryň"},
{"Start graceful shutdown", "Tekiz durmak"},
{"Force shutdown", "Mejbury duralga"},
{"Reload external CSS styles", "Daşarky CSS stillerini täzeden ýükläň"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Bellik:</b> Bu ýerde öndürilen islendik çäre hemişelik däl we konfigurasiýa faýllaryňyzy üýtgetmeýär."},
{"Logging level", "Giriş derejesi"},
{"Transit tunnels limit", "Tranzit tunelleriniň çägi"},
{"Change", "Üýtgetmek"},
{"Change language", "Dil üýtgetmek"},
{"no transit tunnels currently built", "gurlan tranzit tunelleri ýok"},
{"SAM disabled", "SAM öçürilen"},
{"no sessions currently running", "başlamagyň sessiýalary ýok"},
{"SAM session not found", "SAM Sessiýa tapylmady"},
{"SAM Session", "SAM Sessiýa"},
{"Server Tunnels", "Serwer tunelleri"},
{"Client Forwards", "Müşderi gönükdirýär"},
{"Server Forwards", "Serweriň täzeden düzlüleri"},
{"Unknown page", "Näbelli sahypa"},
{"Invalid token", "Nädogry token"},
{"SUCCESS", "Üstünlikli"},
{"Stream closed", "Strim ýapyk"},
{"Stream not found or already was closed", "Strim tapylmady ýa-da eýýäm ýapyldy"},
{"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"},
{"A bit information about service on domain", "Domendäki hyzmat barada käbir maglumatlar"},
{"Submit", "Iber"},
{"Domain can't end with .b32.i2p", "Domain .b32.i2p bilen gutaryp bilmez"},
{"Domain must end with .i2p", "Domeni .i2p bilen gutarmaly"},
{"Such destination is not found", "Bu barmaly ýer tapylmady"},
{"Unknown command", "Näbelli topar"},
{"Command accepted", "Topar kabul edilýär"},
{"Proxy error", "Proksi ýalňyşlygy"},
{"Proxy info", "Proksi maglumat"},
{"Proxy error: Host not found", "Proksi ýalňyşlygy: Host tapylmady"},
{"Remote host not found in router's addressbook", "Uzakdaky öý eýesi marşruteriň salgy kitabynda tapylmady"},
{"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"},
{"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"},
{"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"},
{"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ň."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"gün", "gün"}},
{"hours", {"sagat", "sagat"}},
{"minutes", {"minut", "minut"}},
{"seconds", {"sekunt", "sekunt"}},
{"", {"", ""}},
};
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

215
i18n/Ukrainian.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 2021, 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"
// Ukrainian localization file
namespace i2p
{
namespace i18n
{
namespace ukrainian // language namespace
{
// language name in lowercase
static std::string language = "ukrainian";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
}
static std::map<std::string, std::string> strings
{
{"KiB", "КіБ"},
{"MiB", "МіБ"},
{"GiB", "ГіБ"},
{"building", "будується"},
{"failed", "невдалий"},
{"expiring", "завершується"},
{"established", "працює"},
{"unknown", "невідомо"},
{"exploratory", "дослідницький"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Головна"},
{"Router commands", "Команди маршрутизатора"},
{"Local Destinations", "Локальні Призначення"},
{"LeaseSets", "Лізсети"},
{"Tunnels", "Тунелі"},
{"Transit Tunnels", "Транзитні Тунелі"},
{"Transports", "Транспорти"},
{"I2P tunnels", "I2P тунелі"},
{"SAM sessions", "SAM сесії"},
{"ERROR", "ПОМИЛКА"},
{"OK", "OK"},
{"Testing", "Тестування"},
{"Firewalled", "Заблоковано ззовні"},
{"Unknown", "Невідомо"},
{"Proxy", "Проксі"},
{"Mesh", "MESH-мережа"},
{"Error", "Помилка"},
{"Clock skew", "Неточний час"},
{"Offline", "Офлайн"},
{"Symmetric NAT", "Симетричний NAT"},
{"Uptime", "У мережі"},
{"Network status", "Мережевий статус"},
{"Network status v6", "Мережевий статус v6"},
{"Stopping in", "Зупинка через"},
{"Family", "Сімейство"},
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
{"Received", "Отримано"},
{"KiB/s", "КіБ/с"},
{"Sent", "Відправлено"},
{"Transit", "Транзит"},
{"Data path", "Шлях до даних"},
{"Hidden content. Press on text to see.", "Прихований вміст. Щоб відобразити, натисніть на текст."},
{"Router Ident", "Ідентифікатор маршрутизатора"},
{"Router Family", "Сімейство маршрутизатора"},
{"Router Caps", "Прапорці маршрутизатора"},
{"Version", "Версія"},
{"Our external address", "Наша зовнішня адреса"},
{"supported", "підтримується"},
{"Routers", "Маршрутизатори"},
{"Floodfills", "Флудфіли"},
{"Client Tunnels", "Клієнтські Тунелі"},
{"Services", "Сервіси"},
{"Enabled", "Увімкнуто"},
{"Disabled", "Вимкнуто"},
{"Encrypted B33 address", "Шифровані B33 адреси"},
{"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."},
{"Address", "Адреса"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Inbound tunnels", "Вхідні тунелі"},
{"ms", "мс"},
{"Outbound tunnels", "Вихідні тунелі"},
{"Tags", "Теги"},
{"Incoming", "Вхідні"},
{"Outgoing", "Вихідні"},
{"Destination", "Призначення"},
{"Amount", "Кількість"},
{"Incoming Tags", "Вхідні Теги"},
{"Tags sessions", "Сесії Тегів"},
{"Status", "Статус"},
{"Local Destination", "Локальні Призначення"},
{"Streams", "Потоки"},
{"Close stream", "Закрити потік"},
{"I2CP session not found", "I2CP сесія не знайдена"},
{"I2CP is not enabled", "I2CP не увікнуто"},
{"Invalid", "Некоректний"},
{"Store type", "Тип сховища"},
{"Expires", "Завершується"},
{"Non Expired Leases", "Не завершені Lease-и"},
{"Gateway", "Шлюз"},
{"TunnelID", "ID тунеля"},
{"EndDate", "Закінчується"},
{"not floodfill", "не флудфіл"},
{"Queue size", "Розмір черги"},
{"Run peer test", "Запустити тестування"},
{"Decline transit tunnels", "Відхиляти транзитні тунелі"},
{"Accept transit tunnels", "Ухвалювати транзитні тунелі"},
{"Cancel graceful shutdown", "Скасувати плавну зупинку"},
{"Start graceful shutdown", "Запустити плавну зупинку"},
{"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", "Рівень логування"},
{"Transit tunnels limit", "Обмеження транзитних тунелів"},
{"Change", "Змінити"},
{"Change language", "Змінити мову"},
{"no transit tunnels currently built", "немає побудованих транзитних тунелів"},
{"SAM disabled", "SAM вимкнуто"},
{"no sessions currently running", "немає запущених сесій"},
{"SAM session not found", "SAM сесія не знайдена"},
{"SAM Session", "SAM сесія"},
{"Server Tunnels", "Серверні Тунелі"},
{"Client Forwards", "Клієнтські Переспрямування"},
{"Server Forwards", "Серверні Переспрямування"},
{"Unknown page", "Невідома сторінка"},
{"Invalid token", "Невірний токен"},
{"SUCCESS", "УСПІШНО"},
{"Stream closed", "Потік зачинений"},
{"Stream not found or already was closed", "Потік не знайдений або вже зачинений"},
{"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"},
{"Back to commands list", "Повернутися до списку команд"},
{"Register at reg.i2p", "Зареєструвати на reg.i2p"},
{"Description", "Опис"},
{"A bit information about service on domain", "Трохи інформації про сервіс на домені"},
{"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", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"},
{"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 запиту"},
{"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 проксі"},
{"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 проксі сервера"},
{"Host is down", "Вузол недоступний"},
{"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", {"секунду", "секунди", "секунд"}},
{"", {"", "", ""}},
};
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

215
i18n/Uzbek.cpp Normal file
View File

@@ -0,0 +1,215 @@
/*
* 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
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Ukrainian localization file
namespace i2p
{
namespace i18n
{
namespace uzbek // language namespace
{
// language name in lowercase
static std::string language = "uzbek";
// 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
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "yaratilmoqda"},
{"failed", "muvaffaqiyatsiz"},
{"expiring", "muddati tugaydi"},
{"established", "aloqa o'rnatildi"},
{"unknown", "noma'lum"},
{"exploratory", "tadqiqiy"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> veb-konsoli"},
{"Main page", "Asosiy sahifa"},
{"Router commands", "Router buyruqlari"},
{"Local Destinations", "Mahalliy joylanishlar"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Tunnellar"},
{"Transit Tunnels", "Tranzit Tunellari"},
{"Transports", "Transportlar"},
{"I2P tunnels", "I2P tunnellari"},
{"SAM sessions", "SAM sessiyalari"},
{"ERROR", "XATO"},
{"OK", "OK"},
{"Testing", "Testlash"},
{"Firewalled", "Xavfsizlik devori bilan himoyalangan"},
{"Unknown", "Notanish"},
{"Proxy", "Proksi"},
{"Mesh", "Mesh To'r"},
{"Error", "Xato"},
{"Clock skew", "Aniq vaqt emas"},
{"Offline", "Oflayn"},
{"Symmetric NAT", "Simmetrik NAT"},
{"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"},
{"Received", "Qabul qilindi"},
{"KiB/s", "KiB/s"},
{"Sent", "Yuborilgan"},
{"Transit", "Tranzit"},
{"Data path", "Ma'lumotlar joylanishi"},
{"Hidden content. Press on text to see.", "Yashirin tarkib. Ko'rish uchun matn ustida bosing."},
{"Router Ident", "Router identifikatori"},
{"Router Family", "Router oilasi"},
{"Router Caps", "Router Bayroqlari"},
{"Version", "Versiya"},
{"Our external address", "Bizning tashqi manzilimiz"},
{"supported", "qo'llab-quvvatlanadi"},
{"Routers", "Routerlar"},
{"Floodfills", "Floodfills"},
{"Client Tunnels", "Mijoz Tunellari"},
{"Services", "Xizmatlar"},
{"Enabled", "Yoqilgan"},
{"Disabled", "O'chirilgan"},
{"Encrypted B33 address", "Shifrlangan B33 manzil"},
{"Address registration line", "Manzilni ro'yxatga olish liniyasi"},
{"Domain", "Domen"},
{"Generate", "Yaratish"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Eslatma:</b> natija satridan faqat 2LD domenlarini ro'yxatdan o'tkazish uchun foydalanish mumkin (example.i2p). Subdomenlarni ro'yxatdan o'tkazish uchun 'i2pd-tools'dan foydalaning."},
{"Address", "Manzil"},
{"Type", "Turi"},
{"EncType", "ShifrlashTuri"},
{"Inbound tunnels", "Kirish tunnellari"},
{"ms", "ms"},
{"Outbound tunnels", "Chiquvchi tunnellar"},
{"Tags", "Teglar"},
{"Incoming", "Kiruvchi"},
{"Outgoing", "Chiquvchi"},
{"Destination", "Manzilgoh"},
{"Amount", "Soni"},
{"Incoming Tags", "Kiruvchi teglar"},
{"Tags sessions", "Teglar sessiyalari"},
{"Status", "Holat"},
{"Local Destination", "Mahalliy joylanish"},
{"Streams", "Strim"},
{"Close stream", "Strimni o'chirish"},
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
{"I2CP is not enabled", "I2CP yoqilmagan"},
{"Invalid", "Noto'g'ri"},
{"Store type", "Saqlash turi"},
{"Expires", "Muddati tugaydi"},
{"Non Expired Leases", "Muddati O'tmagan Leases"},
{"Gateway", "Kirish yo'li"},
{"TunnelID", "TunnelID"},
{"EndDate", "Tugash Sanasi"},
{"not floodfill", "floodfill emas"},
{"Queue size", "Navbat hajmi"},
{"Run peer test", "Sinovni boshlang"},
{"Decline transit tunnels", "Tranzit tunnellarini rad etish"},
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"},
{"Start graceful shutdown", "Yumshoq to'xtashni boshlash"},
{"Force shutdown", "Majburiy to'xtatish"},
{"Reload external CSS styles", "Tashqi CSS uslublarini qayta yuklang"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Eslatma:</b> shu yerda qilingan har qanday harakat doimiy emas va konfiguratsiya fayllarini o'zgartirmaydi."},
{"Logging level", "Jurnal darajasi"},
{"Transit tunnels limit", "Tranzit tunellarning chegarasi"},
{"Change", "O'zgartirish"},
{"Change language", "Tilni o'zgartirish"},
{"no transit tunnels currently built", "qurilgan tranzit tunnellari yo'q"},
{"SAM disabled", "SAM o'chirilgan"},
{"no sessions currently running", "hech qanday ishlaydigan sessiyalar yo'q"},
{"SAM session not found", "SAM sessiyasi topilmadi"},
{"SAM Session", "SAM sessiyasi"},
{"Server Tunnels", "Server Tunellari"},
{"Client Forwards", "Mijozlarni Yo'naltirish"},
{"Server Forwards", "Serverni Yo'naltirish"},
{"Unknown page", "Noma'lum sahifa"},
{"Invalid token", "Notogri belgi"},
{"SUCCESS", "Muvaffaqiyat"},
{"Stream closed", "Strim yopiq"},
{"Stream not found or already was closed", "Strim topilmadi yoki allaqachon yopilgan"},
{"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"},
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
{"Description", "Tavsif"},
{"A bit information about service on domain", "Domen xizmatlari haqida bir oz ma'lumot"},
{"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"},
{"Proxy info", "Proksi ma'lumotlari"},
{"Proxy error: Host not found", "Proksi xatosi: Xost topilmadi"},
{"Remote host not found in router's addressbook", "Masofaviy xost yo'riqnoma manzillar kitobida topilmadi"},
{"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"},
{"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"},
{"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"},
{"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."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"kun", "kun"}},
{"hours", {"soat", "soat"}},
{"minutes", {"daqiqa", "daqiqa"}},
{"seconds", {"soniya", "soniya"}},
{"", {"", ""}},
};
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -185,10 +185,7 @@ namespace data
if (InCount && !m)
outCount = 3 * n;
else
{
outCount = 0;
return 0;
}
ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 )
@@ -196,7 +193,7 @@ namespace data
ps = (unsigned char *)InBuffer;
if (outCount > len)
return -1;
return 0;
pd = OutBuffer;
auto endOfOutBuffer = OutBuffer + outCount;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -122,7 +122,7 @@ namespace data
break;
}
default:
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA");
LogPrint (eLogError, "Blinding: Signature type ", (int)sigType, " is not ECDSA");
}
if (group)
{
@@ -156,7 +156,7 @@ namespace data
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
if (l < 32)
{
LogPrint (eLogError, "Blinding: malformed b33 ", b33);
LogPrint (eLogError, "Blinding: Malformed b33 ", b33);
return;
}
uint32_t checksum = crc32 (0, addr + 3, l - 3);
@@ -186,10 +186,10 @@ namespace data
memcpy (m_PublicKey.data (), addr + offset, len);
}
else
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType);
LogPrint (eLogError, "Blinding: Public key in b33 address is too short for signature type ", (int)m_SigType);
}
else
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33");
LogPrint (eLogError, "Blinding: Unknown signature type ", (int)m_SigType, " in b33");
}
std::string BlindedPublicKey::ToB33 () const
@@ -256,7 +256,7 @@ namespace data
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break;
default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
}
return publicKeyLength;
}
@@ -277,8 +277,16 @@ namespace data
i2p::crypto::GetEd25519 ()->BlindPrivateKey (priv, seed, blindedPriv, blindedPub);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break;
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{
uint8_t exp[64];
i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp);
i2p::crypto::GetEd25519 ()->BlindPrivateKey (exp, seed, blindedPriv, blindedPub);
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
break;
}
default:
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
}
return publicKeyLength;
}
@@ -316,7 +324,7 @@ namespace data
SHA256_Final ((uint8_t *)hash, &ctx);
}
else
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported");
LogPrint (eLogError, "Blinding: Blinded key type ", (int)m_BlindedSigType, " is not supported");
return hash;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -19,6 +19,7 @@
#include "Identity.h"
#include "Config.h"
#include "version.h"
#include "Log.h"
using namespace boost::program_options;
@@ -36,6 +37,7 @@ namespace config {
("conf", value<std::string>()->default_value(""), "Path to main i2pd config file (default: try ~/.i2pd/i2pd.conf or /var/lib/i2pd/i2pd.conf)")
("tunconf", value<std::string>()->default_value(""), "Path to config with tunnels list and options (default: try ~/.i2pd/tunnels.conf or /var/lib/i2pd/tunnels.conf)")
("tunnelsdir", value<std::string>()->default_value(""), "Path to extra tunnels' configs folder (default: ~/.i2pd/tunnels.d or /var/lib/i2pd/tunnels.d")
("certsdir", value<std::string>()->default_value(""), "Path to certificates used for verifying .su3, families (default: ~/.i2pd/certificates or /var/lib/i2pd/certificates")
("pidfile", value<std::string>()->default_value(""), "Path to pidfile (default: ~/i2pd/i2pd.pid or /var/lib/i2pd/i2pd.pid)")
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
@@ -50,20 +52,22 @@ namespace config {
("nat", bool_switch()->default_value(true), "Should we assume we are behind NAT? (default: enabled)")
("port", value<uint16_t>()->default_value(0), "Port to listen for incoming connections (default: auto)")
("ipv4", bool_switch()->default_value(true), "Enable communication through ipv4 (default: enabled)")
("address4", value<std::string>()->default_value(""), "Local address to bind ipv4 transport sockets to")
("ipv6", bool_switch()->default_value(false), "Enable communication through ipv6 (default: disabled)")
("address6", value<std::string>()->default_value(""), "Local address to bind ipv6 transport sockets to")
("reservedrange", bool_switch()->default_value(true), "Check remote RI for being in blacklist of reserved IP ranges (default: enabled)")
("netid", value<int>()->default_value(I2PD_NET_ID), "Specify NetID. Main I2P is 2")
("daemon", bool_switch()->default_value(false), "Router will go to background after start (default: disabled)")
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
("notransit", bool_switch()->default_value(false), "Router will not accept transit tunnels at startup (default: disabled)")
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("bandwidth", value<std::string>()->default_value(""), "Transit traffic bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
("ntcp", bool_switch()->default_value(false), "Ignored. Always false")
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
#ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Windows service management ('install' or 'remove')")
("svcctl", value<std::string>()->default_value(""), "Ignored")
("insomnia", bool_switch()->default_value(false), "Prevent system from sleeping (default: disabled)")
("close", value<std::string>()->default_value("ask"), "Action on close: minimize, exit, ask")
#endif
@@ -90,6 +94,7 @@ namespace config {
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
("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 )")
;
options_description httpproxy("HTTP Proxy options");
@@ -110,6 +115,7 @@ namespace config {
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0,4"), "Local destination's LeaseSet encryption type")
("httpproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key")
;
options_description socksproxy("SOCKS Proxy options");
@@ -131,6 +137,7 @@ namespace config {
("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
("socksproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("0,4"), "Local destination's LeaseSet encryption type")
("socksproxy.i2cp.leaseSetPrivKey", value<std::string>()->default_value(""), "LeaseSet private key")
;
options_description sam("SAM bridge options");
@@ -196,18 +203,22 @@ namespace config {
("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")
("reseed.urls", value<std::string>()->default_value(
"https://reseed.i2p-projekt.de/,"
"https://reseed2.i2p.net/,"
"https://reseed.diva.exchange/,"
"https://reseed-fr.i2pd.xyz/,"
"https://reseed.memcpy.io/,"
"https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/,"
"https://reseed.i2pgit.org/,"
"https://i2p.novg.net/"
"https://i2p.novg.net/,"
"https://banana.incognet.io/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:9de3:fea4:f6ac::ace]:7070/"
), "Reseed URLs through the Yggdrasil, separated by comma")
"http://[324:71e:281a:9ed3::ace]:7070/,"
"http://[301:65b9:c7cd:9a36::1]:18801/,"
"http://[320:8936:ec1a:31f1::216]/,"
"http://[306:3834:97b9:a00a::1]/"
), "Reseed URLs through the Yggdrasil, separated by comma")
;
options_description addressbook("AddressBook options");
@@ -215,13 +226,15 @@ namespace config {
("addressbook.defaulturl", value<std::string>()->default_value(
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
), "AddressBook subscription URL for initial setup")
("addressbook.subscriptions", value<std::string>()->default_value(""), "AddressBook subscriptions URLs, separated by comma")
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
("addressbook.subscriptions", value<std::string>()->default_value(
"http://reg.i2p/hosts.txt"
), "AddressBook subscriptions URLs, separated by comma")
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
options_description trust("Trust options");
trust.add_options()
("trust.enabled", value<bool>()->default_value(false), "Enable explicit trust options")
("trust.family", value<std::string>()->default_value(""), "Router Familiy to trust for first hops")
("trust.family", value<std::string>()->default_value(""), "Router Family to trust for first hops")
("trust.routers", value<std::string>()->default_value(""), "Only Connect to these routers")
("trust.hidden", value<bool>()->default_value(false), "Should we hide our router from other routers?")
;
@@ -247,7 +260,7 @@ namespace config {
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
("ntcp2.published", value<bool>()->default_value(true), "Publish NTCP2 (default: enabled)")
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to bind NTCP2 on")
("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to publish NTCP2 with")
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
;
@@ -259,8 +272,9 @@ namespace config {
"1.pool.ntp.org,"
"2.pool.ntp.org,"
"3.pool.ntp.org"
), "Comma separated list of NTCP servers")
), "Comma separated list of NTP servers")
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
("nettime.frompeers", value<bool>()->default_value(true), "Sync clock from transport peers (default: enabled)")
;
options_description persist("Network information persisting options");
@@ -278,10 +292,10 @@ namespace config {
options_description meshnets("Meshnet transports options");
meshnets.add_options()
("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (deafult: false)")
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
;
("meshnets.yggdrasil", bool_switch()->default_value(false), "Support transports through the Yggdrasil (default: false)")
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
;
m_OptionsDesc
.add(general)
.add(limits)
@@ -312,7 +326,7 @@ namespace config {
try
{
auto style = boost::program_options::command_line_style::unix_style
| boost::program_options::command_line_style::allow_long_disguise;
| boost::program_options::command_line_style::allow_long_disguise;
style &= ~ boost::program_options::command_line_style::allow_guessing;
if (ignoreUnknown)
store(command_line_parser(argc, argv).options(m_OptionsDesc).style (style).allow_unregistered().run(), m_Options);
@@ -321,6 +335,7 @@ namespace config {
}
catch (boost::program_options::error& e)
{
ThrowFatal ("Error while parsing arguments: ", e.what());
std::cerr << "args: " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
@@ -358,6 +373,7 @@ namespace config {
if (!config.is_open())
{
ThrowFatal ("Missing or unreadable config file: ", path);
std::cerr << "missing/unreadable config file: " << path << std::endl;
exit(EXIT_FAILURE);
}
@@ -368,6 +384,7 @@ namespace config {
}
catch (boost::program_options::error& e)
{
ThrowFatal ("Error while parsing config file: ", e.what());
std::cerr << e.what() << std::endl;
exit(EXIT_FAILURE);
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -353,7 +353,7 @@ namespace crypto
bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
{
if (pub[31] & 0x80) return false; // not x25519 key
if (!pub || (pub[31] & 0x80)) return false; // not x25519 key
#if OPENSSL_X25519
EVP_PKEY_derive_init (m_Ctx);
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
@@ -389,7 +389,7 @@ namespace crypto
{
size_t len = 32;
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
}
}
#else
memcpy (m_PrivateKey, priv, 32);
if (calculatePublic)
@@ -398,8 +398,9 @@ namespace crypto
}
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted)
{
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
// everything, but a, because a might come from table
BIGNUM * k = BN_CTX_get (ctx);
@@ -435,37 +436,32 @@ namespace crypto
BN_bin2bn (m, 255, b);
BN_mod_mul (b, b1, b, elgp, ctx);
// copy a and b
if (zeroPadding)
{
encrypted[0] = 0;
bn2buf (a, encrypted + 1, 256);
encrypted[257] = 0;
bn2buf (b, encrypted + 258, 256);
}
else
{
bn2buf (a, encrypted, 256);
bn2buf (b, encrypted + 256, 256);
}
encrypted[0] = 0;
bn2buf (a, encrypted + 1, 256);
encrypted[257] = 0;
bn2buf (b, encrypted + 258, 256);
BN_free (a);
BN_CTX_end (ctx);
BN_CTX_free (ctx);
}
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted,
uint8_t * data, BN_CTX * ctx, bool zeroPadding)
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data)
{
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
BIGNUM * x = BN_CTX_get (ctx), * a = BN_CTX_get (ctx), * b = BN_CTX_get (ctx);
BN_bin2bn (key, 256, x);
BN_sub (x, elgp, x); BN_sub_word (x, 1); // x = elgp - x- 1
BN_bin2bn (zeroPadding ? encrypted + 1 : encrypted, 256, a);
BN_bin2bn (zeroPadding ? encrypted + 258 : encrypted + 256, 256, b);
BN_bin2bn (encrypted + 1, 256, a);
BN_bin2bn (encrypted + 258, 256, b);
// m = b*(a^x mod p) mod p
BN_mod_exp (x, a, x, elgp, ctx);
BN_mod_mul (b, b, x, elgp, ctx);
uint8_t m[255];
bn2buf (b, m, 255);
BN_CTX_end (ctx);
BN_CTX_free (ctx);
uint8_t hash[32];
SHA256 (m + 33, 222, hash);
if (memcmp (m + 1, hash, 32))
@@ -499,8 +495,9 @@ namespace crypto
}
// ECIES
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted)
{
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order(curve, q, ctx);
@@ -512,19 +509,10 @@ namespace crypto
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
if (zeroPadding)
{
encrypted[0] = 0;
bn2buf (x, encrypted + 1, len);
bn2buf (y, encrypted + 1 + len, len);
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
}
else
{
bn2buf (x, encrypted, len);
bn2buf (y, encrypted + len, len);
RAND_bytes (encrypted + 2*len, 256 - 2*len);
}
encrypted[0] = 0;
bn2buf (x, encrypted + 1, len);
bn2buf (y, encrypted + 1 + len, len);
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
// encryption key and iv
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
@@ -541,36 +529,25 @@ namespace crypto
CBCEncryption encryption;
encryption.SetKey (shared);
encryption.SetIV (iv);
if (zeroPadding)
{
encrypted[257] = 0;
encryption.Encrypt (m, 256, encrypted + 258);
}
else
encryption.Encrypt (m, 256, encrypted + 256);
encrypted[257] = 0;
encryption.Encrypt (m, 256, encrypted + 258);
EC_POINT_free (p);
BN_CTX_end (ctx);
BN_CTX_free (ctx);
}
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data)
{
bool ret = true;
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order(curve, q, ctx);
int len = BN_num_bytes (q);
// point for shared secret
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
if (zeroPadding)
{
BN_bin2bn (encrypted + 1, len, x);
BN_bin2bn (encrypted + 1 + len, len, y);
}
else
{
BN_bin2bn (encrypted, len, x);
BN_bin2bn (encrypted + len, len, y);
}
BN_bin2bn (encrypted + 1, len, x);
BN_bin2bn (encrypted + 1 + len, len, y);
auto p = EC_POINT_new (curve);
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
{
@@ -587,10 +564,7 @@ namespace crypto
CBCDecryption decryption;
decryption.SetKey (shared);
decryption.SetIV (iv);
if (zeroPadding)
decryption.Decrypt (encrypted + 258, 256, m);
else
decryption.Decrypt (encrypted + 256, 256, m);
decryption.Decrypt (encrypted + 258, 256, m);
// verify and copy
uint8_t hash[32];
SHA256 (m + 33, 222, hash);
@@ -610,6 +584,7 @@ namespace crypto
EC_POINT_free (p);
BN_CTX_end (ctx);
BN_CTX_free (ctx);
return ret;
}
@@ -1302,7 +1277,7 @@ namespace crypto
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
}
if (info.length () > 0)
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.c_str (), info.length ());
EVP_PKEY_derive (pctx, out, &outLen);
EVP_PKEY_CTX_free (pctx);
#else
@@ -1320,7 +1295,7 @@ namespace crypto
}
// Noise
void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
{
SHA256_CTX ctx;
@@ -1336,7 +1311,7 @@ namespace crypto
// new ck is m_CK[0:31], key is m_CK[32:63]
}
static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck,
static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck,
const uint8_t * hh, const uint8_t * pub)
{
// pub is Bob's public static key, hh = SHA256(h)
@@ -1346,22 +1321,22 @@ namespace crypto
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
}
}
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
{
static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
static const uint8_t hh[32] =
{
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
}; // hh = SHA256(protocol_name || 0)
InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
}
}
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
{
static const uint8_t protocolNameHash[] =
static const uint8_t protocolNameHash[32] =
{
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
@@ -1371,9 +1346,24 @@ namespace crypto
0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
}; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub);
}
InitNoiseState (state, protocolNameHash, hh, pub);
}
void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub)
{
static const uint8_t protocolNameHash[32] =
{
0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4,
0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32
}; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256")
static const uint8_t hh[32] =
{
0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53,
0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33
}; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub);
}
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
{
static const uint8_t protocolNameHash[32] =
@@ -1386,9 +1376,9 @@ namespace crypto
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
}; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub);
}
InitNoiseState (state, protocolNameHash, hh, pub);
}
// init and terminate
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -39,7 +39,9 @@
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# if (OPENSSL_VERSION_NUMBER < 0x030000000) // 3.0.0, regression in SipHash
# define OPENSSL_SIPHASH 1
# endif
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
@@ -93,7 +95,7 @@ namespace crypto
bool IsElligatorIneligible () const { return m_IsElligatorIneligible; }
void SetElligatorIneligible () { m_IsElligatorIneligible = true; }
private:
uint8_t m_PublicKey[32];
@@ -104,17 +106,17 @@ namespace crypto
BN_CTX * m_Ctx;
uint8_t m_PrivateKey[32];
#endif
bool m_IsElligatorIneligible = false; // true if definitly ineligible
bool m_IsElligatorIneligible = false; // true if definitely ineligible
};
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
// ECIES
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted); // 222 bytes data, 514 bytes encrypted
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data); // 514 bytes encrypted, 222 data
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
// HMAC
@@ -315,13 +317,14 @@ namespace crypto
uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/;
void MixHash (const uint8_t * buf, size_t len);
void MixKey (const uint8_t * sharedSecret);
void MixKey (const uint8_t * sharedSecret);
};
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router)
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2)
void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (SSU2)
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 TerminateCrypto ();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -20,10 +20,9 @@ namespace crypto
memcpy (m_PublicKey, pub, 256);
}
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
{
if (!ctx) return;
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, zeroPadding);
ElGamalEncrypt (m_PublicKey, data, encrypted);
}
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
@@ -31,10 +30,9 @@ namespace crypto
memcpy (m_PrivateKey, priv, 256);
}
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data)
{
if (!ctx) return false;
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, zeroPadding);
return ElGamalDecrypt (m_PrivateKey, encrypted, data);
}
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
@@ -54,10 +52,10 @@ namespace crypto
if (m_PublicKey) EC_POINT_free (m_PublicKey);
}
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
{
if (m_Curve && m_PublicKey)
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx, zeroPadding);
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted);
}
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
@@ -72,10 +70,10 @@ namespace crypto
if (m_PrivateKey) BN_free (m_PrivateKey);
}
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data)
{
if (m_Curve && m_PrivateKey)
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx, zeroPadding);
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data);
return false;
}
@@ -114,10 +112,10 @@ namespace crypto
if (m_PublicKey) EC_POINT_free (m_PublicKey);
}
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted)
{
if (m_PublicKey)
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx, zeroPadding);
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted);
}
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
@@ -130,10 +128,10 @@ namespace crypto
if (m_PrivateKey) BN_free (m_PrivateKey);
}
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data)
{
if (m_PrivateKey)
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx, zeroPadding);
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data);
return false;
}
@@ -161,7 +159,7 @@ namespace crypto
memcpy (m_PublicKey, pub, 32);
}
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool)
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub)
{
memcpy (pub, m_PublicKey, 32);
}
@@ -171,7 +169,7 @@ namespace crypto
m_StaticKeys.SetPrivateKey (priv, calculatePublic);
}
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding)
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret)
{
return m_StaticKeys.Agree (epub, sharedSecret);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -21,7 +21,7 @@ namespace crypto
public:
virtual ~CryptoKeyEncryptor () {};
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) = 0; // 222 bytes data, 512/514 bytes encrypted
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) = 0;
};
class CryptoKeyDecryptor
@@ -29,7 +29,7 @@ namespace crypto
public:
virtual ~CryptoKeyDecryptor () {};
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data) = 0;
virtual size_t GetPublicKeyLen () const = 0; // we need it to set key in LS2
};
@@ -39,7 +39,7 @@ namespace crypto
public:
ElGamalEncryptor (const uint8_t * pub);
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
void Encrypt (const uint8_t * data, uint8_t * encrypted) override; // 222 bytes data, 514 bytes encrypted
private:
@@ -51,8 +51,8 @@ namespace crypto
public:
ElGamalDecryptor (const uint8_t * priv);
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 256; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override; // 514 bytes encrypted, 222 bytes data
size_t GetPublicKeyLen () const override { return 256; };
private:
@@ -67,7 +67,7 @@ namespace crypto
ECIESP256Encryptor (const uint8_t * pub);
~ECIESP256Encryptor ();
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
private:
@@ -82,8 +82,8 @@ namespace crypto
ECIESP256Decryptor (const uint8_t * priv);
~ECIESP256Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 64; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override;
size_t GetPublicKeyLen () const override { return 64; };
private:
@@ -101,7 +101,7 @@ namespace crypto
ECIESGOSTR3410Encryptor (const uint8_t * pub);
~ECIESGOSTR3410Encryptor ();
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
private:
@@ -115,8 +115,8 @@ namespace crypto
ECIESGOSTR3410Decryptor (const uint8_t * priv);
~ECIESGOSTR3410Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
size_t GetPublicKeyLen () const { return 64; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override;
size_t GetPublicKeyLen () const override { return 64; };
private:
@@ -133,7 +133,7 @@ namespace crypto
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
~ECIESX25519AEADRatchetEncryptor () {};
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
void Encrypt (const uint8_t *, uint8_t * pub) override;
// copies m_PublicKey to pub
private:
@@ -147,9 +147,9 @@ namespace crypto
ECIESX25519AEADRatchetDecryptor (const uint8_t * priv, bool calculatePublic = false);
~ECIESX25519AEADRatchetDecryptor () {};
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding);
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret) override;
// agree with static and return in sharedSecret (32 bytes)
size_t GetPublicKeyLen () const { return 32; };
size_t GetPublicKeyLen () const override { return 32; };
const uint8_t * GetPubicKey () const { return m_StaticKeys.GetPublicKey (); };
private:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -21,6 +21,9 @@ 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)
{
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
auto identityLen = m_Owner->GetIdentity ()->GetFullLen ();
m_From.resize (identityLen);
m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen);
@@ -152,11 +155,16 @@ namespace datagram
const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
{
size_t size;
auto msg = m_I2NPMsgsPool.AcquireShared ();
uint8_t * buf = msg->GetPayload ();
buf += 4; // reserve for length
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
if (m_Gzip && m_Deflator)
size = m_Deflator->Deflate (payloads, buf, msg->maxLen - msg->len);
else
size = i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
if (size)
{
htobe32buf (msg->GetPayload (), size); // length
@@ -295,7 +303,7 @@ namespace datagram
}
}
if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ())
if (!m_RoutingSession || m_RoutingSession->IsTerminated () || !m_RoutingSession->IsReadyToSend ())
{
bool found = false;
for (auto& it: m_PendingRoutingSessions)
@@ -363,8 +371,6 @@ namespace datagram
{
// no current path, make one
path = std::make_shared<i2p::garlic::GarlicRoutingPath>();
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel();
if (!path->outboundTunnel) return nullptr;
if (m_RemoteLeaseSet)
{
@@ -378,6 +384,11 @@ namespace datagram
}
else
return nullptr;
auto leaseRouter = i2p::data::netdb.FindRouter (path->remoteLease->tunnelGateway);
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(nullptr,
leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports);
if (!path->outboundTunnel) return nullptr;
}
else
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -117,12 +117,12 @@ namespace datagram
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
// TODO: implement calls from other thread from SAM
std::shared_ptr<DatagramSession> GetSession(const i2p::data::IdentHash & ident);
void SendDatagram (std::shared_ptr<DatagramSession> session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);
void SendRawDatagram (std::shared_ptr<DatagramSession> session, const uint8_t * payload, size_t len, uint16_t fromPort, uint16_t toPort);
void FlushSendQueue (std::shared_ptr<DatagramSession> session);
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; };
@@ -164,7 +164,7 @@ namespace datagram
std::map<uint16_t, Receiver> m_ReceiversByPorts;
i2p::data::GzipInflator m_Inflator;
i2p::data::GzipDeflator m_Deflator;
std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
std::vector<uint8_t> m_From, m_Signature;
i2p::util::MemoryPool<I2NPMessageBuffer<I2NP_MAX_MESSAGE_SIZE> > m_I2NPMsgsPool;
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -56,7 +56,7 @@ namespace client
it = params->find (I2CP_PARAM_TAGS_TO_SEND);
if (it != params->end ())
numTags = std::stoi(it->second);
LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
LogPrint (eLogInfo, "Destination: Parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS);
if (it != params->end ())
SetNumRatchetInboundTags (std::stoi(it->second));
@@ -82,6 +82,14 @@ namespace client
if (it != params->end ()) m_Nickname = it->second;
// otherwise we set default nickname in Start when we know local address
}
it = params->find (I2CP_PARAM_DONT_PUBLISH_LEASESET);
if (it != params->end ())
{
// oveeride isPublic
bool dontpublish = false;
i2p::config::GetOption (it->second, dontpublish);
m_IsPublic = !dontpublish;
}
it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ())
m_LeaseSetType = std::stoi(it->second);
@@ -104,7 +112,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(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr);
}
}
@@ -112,7 +120,7 @@ namespace client
}
catch (std::exception & ex)
{
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
}
SetNumTags (numTags);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty);
@@ -128,7 +136,7 @@ namespace client
auto minlatency = std::stoi(itr->second);
if ( minlatency > 0 && maxlatency > 0 ) {
// set tunnel pool latency
LogPrint(eLogInfo, "Destination: requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
LogPrint(eLogInfo, "Destination: Requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
m_Pool->RequireLatency(minlatency, maxlatency);
}
}
@@ -243,7 +251,7 @@ namespace client
}
else
{
LogPrint (eLogWarning, "Destination: remote LeaseSet expired");
LogPrint (eLogWarning, "Destination: Remote LeaseSet expired");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets.erase (ident);
return nullptr;
@@ -300,7 +308,11 @@ namespace client
{
int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum
CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels));
auto tunnels = m_Pool->GetInboundTunnels (numTunnels);
if (!tunnels.empty ())
CreateNewLeaseSet (tunnels);
else
LogPrint (eLogInfo, "Destination: No inbound tunnels for LeaseSet");
}
bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
@@ -333,10 +345,11 @@ namespace client
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len)
{
I2NPMessageType typeID = (I2NPMessageType)(buf[I2NP_HEADER_TYPEID_OFFSET]);
LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE);
uint32_t msgID = bufbe32toh (buf + I2NP_HEADER_MSGID_OFFSET);
LeaseSetDestination::HandleCloveI2NPMessage (typeID, buf + I2NP_HEADER_SIZE, GetI2NPMessageLength(buf, len) - I2NP_HEADER_SIZE, msgID);
}
bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len)
bool LeaseSetDestination::HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID)
{
switch (typeID)
{
@@ -353,6 +366,9 @@ namespace client
case eI2NPDatabaseSearchReply:
HandleDatabaseSearchReplyMessage (payload, len);
break;
case eI2NPShortTunnelBuildReply: // might come as garlic encrypted
i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID));
break;
default:
LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID);
return false;
@@ -379,14 +395,14 @@ namespace client
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end () &&
if (it != m_RemoteLeaseSets.end () &&
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
{
leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
{
leaseSet->Update (buf + offset, len - offset);
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ())
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
else
{
@@ -405,7 +421,7 @@ namespace client
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
else
leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset, true, GetPreferredCryptoType () ); // LeaseSet2
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key && !leaseSet->IsExpired ())
{
if (leaseSet->GetIdentHash () != GetIdentHash ())
{
@@ -471,7 +487,7 @@ namespace client
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");
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
}
}
@@ -539,16 +555,9 @@ namespace client
shared_from_this (), std::placeholders::_1));
return;
}
auto outbound = m_Pool->GetNextOutboundTunnel ();
if (!outbound)
if (!m_Pool->GetInboundTunnels ().size () || !m_Pool->GetOutboundTunnels ().size ())
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
return;
}
auto inbound = m_Pool->GetNextInboundTunnel ();
if (!inbound)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
LogPrint (eLogError, "Destination: Can't publish LeaseSet. Destination is not ready");
return;
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
@@ -557,7 +566,34 @@ namespace client
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
m_ExcludedFloodfills.clear ();
return;
}
}
auto outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
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)
{
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 more floodfills found");
if (!floodfill || !outbound || !inbound)
{
m_ExcludedFloodfills.clear ();
return;
}
}
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
@@ -602,7 +638,7 @@ namespace client
auto ls = GetLeaseSetMt ();
if (!ls)
{
LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
LogPrint (eLogWarning, "Destination: Couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
return;
}
auto s = shared_from_this ();
@@ -614,7 +650,7 @@ namespace client
if (*ls == *leaseSet)
{
// we got latest LeasetSet
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", s->GetIdentHash().ToBase32());
LogPrint (eLogDebug, "Destination: Published LeaseSet verified for ", s->GetIdentHash().ToBase32());
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
return;
@@ -623,7 +659,7 @@ namespace client
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", s->GetIdentHash().ToBase32());
}
else
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
LogPrint (eLogWarning, "Destination: Couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
// we have to publish again
s->Publish ();
});
@@ -735,10 +771,10 @@ 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 ();
request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true));
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false));
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
if (request->replyTunnel && request->outboundTunnel)
@@ -751,11 +787,11 @@ namespace client
uint8_t replyKey[32], replyTag[32];
RAND_bytes (replyKey, 32); // random session key
RAND_bytes (replyTag, isECIES ? 8 : 32); // random session tag
if (isECIES)
if (isECIES)
AddECIESx25519Key (replyKey, replyTag);
else
else
AddSessionKey (replyKey, replyTag);
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
request->outboundTunnel->SendTunnelDataMsg (
{
@@ -850,8 +886,8 @@ namespace client
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service)
@@ -900,11 +936,11 @@ namespace client
encryptionKey->GenerateKeys ();
encryptionKey->CreateDecryptor ();
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{
{
m_ECIESx25519EncryptionKey.reset (encryptionKey);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2
}
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // Rathets must use LeaseSet2
}
else
m_StandardEncryptionKey.reset (encryptionKey);
}
@@ -923,7 +959,7 @@ namespace client
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ())
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
// authentication for encrypted LeaseSet
@@ -950,7 +986,7 @@ namespace client
}
catch (std::exception & ex)
{
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
}
}
@@ -1026,7 +1062,7 @@ namespace client
LogPrint (eLogError, "Destination: Missing raw datagram destination");
break;
default:
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
LogPrint (eLogError, "Destination: Data: Unexpected protocol ", buf[9]);
}
}
@@ -1034,7 +1070,7 @@ namespace client
{
if (!streamRequestComplete)
{
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
return;
}
auto leaseSet = FindLeaseSet (dest);
@@ -1058,7 +1094,7 @@ namespace client
{
if (!streamRequestComplete)
{
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
return;
}
auto s = GetSharedFromThis ();
@@ -1080,6 +1116,35 @@ namespace client
return nullptr;
}
void ClientDestination::SendPing (const i2p::data::IdentHash& to)
{
if (m_StreamingDestination)
{
auto leaseSet = FindLeaseSet (to);
if (leaseSet)
m_StreamingDestination->SendPing (leaseSet);
else
{
auto s = m_StreamingDestination;
RequestDestination (to,
[s](std::shared_ptr<const i2p::data::LeaseSet> ls)
{
if (ls) s->SendPing (ls);
});
}
}
}
void ClientDestination::SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to)
{
auto s = m_StreamingDestination;
RequestDestinationWithEncryptedLeaseSet (to,
[s](std::shared_ptr<const i2p::data::LeaseSet> ls)
{
if (ls) s->SendPing (ls);
});
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
{
if (port)
@@ -1127,6 +1192,21 @@ namespace client
return dest;
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (int port)
{
if (port)
{
auto it = m_StreamingDestinationsByPorts.find (port);
if (it != m_StreamingDestinationsByPorts.end ())
{
auto ret = it->second;
m_StreamingDestinationsByPorts.erase (it);
return ret;
}
}
return nullptr;
}
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
{
if (m_DatagramDestination == nullptr)
@@ -1176,7 +1256,7 @@ namespace client
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
}
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
{
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
@@ -1214,15 +1294,15 @@ namespace client
if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
}
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const
{
if (preferredCrypto == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
if (m_ECIESx25519EncryptionKey && m_ECIESx25519EncryptionKey->decryptor)
return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true);
return m_ECIESx25519EncryptionKey->decryptor->Decrypt (encrypted, data);
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor)
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data, ctx, true);
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data);
else
LogPrint (eLogError, "Destinations: decryptor is not set");
LogPrint (eLogError, "Destinations: Decryptor is not set");
return false;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -61,8 +61,9 @@ namespace client
const char I2CP_PARAM_RATCHET_OUTBOUND_TAGS[] = "crypto.ratchet.outboundTags"; // not used yet
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname";
const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet";
const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType";
const int DEFAULT_LEASESET_TYPE = 1;
const int DEFAULT_LEASESET_TYPE = 3;
const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType";
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
@@ -79,7 +80,7 @@ namespace client
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
const char I2CP_PARAM_STREAMING_ANSWER_PINGS[] = "i2p.streaming.answerPings";
const int DEFAULT_ANSWER_PINGS = true;
const int DEFAULT_ANSWER_PINGS = true;
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
@@ -137,21 +138,23 @@ namespace client
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
void SetLeaseSetUpdated ();
bool IsPublic () const { return m_IsPublic; };
void SetPublic (bool pub) { m_IsPublic = pub; };
protected:
// implements GarlicDestination
void HandleI2NPMessage (const uint8_t * buf, size_t len);
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len);
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID);
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
int GetLeaseSetType () const { return m_LeaseSetType; };
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
int GetAuthType () const { return m_AuthType; };
bool IsPublic () const { return m_IsPublic; };
virtual void CleanupDestination () {}; // additional clean up in derived classes
// I2CP
virtual void HandleDataMessage (const uint8_t * buf, size_t len) = 0;
virtual void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels) = 0;
virtual void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels) = 0;
private:
@@ -235,23 +238,26 @@ namespace client
// 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);
// 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 (std::shared_ptr<const i2p::data::LeaseSet> remote, int 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);
void StopAcceptingStreams ();
bool IsAcceptingStreams () const;
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
bool IsStreamingAnswerPings () const { return m_IsStreamingAnswerPings; }
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
// implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
bool Decrypt (const uint8_t * encrypted, uint8_t * data, i2p::data::CryptoKeyType preferredCrypto) const;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const;
@@ -261,7 +267,7 @@ namespace client
void CleanupDestination ();
// I2CP
void HandleDataMessage (const uint8_t * buf, size_t len);
void CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels);
void CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels);
private:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -31,16 +31,16 @@ namespace garlic
uint8_t keydata[64];
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
memcpy (m_NextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_KeyData.buf);
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", m_SessionTagKeyData);
// [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
memcpy (m_SymmKeyCK, m_KeyData.buf + 32, 32);
memcpy (m_SymmKeyCK, (const uint8_t *)m_SessionTagKeyData + 32, 32);
m_NextSymmKeyIndex = 0;
}
void RatchetTagSet::NextSessionTagRatchet ()
{
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), nullptr, 0, "STInitialization", m_KeyData.buf); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
memcpy (m_SessTagConstant, m_KeyData.GetSessTagConstant (), 32);
i2p::crypto::HKDF (m_SessionTagKeyData, nullptr, 0, "STInitialization", m_SessionTagKeyData); // [sessTag_ck, sesstag_constant] = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
memcpy (m_SessTagConstant, (const uint8_t *)m_SessionTagKeyData + 32, 32); // SESSTAG_CONSTANT = keydata[32:63]
m_NextIndex = 0;
}
@@ -52,8 +52,8 @@ namespace garlic
LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
return 0;
}
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
return m_KeyData.GetTag ();
i2p::crypto::HKDF (m_SessionTagKeyData, m_SessTagConstant, 32, "SessionTagKeyGen", m_SessionTagKeyData); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
return m_SessionTagKeyData.GetLL ()[4]; // tag = keydata[32:39]
}
void RatchetTagSet::GetSymmKey (int index, uint8_t * key)
@@ -90,24 +90,24 @@ namespace garlic
}
void RatchetTagSet::DeleteSymmKey (int index)
{
{
m_ItermediateSymmKeys.erase (index);
}
void ReceiveRatchetTagSet::Expire ()
{
if (!m_ExpirationTimestamp)
m_ExpirationTimestamp = i2p::util::GetSecondsSinceEpoch () + ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT;
}
bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const
{
return m_ExpirationTimestamp && ts > m_ExpirationTimestamp;
}
bool ReceiveRatchetTagSet::IsIndexExpired (int index) const
{
return index < m_TrimBehindIndex;
bool ReceiveRatchetTagSet::IsExpired (uint64_t ts) const
{
return m_ExpirationTimestamp && ts > m_ExpirationTimestamp;
}
bool ReceiveRatchetTagSet::IsIndexExpired (int index) const
{
return index < m_TrimBehindIndex;
}
bool ReceiveRatchetTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
@@ -115,54 +115,55 @@ namespace garlic
auto session = GetSession ();
if (!session) return false;
return session->HandleNextMessage (buf, len, shared_from_this (), index);
}
DatabaseLookupTagSet::DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
memcpy (m_Key, key, 32);
Expire ();
}
bool DatabaseLookupTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
memcpy (m_Key, key, 32);
Expire ();
}
bool SymmetricKeyTagSet::HandleNextMessage (uint8_t * buf, size_t len, int index)
{
if (len < 24) return false;
uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0
size_t offset = 8; // first 8 bytes is reply tag used as AD
size_t offset = 8; // first 8 bytes is reply tag used as AD
len -= 16; // poly1305
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len - offset, buf, 8, m_Key, nonce, buf + offset, len - offset, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Lookup reply AEAD decryption failed");
LogPrint (eLogWarning, "Garlic: Symmetric key tagset AEAD decryption failed");
return false;
}
// we assume 1 I2NP block with delivery type local
if (offset + 3 > len)
{
LogPrint (eLogWarning, "Garlic: Lookup reply is too short ", len);
if (offset + 3 > len)
{
LogPrint (eLogWarning, "Garlic: Symmetric key tagset is too short ", len);
return false;
}
}
if (buf[offset] != eECIESx25519BlkGalicClove)
{
LogPrint (eLogWarning, "Garlic: Lookup reply unexpected block ", (int)buf[offset]);
LogPrint (eLogWarning, "Garlic: Symmetric key tagset unexpected block ", (int)buf[offset]);
return false;
}
}
offset++;
auto size = bufbe16toh (buf + offset);
offset += 2;
if (offset + size > len)
if (offset + size > len)
{
LogPrint (eLogWarning, "Garlic: Lookup reply block is too long ", size);
LogPrint (eLogWarning, "Garlic: Symmetric key tagset block is too long ", size);
return false;
}
}
if (m_Destination)
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size);
m_Destination->HandleECIESx25519GarlicClove (buf + offset, size);
return true;
}
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet):
GarlicRoutingSession (owner, attachLeaseSet)
}
ECIESX25519AEADRatchetSession::ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS):
GarlicRoutingSession (owner, true)
{
if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
}
@@ -180,11 +181,11 @@ namespace garlic
{
bool ineligible = false;
while (!ineligible)
{
{
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
ineligible = m_EphemeralKeys->IsElligatorIneligible ();
if (!ineligible) // we haven't tried it yet
{
{
if (i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys->GetPublicKey (), buf))
return true; // success
// otherwise return back
@@ -193,9 +194,9 @@ namespace garlic
}
else
i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys);
}
}
// we still didn't find elligator eligible pair
for (int i = 0; i < 10; i++)
for (int i = 0; i < 25; i++)
{
// create new
m_EphemeralKeys = std::make_shared<i2p::crypto::X25519Keys>();
@@ -207,7 +208,7 @@ namespace garlic
// let NTCP2 use it
m_EphemeralKeys->SetElligatorIneligible ();
i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys);
}
}
}
LogPrint (eLogError, "Garlic: Can't generate elligator eligible x25519 keys");
return false;
@@ -227,8 +228,8 @@ namespace garlic
if (!GetOwner ()) return false;
// we are Bob
// KDF1
i2p::crypto::InitNoiseIKState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{
LogPrint (eLogError, "Garlic: Can't decode elligator");
@@ -238,11 +239,11 @@ namespace garlic
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
if (!GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
return false;
}
}
MixKey (sharedSecret);
// decrypt flags/static
@@ -262,11 +263,11 @@ namespace garlic
{
// static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32);
if (!GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk)
if (!GetOwner ()->Decrypt (fs, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, apk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false;
}
}
MixKey (sharedSecret);
}
else // all zeros flags
@@ -279,13 +280,13 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false;
}
m_State = eSessionStateNewSessionReceived;
if (isStatic)
{
if (isStatic)
{
MixHash (buf, len); // h = SHA256(h || ciphertext)
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
}
}
HandlePayload (payload.data (), len - 16, nullptr, 0);
return true;
@@ -313,7 +314,7 @@ namespace garlic
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
break;
case eECIESx25519BlkNextKey:
LogPrint (eLogDebug, "Garlic: next key");
LogPrint (eLogDebug, "Garlic: Next key");
if (receiveTagset)
HandleNextKey (buf + offset, size, receiveTagset);
else
@@ -321,7 +322,7 @@ namespace garlic
break;
case eECIESx25519BlkAck:
{
LogPrint (eLogDebug, "Garlic: ack");
LogPrint (eLogDebug, "Garlic: Ack");
int numAcks = size >> 2; // /4
auto offset1 = offset;
for (auto i = 0; i < numAcks; i++)
@@ -333,24 +334,24 @@ namespace garlic
}
case eECIESx25519BlkAckRequest:
{
LogPrint (eLogDebug, "Garlic: ack request");
LogPrint (eLogDebug, "Garlic: Ack request");
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
break;
}
case eECIESx25519BlkTermination:
LogPrint (eLogDebug, "Garlic: termination");
LogPrint (eLogDebug, "Garlic: Termination");
if (GetOwner ())
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
if (receiveTagset) receiveTagset->Expire ();
break;
case eECIESx25519BlkDateTime:
LogPrint (eLogDebug, "Garlic: datetime");
LogPrint (eLogDebug, "Garlic: Datetime");
break;
case eECIESx25519BlkOptions:
LogPrint (eLogDebug, "Garlic: options");
LogPrint (eLogDebug, "Garlic: Options");
break;
case eECIESx25519BlkPadding:
LogPrint (eLogDebug, "Garlic: padding");
LogPrint (eLogDebug, "Garlic: Padding");
break;
default:
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
@@ -380,7 +381,7 @@ namespace garlic
newTagset->NextSessionTagRatchet ();
m_SendTagset = newTagset;
m_SendForwardKey = false;
LogPrint (eLogDebug, "Garlic: next send tagset ", newTagset->GetTagSetID (), " created");
LogPrint (eLogDebug, "Garlic: Next send tagset ", newTagset->GetTagSetID (), " created");
}
else
LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID);
@@ -423,7 +424,7 @@ namespace garlic
GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS);
receiveTagset->Expire ();
LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created");
LogPrint (eLogDebug, "Garlic: Next receive tagset ", tagsetID, " created");
}
}
@@ -445,7 +446,7 @@ namespace garlic
m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair ();
m_SendForwardKey = true;
LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
LogPrint (eLogDebug, "Garlic: New send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
}
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
@@ -460,14 +461,14 @@ namespace garlic
offset += 32;
// KDF1
i2p::crypto::InitNoiseIKState (*this, m_RemoteStaticKey); // bpk
i2p::crypto::InitNoiseIKState (GetNoiseState (), m_RemoteStaticKey); // bpk
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32];
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return false;
}
}
MixKey (sharedSecret);
// encrypt flags/static key section
uint8_t nonce[12];
@@ -477,7 +478,7 @@ namespace garlic
fs = GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
else
{
memset (out + offset, 0, 32); // all zeros flags section
memset (out + offset, 0, 32); // all zeros flags section
fs = out + offset;
}
if (!i2p::crypto::AEADChaCha20Poly1305 (fs, 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
@@ -485,14 +486,14 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD encryption failed ");
return false;
}
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48;
// KDF2
if (isStatic)
{
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk)
MixKey (sharedSecret);
{
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bpk)
MixKey (sharedSecret);
}
else
CreateNonce (1, nonce);
@@ -502,50 +503,22 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false;
}
m_State = eSessionStateNewSessionSent;
if (isStatic)
{
{
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
if (GetOwner ())
{
auto tagsetNsr = std::make_shared<ReceiveRatchetTagSet>(shared_from_this (), true);
InitNewSessionTagset (tagsetNsr);
tagsetNsr->Expire (); // let non-replied session expire
GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS);
}
}
}
return true;
}
bool ECIESX25519AEADRatchetSession::NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Alice, router's bpk is m_RemoteStaticKey
i2p::crypto::InitNoiseNState (*this, m_RemoteStaticKey);
size_t offset = 0;
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
memcpy (out + offset, m_EphemeralKeys->GetPublicKey (), 32);
MixHash (out + offset, 32); // h = SHA256(h || aepk)
offset += 32;
uint8_t sharedSecret[32];
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // x25519(aesk, bpk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return false;
}
MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload for router AEAD encryption failed");
return false;
}
m_State = eSessionStateNewSessionSent;
return true;
}
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob
@@ -561,7 +534,7 @@ namespace garlic
LogPrint (eLogError, "Garlic: Can't encode elligator");
return false;
}
memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
memcpy (m_NSREncodedKey, out + offset, 32); // for possible next NSR
memcpy (m_NSRH, m_H, 32);
offset += 32;
// KDF for Reply Key Section
@@ -572,13 +545,13 @@ namespace garlic
{
LogPrint (eLogWarning, "Garlic: Incorrect Alice ephemeral key");
return false;
}
}
MixKey (sharedSecret);
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret)) // sharedSecret = x25519(besk, apk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
return false;
}
}
MixKey (sharedSecret);
uint8_t nonce[12];
CreateNonce (0, nonce);
@@ -611,10 +584,10 @@ namespace garlic
}
m_State = eSessionStateNewSessionReplySent;
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
return true;
}
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob and sent NSR already
@@ -645,7 +618,7 @@ namespace garlic
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
{
// we are Alice
LogPrint (eLogDebug, "Garlic: reply received");
LogPrint (eLogDebug, "Garlic: Reply received");
const uint8_t * tag = buf;
buf += 8; len -= 8; // tag
uint8_t bepk[32]; // Bob's ephemeral key
@@ -656,7 +629,7 @@ namespace garlic
}
buf += 32; len -= 32;
// KDF for Reply Key Section
i2p::util::SaveStateHelper<i2p::crypto::NoiseSymmetricState> s(*this); // restore noise state on exit
i2p::util::SaveStateHelper<i2p::crypto::NoiseSymmetricState> s(GetNoiseState ()); // restore noise state on exit
MixHash (tag, 8); // h = SHA256(h || tag)
MixHash (bepk, 32); // h = SHA256(h || bepk)
uint8_t sharedSecret[32];
@@ -664,9 +637,9 @@ namespace garlic
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob ephemeral key");
return false;
}
}
MixKey (sharedSecret);
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
GetOwner ()->Decrypt (bepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
MixKey (sharedSecret);
uint8_t nonce[12];
@@ -727,11 +700,11 @@ namespace garlic
uint64_t tag = m_SendTagset->GetNextSessionTag ();
if (!tag)
{
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
if (GetOwner ())
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
return false;
}
}
memcpy (out, &tag, 8);
// ad = The session tag, 8 bytes
// ciphertext = ENCRYPT(k, n, payload, ad)
@@ -763,7 +736,7 @@ namespace garlic
}
HandlePayload (payload, len - 16, receiveTagset, index);
if (GetOwner ())
{
{
int moreTags = 0;
if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings?
{
@@ -772,17 +745,17 @@ namespace garlic
index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind
}
else
{
{
moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
moreTags -= (receiveTagset->GetNextIndex () - index);
index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind
}
}
if (moreTags > 0)
GenerateMoreReceiveTags (receiveTagset, moreTags);
if (index > 0)
receiveTagset->SetTrimBehind (index);
}
}
return true;
}
@@ -801,19 +774,18 @@ namespace garlic
#endif
case eSessionStateEstablished:
if (receiveTagset->IsNS ())
{
// our of sequence NSR
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
{
// our of sequence NSR
LogPrint (eLogDebug, "Garlic: Check for out of order NSR with index ", index);
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
return HandleNewOutgoingSessionReply (buf, len);
}
}
else
return HandleExistingSessionMessage (buf, len, receiveTagset, index);
case eSessionStateNew:
return HandleNewIncomingSession (buf, len);
case eSessionStateNewSessionSent:
receiveTagset->Expire (); // NSR tagset
return HandleNewOutgoingSessionReply (buf, len);
default:
return false;
@@ -821,36 +793,11 @@ namespace garlic
return true;
}
bool ECIESX25519AEADRatchetSession::HandleNextMessageForRouter (const uint8_t * buf, size_t len)
{
if (!GetOwner ()) return false;
// we are Bob
i2p::crypto::InitNoiseNState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
MixHash (buf, 32);
uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
{
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
return false;
}
MixKey (sharedSecret);
buf += 32; len -= 32;
uint8_t nonce[12];
CreateNonce (0, nonce);
std::vector<uint8_t> payload (len - 16);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
return false;
}
HandlePayload (payload.data (), len - 16, nullptr, 0);
return true;
}
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
size_t len = payload.size ();
uint8_t * payload = GetOwner ()->GetPayloadBuffer ();
if (!payload) return nullptr;
size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload);
if (!len) return nullptr;
auto m = NewI2NPMessage (len + 100); // 96 + 4
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
@@ -859,35 +806,30 @@ namespace garlic
switch (m_State)
{
case eSessionStateEstablished:
if (!NewExistingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
if (!NewExistingSessionMessage (payload, len, buf, m->maxLen))
return nullptr;
len += 24;
break;
case eSessionStateNew:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen))
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen))
return nullptr;
len += 96;
break;
case eSessionStateNewSessionReceived:
if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
if (!NewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr;
len += 72;
break;
case eSessionStateNewSessionReplySent:
if (!NextNewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
if (!NextNewSessionReplyMessage (payload, len, buf, m->maxLen))
return nullptr;
len += 72;
break;
case eSessionStateOneTime:
if (!NewOutgoingSessionMessage (payload.data (), payload.size (), buf, m->maxLen, false))
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false))
return nullptr;
len += 96;
break;
case eSessionStateForRouter:
if (!NewOutgoingMessageForRouter (payload.data (), payload.size (), buf, m->maxLen))
return nullptr;
len += 48;
break;
break;
default:
return nullptr;
}
@@ -898,22 +840,22 @@ namespace garlic
return m;
}
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter)
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg)
{
m_State = isForRouter ? eSessionStateForRouter : eSessionStateOneTime;
m_State = eSessionStateOneTime;
return WrapSingleMessage (msg);
}
std::vector<uint8_t> ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first)
}
size_t ECIESX25519AEADRatchetSession::CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload)
{
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch ();
size_t payloadLen = 0;
if (first) payloadLen += 7;// datatime
if (msg)
{
{
payloadLen += msg->GetPayloadLength () + 13;
if (m_Destination) payloadLen += 32;
}
}
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{
// resubmit non-confirmed LeaseSet
@@ -954,9 +896,9 @@ namespace garlic
paddingSize = m_PaddingSizes[m_NextPaddingSize++] & 0x0F; // 0 - 15
if (m_NextPaddingSize >= 32)
{
RAND_bytes (m_PaddingSizes, 32);
RAND_bytes (m_PaddingSizes, 32);
m_NextPaddingSize = 0;
}
}
if (delta > 3)
{
delta -= 3;
@@ -966,89 +908,93 @@ namespace garlic
payloadLen += paddingSize + 3;
}
}
std::vector<uint8_t> v(payloadLen);
if (payloadLen)
{
{
if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
{
LogPrint (eLogError, "Garlic: Payload length ", payloadLen, " is too long");
return 0;
}
m_LastSentTimestamp = ts;
size_t offset = 0;
// DateTime
if (first)
{
v[offset] = eECIESx25519BlkDateTime; offset++;
htobe16buf (v.data () + offset, 4); offset += 2;
htobe32buf (v.data () + offset, ts/1000); offset += 4; // in seconds
payload[offset] = eECIESx25519BlkDateTime; offset++;
htobe16buf (payload + offset, 4); offset += 2;
htobe32buf (payload + offset, ts/1000); offset += 4; // in seconds
}
// LeaseSet
if (leaseSet)
{
offset += CreateLeaseSetClove (leaseSet, ts, v.data () + offset, payloadLen - offset);
offset += CreateLeaseSetClove (leaseSet, ts, payload + offset, payloadLen - offset);
if (!first)
{
// ack request
v[offset] = eECIESx25519BlkAckRequest; offset++;
htobe16buf (v.data () + offset, 1); offset += 2;
v[offset] = 0; offset++; // flags
payload[offset] = eECIESx25519BlkAckRequest; offset++;
htobe16buf (payload + offset, 1); offset += 2;
payload[offset] = 0; offset++; // flags
}
}
// msg
if (msg)
offset += CreateGarlicClove (msg, v.data () + offset, payloadLen - offset);
offset += CreateGarlicClove (msg, payload + offset, payloadLen - offset);
// ack
if (m_AckRequests.size () > 0)
{
v[offset] = eECIESx25519BlkAck; offset++;
htobe16buf (v.data () + offset, m_AckRequests.size () * 4); offset += 2;
payload[offset] = eECIESx25519BlkAck; offset++;
htobe16buf (payload + offset, m_AckRequests.size () * 4); offset += 2;
for (auto& it: m_AckRequests)
{
htobe16buf (v.data () + offset, it.first); offset += 2;
htobe16buf (v.data () + offset, it.second); offset += 2;
htobe16buf (payload + offset, it.first); offset += 2;
htobe16buf (payload + offset, it.second); offset += 2;
}
m_AckRequests.clear ();
}
// next keys
if (m_SendReverseKey)
{
v[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2;
v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG;
payload[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (payload + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2;
payload[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG;
int keyID = m_NextReceiveRatchet->keyID - 1;
if (m_NextReceiveRatchet->newKey)
{
v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG;
payload[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG;
keyID++;
}
offset++; // flag
htobe16buf (v.data () + offset, keyID); offset += 2; // keyid
htobe16buf (payload + offset, keyID); offset += 2; // keyid
if (m_NextReceiveRatchet->newKey)
{
memcpy (v.data () + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32);
memcpy (payload + offset, m_NextReceiveRatchet->key->GetPublicKey (), 32);
offset += 32; // public key
}
m_SendReverseKey = false;
}
if (m_SendForwardKey)
{
v[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (v.data () + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2;
v[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG;
if (!m_NextSendRatchet->keyID) v[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only
payload[offset] = eECIESx25519BlkNextKey; offset++;
htobe16buf (payload + offset, m_NextSendRatchet->newKey ? 35 : 3); offset += 2;
payload[offset] = m_NextSendRatchet->newKey ? ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG : ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG;
if (!m_NextSendRatchet->keyID) payload[offset] |= ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; // for first key only
offset++; // flag
htobe16buf (v.data () + offset, m_NextSendRatchet->keyID); offset += 2; // keyid
htobe16buf (payload + offset, m_NextSendRatchet->keyID); offset += 2; // keyid
if (m_NextSendRatchet->newKey)
{
memcpy (v.data () + offset, m_NextSendRatchet->key->GetPublicKey (), 32);
memcpy (payload + offset, m_NextSendRatchet->key->GetPublicKey (), 32);
offset += 32; // public key
}
}
// padding
if (paddingSize)
{
v[offset] = eECIESx25519BlkPadding; offset++;
htobe16buf (v.data () + offset, paddingSize); offset += 2;
memset (v.data () + offset, 0, paddingSize); offset += paddingSize;
payload[offset] = eECIESx25519BlkPadding; offset++;
htobe16buf (payload + offset, paddingSize); offset += 2;
memset (payload + offset, 0, paddingSize); offset += paddingSize;
}
}
return v;
}
return payloadLen;
}
size_t ECIESX25519AEADRatchetSession::CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len)
@@ -1104,17 +1050,17 @@ namespace garlic
void ECIESX25519AEADRatchetSession::GenerateMoreReceiveTags (std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int numTags)
{
if (GetOwner ())
{
{
for (int i = 0; i < numTags; i++)
{
{
auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
if (!tag)
{
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
break;
}
}
}
}
}
}
}
bool ECIESX25519AEADRatchetSession::CheckExpired (uint64_t ts)
@@ -1124,39 +1070,141 @@ namespace garlic
ts*1000 > m_LastSentTimestamp + ECIESX25519_SEND_EXPIRATION_TIMEOUT*1000; // milliseconds
}
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState):
ECIESX25519AEADRatchetSession (&i2p::context, false)
{
SetLeaseSetUpdateStatus (eLeaseSetDoNotSend);
SetNoiseState (initState);
}
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
{
if (!GetOwner ()) return false;
m_CurrentNoiseState = GetNoiseState ();
// we are Bob
m_CurrentNoiseState.MixHash (buf, 32);
uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (buf, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
{
LogPrint (eLogWarning, "Garlic: Incorrect N ephemeral public key");
return false;
}
m_CurrentNoiseState.MixKey (sharedSecret);
buf += 32; len -= 32;
uint8_t nonce[12];
CreateNonce (0, nonce);
std::vector<uint8_t> payload (len - 16);
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_CurrentNoiseState.m_H, 32,
m_CurrentNoiseState.m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
return false;
}
HandlePayload (payload.data (), len - 16, nullptr, 0);
return true;
}
static size_t CreateGarlicPayload (std::shared_ptr<const I2NPMessage> msg, uint8_t * payload,
bool datetime, size_t optimalSize)
{
size_t len = 0;
if (datetime)
{
// DateTime
payload[0] = eECIESx25519BlkDateTime;
htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
len = 7;
}
// I2NP
payload += len;
uint16_t cloveSize = msg->GetPayloadLength () + 10;
payload[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (payload + 1, cloveSize); // size
payload += 3;
payload[0] = 0; // flag and delivery instructions
payload[1] = msg->GetTypeID (); // I2NP msg type
htobe32buf (payload + 2, msg->GetMsgID ()); // msgID
htobe32buf (payload + 6, msg->GetExpiration () / 1000); // expiration in seconds
memcpy (payload + 10, msg->GetPayload (), msg->GetPayloadLength ());
len += cloveSize + 3;
payload += cloveSize;
// padding
int delta = (int)optimalSize - (int)len;
if (delta < 0 || delta > 3) // don't create padding if we are close to optimal size
{
uint8_t paddingSize = rand () & 0x0F; // 0 - 15
if (delta > 3)
{
delta -= 3;
if (paddingSize > delta) paddingSize %= delta;
}
payload[0] = eECIESx25519BlkPadding;
htobe16buf (payload + 1, paddingSize);
if (paddingSize) memset (payload + 3, 0, paddingSize);
len += paddingSize + 3;
}
return len;
}
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
{
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0
size_t offset = 0;
memcpy (buf + offset, &tag, 8); offset += 8;
auto payload = buf + offset;
uint16_t cloveSize = msg->GetPayloadLength () + 9 + 1;
size_t len = cloveSize + 3;
payload[0] = eECIESx25519BlkGalicClove; // clove type
htobe16buf (payload + 1, cloveSize); // size
payload += 3;
*payload = 0; payload++; // flag and delivery instructions
*payload = msg->GetTypeID (); // I2NP msg type
htobe32buf (payload + 1, msg->GetMsgID ()); // msgID
htobe32buf (payload + 5, msg->GetExpiration () / 1000); // expiration in seconds
memcpy (payload + 9, msg->GetPayload (), msg->GetPayloadLength ());
if (!i2p::crypto::AEADChaCha20Poly1305 (buf + offset, len, buf, 8, key, nonce, buf + offset, len + 16, true)) // encrypt
size_t len = CreateGarlicPayload (msg, payload, false, 956); // 1003 - 8 tag - 16 Poly1305 hash - 16 I2NP header - 4 garlic length - 3 local tunnel delivery
uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, buf, 8, key, nonce, payload, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return nullptr;
}
offset += len + 16;
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
return m;
}
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey)
{
// Noise_N, we are Alice, routerPublicKey is Bob's
i2p::crypto::NoiseSymmetricState noiseState;
i2p::crypto::InitNoiseNState (noiseState, routerPublicKey);
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
size_t offset = 0;
auto ephemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
memcpy (buf + offset, ephemeralKeys->GetPublicKey (), 32);
noiseState.MixHash (buf + offset, 32); // h = SHA256(h || aepk)
offset += 32;
uint8_t sharedSecret[32];
if (!ephemeralKeys->Agree (routerPublicKey, sharedSecret)) // x25519(aesk, bpk)
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return nullptr;
}
noiseState.MixKey (sharedSecret);
auto payload = buf + offset;
size_t len = CreateGarlicPayload (msg, payload, true, 900); // 1003 - 32 eph key - 16 Poly1305 hash - 16 I2NP header - 4 garlic length - 35 router tunnel delivery
uint8_t nonce[12];
memset (nonce, 0, 12);
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, noiseState.m_H, 32, noiseState.m_CK + 32, nonce, payload, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload for router AEAD encryption failed");
return nullptr;
}
offset += len + 16;
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
return m;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -27,7 +27,7 @@ namespace garlic
{
const int ECIESX25519_RESTART_TIMEOUT = 120; // number of second since session creation we can restart session after
const int ECIESX25519_INACTIVITY_TIMEOUT = 90; // number of seconds we receive nothing and should restart if we can
const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after
const int ECIESX25519_SEND_INACTIVITY_TIMEOUT = 5000; // number of milliseconds we can send empty(pyaload only) packet after
const int ECIESX25519_SEND_EXPIRATION_TIMEOUT = 480; // in seconds
const int ECIESX25519_RECEIVE_EXPIRATION_TIMEOUT = 600; // in seconds
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180
@@ -45,7 +45,7 @@ namespace garlic
RatchetTagSet () {};
virtual ~RatchetTagSet () {};
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
uint64_t GetNextSessionTag ();
@@ -56,23 +56,14 @@ namespace garlic
int GetTagSetID () const { return m_TagSetID; };
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
private:
union
{
uint64_t ll[8];
uint8_t buf[64];
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
} m_KeyData;
i2p::data::Tag<64> m_SessionTagKeyData;
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
int m_NextIndex, m_NextSymmKeyIndex;
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
int m_TagSetID = 0;
};
@@ -82,42 +73,43 @@ namespace garlic
{
public:
ReceiveRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session, bool isNS = false):
ReceiveRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session, bool isNS = false):
m_Session (session), m_IsNS (isNS) {};
bool IsNS () const { return m_IsNS; };
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session; };
void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
void SetTrimBehind (int index) { if (index > m_TrimBehindIndex) m_TrimBehindIndex = index; };
int GetTrimBehind () const { return m_TrimBehindIndex; };
void Expire ();
bool IsExpired (uint64_t ts) const;
bool IsExpired (uint64_t ts) const;
virtual bool IsIndexExpired (int index) const;
virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
private:
int m_TrimBehindIndex = 0;
std::shared_ptr<ECIESX25519AEADRatchetSession> m_Session;
bool m_IsNS;
uint64_t m_ExpirationTimestamp = 0;
};
};
class DatabaseLookupTagSet: public ReceiveRatchetTagSet
class SymmetricKeyTagSet: public ReceiveRatchetTagSet
{
public:
DatabaseLookupTagSet (GarlicDestination * destination, const uint8_t * key);
SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key);
bool IsIndexExpired (int index) const { return false; };
bool HandleNextMessage (uint8_t * buf, size_t len, int index);
private:
GarlicDestination * m_Destination;
uint8_t m_Key[32];
};
};
enum ECIESx25519BlockType
{
eECIESx25519BlkDateTime = 0,
@@ -135,7 +127,7 @@ namespace garlic
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession,
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession,
private i2p::crypto::NoiseSymmetricState,
public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
{
@@ -146,8 +138,7 @@ namespace garlic
eSessionStateNewSessionSent,
eSessionStateNewSessionReplySent,
eSessionStateEstablished,
eSessionStateOneTime,
eSessionStateForRouter
eSessionStateOneTime
};
struct DHRatchet
@@ -160,17 +151,16 @@ namespace garlic
public:
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSetNS);
~ECIESX25519AEADRatchetSession ();
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0);
bool HandleNextMessageForRouter (const uint8_t * buf, size_t len);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter = false);
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg);
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
void Terminate () { m_IsTerminated = true; }
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
{
@@ -180,31 +170,35 @@ namespace garlic
bool CheckExpired (uint64_t ts); // true is expired
bool CanBeRestarted (uint64_t ts) const { return ts > m_SessionCreatedTimestamp + ECIESX25519_RESTART_TIMEOUT; }
bool IsInactive (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_INACTIVITY_TIMEOUT && CanBeRestarted (ts); }
bool IsRatchets () const { return true; };
bool IsReadyToSend () const { return m_State != eSessionStateNewSessionSent; };
bool IsTerminated () const { return m_IsTerminated; }
uint64_t GetLastActivityTimestamp () const { return m_LastActivityTimestamp; };
protected:
i2p::crypto::NoiseSymmetricState& GetNoiseState () { return *this; };
void SetNoiseState (const i2p::crypto::NoiseSymmetricState& state) { GetNoiseState () = state; };
void CreateNonce (uint64_t seqn, uint8_t * nonce);
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index);
private:
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
void InitNewSessionTagset (std::shared_ptr<RatchetTagSet> tagsetNsr) const;
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index);
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset, int index);
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<ReceiveRatchetTagSet>& receiveTagset);
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic = true);
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
bool NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
size_t CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first, uint8_t * payload);
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
@@ -226,7 +220,7 @@ namespace garlic
bool m_SendReverseKey = false, m_SendForwardKey = false, m_IsTerminated = false;
std::unique_ptr<DHRatchet> m_NextReceiveRatchet, m_NextSendRatchet;
uint8_t m_PaddingSizes[32], m_NextPaddingSize;
public:
// for HTTP only
@@ -237,8 +231,24 @@ namespace garlic
}
};
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
// single session for all incoming messages
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
{
public:
RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState);
bool HandleNextMessage (const uint8_t * buf, size_t len);
i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; };
private:
i2p::crypto::NoiseSymmetricState m_CurrentNoiseState;
};
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey);
}
}
#endif

View File

@@ -12,6 +12,7 @@
#ifdef _WIN32
#include <shlobj.h>
#include <windows.h>
#include <codecvt>
#endif
#include "Base.h"
@@ -23,6 +24,7 @@ namespace i2p {
namespace fs {
std::string appName = "i2pd";
std::string dataDir = "";
std::string certsDir = "";
#ifdef _WIN32
std::string dirSep = "\\";
#else
@@ -41,16 +43,32 @@ namespace fs {
return dataDir;
}
const std::string & GetCertsDir () {
return certsDir;
}
const std::string GetUTF8DataDir () {
#ifdef _WIN32
boost::filesystem::wpath path (dataDir);
auto loc = boost::filesystem::path::imbue(std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) ); // convert path to UTF-8
auto dataDirUTF8 = path.string();
boost::filesystem::path::imbue(loc); // Return locale settings back
return dataDirUTF8;
#else
return dataDir; // linux, osx, android uses UTF-8 by default
#endif
}
void DetectDataDir(const std::string & cmdline_param, bool isService) {
if (cmdline_param != "") {
dataDir = cmdline_param;
return;
}
#ifdef _WIN32
char localAppData[MAX_PATH];
wchar_t localAppData[MAX_PATH];
// check executable directory first
if(!GetModuleFileName(NULL, localAppData, MAX_PATH))
if(!GetModuleFileNameW(NULL, localAppData, MAX_PATH))
{
#ifdef WIN32_APP
MessageBox(NULL, TEXT("Unable to get application path!"), TEXT("I2Pd: error"), MB_ICONERROR | MB_OK);
@@ -61,14 +79,15 @@ namespace fs {
}
else
{
auto execPath = boost::filesystem::path(localAppData).parent_path();
auto execPath = boost::filesystem::wpath(localAppData).parent_path();
// if config file exists in .exe's folder use it
if(boost::filesystem::exists(execPath/"i2pd.conf")) // TODO: magic string
dataDir = execPath.string ();
else // otherwise %appdata%
{
if(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, localAppData) != S_OK)
dataDir = execPath.string ();
} else // otherwise %appdata%
{
if(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, localAppData) != S_OK)
{
#ifdef WIN32_APP
MessageBox(NULL, TEXT("Unable to get AppData path!"), TEXT("I2Pd: error"), MB_ICONERROR | MB_OK);
@@ -78,7 +97,9 @@ namespace fs {
exit(1);
}
else
dataDir = std::string(localAppData) + "\\" + appName;
{
dataDir = boost::filesystem::wpath(localAppData).string() + "\\" + appName;
}
}
}
return;
@@ -110,6 +131,21 @@ namespace fs {
#endif
}
void SetCertsDir(const std::string & cmdline_certsdir) {
if (cmdline_certsdir != "")
{
if (cmdline_certsdir[cmdline_certsdir.length()-1] == '/')
certsDir = cmdline_certsdir.substr(0, cmdline_certsdir.size()-1); // strip trailing slash
else
certsDir = cmdline_certsdir;
}
else
{
certsDir = i2p::fs::DataDirPath("certificates");
}
return;
}
bool Init() {
if (!boost::filesystem::exists(dataDir))
boost::filesystem::create_directory(dataDir);

View File

@@ -75,6 +75,12 @@ namespace fs {
/** @brief Returns datadir path */
const std::string & GetDataDir();
/** @brief Returns certsdir path */
const std::string & GetCertsDir();
/** @brief Returns datadir path in UTF-8 encoding */
const std::string GetUTF8DataDir();
/**
* @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something>
@@ -87,7 +93,20 @@ namespace fs {
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
*/
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
/**
* @brief Set certsdir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
*
* Examples of autodetected paths:
*
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\certificates
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\certificates
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates
* Unix: /var/lib/i2pd/certificates (system=1) >> ~/.i2pd/ or /tmp/i2pd/certificates
*/
void SetCertsDir(const std::string & cmdline_certsdir);
/**
* @brief Create subdirectories inside datadir

View File

@@ -13,6 +13,7 @@
#include "FS.h"
#include "Log.h"
#include "Family.h"
#include "Config.h"
namespace i2p
{
@@ -98,7 +99,8 @@ namespace data
void Families::LoadCertificates ()
{
std::string certDir = i2p::fs::DataDirPath("certificates", "family");
std::string certDir = i2p::fs::GetCertsDir() + i2p::fs::dirSep + "family";
std::vector<std::string> files;
int numCertificates = 0;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -164,9 +164,7 @@ namespace garlic
RAND_bytes (elGamal.preIV, 32); // Pre-IV
uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv);
BN_CTX * ctx = BN_CTX_new ();
m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx);
BN_CTX_free (ctx);
m_Destination->Encrypt ((uint8_t *)&elGamal, buf);
m_Encryption.SetIV (iv);
buf += 514;
len += 514;
@@ -273,7 +271,7 @@ namespace garlic
(*numCloves)++;
}
}
if (msg) // clove message ifself if presented
if (msg) // clove message itself if presented
{
size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false);
(*numCloves)++;
@@ -433,14 +431,14 @@ namespace garlic
}
GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default
m_NumRatchetInboundTags (0) // 0 means standard
m_PayloadBuffer (nullptr), m_NumRatchetInboundTags (0) // 0 means standard
{
m_Ctx = BN_CTX_new ();
}
GarlicDestination::~GarlicDestination ()
{
BN_CTX_free (m_Ctx);
if (m_PayloadBuffer)
delete[] m_PayloadBuffer;
}
void GarlicDestination::CleanUp ()
@@ -454,7 +452,7 @@ namespace garlic
{
it.second->Terminate ();
it.second->SetOwner (nullptr);
}
}
m_ECIESx25519Sessions.clear ();
m_ECIESx25519Tags.clear ();
}
@@ -471,10 +469,15 @@ namespace garlic
{
uint64_t t;
memcpy (&t, tag, 8);
auto tagset = std::make_shared<DatabaseLookupTagSet>(this, key);
m_ECIESx25519Tags.emplace (t, ECIESX25519AEADRatchetIndexTagset{0, tagset});
}
AddECIESx25519Key (key, t);
}
void GarlicDestination::AddECIESx25519Key (const uint8_t * key, uint64_t tag)
{
auto tagset = std::make_shared<SymmetricKeyTagSet>(this, key);
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{0, tagset});
}
bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
{
AddSessionKey (key, tag);
@@ -487,31 +490,18 @@ namespace garlic
uint32_t length = bufbe32toh (buf);
if (length > msg->GetLength ())
{
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
LogPrint (eLogWarning, "Garlic: Message length ", length, " exceeds I2NP message length ", msg->GetLength ());
return;
}
auto mod = length & 0x0f; // %16
buf += 4; // length
bool found = false;
uint64_t tag;
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
{
// try ECIESx25519 tag
memcpy (&tag, buf, 8);
auto it1 = m_ECIESx25519Tags.find (tag);
if (it1 != m_ECIESx25519Tags.end ())
{
found = true;
if (it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
m_LastTagset = it1->second.tagset;
else
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
m_ECIESx25519Tags.erase (it1);
}
}
// try ECIESx25519 tag
found = HandleECIESx25519TagMessage (buf, length);
if (!found)
{
{
auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
// AES tag might be used even if encryption type is not ElGamal/AES
if (it != m_Tags.end ()) // try AES tag
@@ -529,7 +519,7 @@ namespace garlic
found = true;
}
else
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
LogPrint (eLogWarning, "Garlic: Message length ", length, " is less than 32 bytes");
}
if (!found) // assume new session
{
@@ -537,7 +527,7 @@ namespace garlic
// try ElGamal/AES first if leading block is 514
ElGamalBlock elGamal;
if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
Decrypt (buf, (uint8_t *)&elGamal, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
{
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
uint8_t iv[32]; // IV is first 16 bytes
@@ -552,38 +542,57 @@ namespace garlic
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
if (!session->HandleNextMessage (buf, length, nullptr, 0))
{
// try to gererate more tags for last tagset
if (m_LastTagset && m_LastTagset->GetNextIndex () < 2*ECIESX25519_TAGSET_MAX_NUM_TAGS)
// try to generate more tags for last tagset
if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS))
{
uint64_t missingTag; memcpy (&missingTag, buf, 8);
auto maxTags = std::max (m_NumRatchetInboundTags, ECIESX25519_MAX_NUM_GENERATED_TAGS);
LogPrint (eLogWarning, "Garlic: Trying to generate more ECIES-X25519-AEAD-Ratchet tags");
for (int i = 0; i < maxTags; i++)
{
auto nextTag = AddECIESx25519SessionNextTag (m_LastTagset);
if (!nextTag)
{
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
break;
}
if (nextTag == tag)
}
if (nextTag == missingTag)
{
LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated");
if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[tag].index))
if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[nextTag].index))
found = true;
break;
}
}
}
if (!found) m_LastTagset = nullptr;
}
if (!found)
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
}
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
}
}
else
LogPrint (eLogError, "Garlic: Failed to decrypt message");
}
}
}
}
bool GarlicDestination::HandleECIESx25519TagMessage (uint8_t * buf, size_t len)
{
uint64_t tag;
memcpy (&tag, buf, 8);
auto it = m_ECIESx25519Tags.find (tag);
if (it != m_ECIESx25519Tags.end ())
{
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
m_LastTagset = it->second.tagset;
else
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
m_ECIESx25519Tags.erase (it);
return true;
}
return false;
}
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
@@ -620,7 +629,7 @@ namespace garlic
SHA256 (buf, payloadSize, digest);
if (memcmp (payloadHash, digest, 32)) // payload hash doesn't match
{
LogPrint (eLogError, "Garlic: wrong payload hash");
LogPrint (eLogError, "Garlic: Wrong payload hash");
return;
}
HandleGarlicPayload (buf, payloadSize, from);
@@ -630,7 +639,7 @@ namespace garlic
{
if (len < 1)
{
LogPrint (eLogError, "Garlic: payload is too short");
LogPrint (eLogError, "Garlic: Payload is too short");
return;
}
int numCloves = buf[0];
@@ -645,7 +654,7 @@ namespace garlic
if (flag & 0x80) // encrypted?
{
// TODO: implement
LogPrint (eLogWarning, "Garlic: clove encrypted");
LogPrint (eLogWarning, "Garlic: Clove encrypted");
buf += 32;
}
ptrdiff_t offset = buf - buf1;
@@ -653,35 +662,35 @@ namespace garlic
switch (deliveryType)
{
case eGarlicDeliveryTypeLocal:
LogPrint (eLogDebug, "Garlic: type local");
LogPrint (eLogDebug, "Garlic: Type local");
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
HandleI2NPMessage (buf, len - offset);
break;
case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination");
LogPrint (eLogDebug, "Garlic: Type destination");
buf += 32; // destination. check it later or for multiple destinations
offset = buf - buf1;
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
HandleI2NPMessage (buf, len - offset);
break;
case eGarlicDeliveryTypeTunnel:
{
LogPrint (eLogDebug, "Garlic: type tunnel");
LogPrint (eLogDebug, "Garlic: Type tunnel");
// gwHash and gwTunnel sequence is reverted
uint8_t * gwHash = buf;
buf += 32;
offset = buf - buf1;
if (offset + 4 > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
uint32_t gwTunnel = bufbe32toh (buf);
@@ -712,22 +721,22 @@ namespace garlic
{
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
i2p::transport::transports.SendMessage (ident,
CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
}
else
LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported");
LogPrint (eLogWarning, "Garlic: Type router for inbound tunnels not supported");
break;
}
default:
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
LogPrint (eLogWarning, "Garlic: Unknown delivery type ", (int)deliveryType);
}
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
@@ -737,7 +746,7 @@ namespace garlic
offset = buf - buf1;
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: clove is too long");
LogPrint (eLogError, "Garlic: Clove is too long");
break;
}
len -= offset;
@@ -748,16 +757,12 @@ namespace garlic
std::shared_ptr<I2NPMessage> msg)
{
if (router->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{
auto session = std::make_shared<ECIESX25519AEADRatchetSession>(this, false);
session->SetRemoteStaticKey (router->GetIdentity ()->GetEncryptionPublicKey ());
return session->WrapOneTimeMessage (msg, true);
}
return WrapECIESX25519MessageForRouter (msg, router->GetIdentity ()->GetEncryptionPublicKey ());
else
{
{
auto session = GetRoutingSession (router, false);
return session->WrapSingleMessage (msg);
}
}
}
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
@@ -768,17 +773,17 @@ namespace garlic
{
ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32];
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
destination->Encrypt (nullptr, staticKey); // we are supposed to get static key
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
{
{
session = it->second;
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
{
LogPrint (eLogDebug, "Garlic: session restarted");
LogPrint (eLogDebug, "Garlic: Session restarted");
session = nullptr;
}
}
}
}
if (!session)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
@@ -835,7 +840,7 @@ namespace garlic
it->second->GetSharedRoutingPath (); // delete shared path if necessary
if (!it->second->CleanupExpiredTags ())
{
LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted");
LogPrint (eLogInfo, "Garlic: Routing session to ", it->first.ToBase32 (), " deleted");
it->second->SetOwner (nullptr);
it = m_Sessions.erase (it);
}
@@ -874,14 +879,18 @@ namespace garlic
it->second.tagset->DeleteSymmKey (it->second.index);
it = m_ECIESx25519Tags.erase (it);
numExpiredTags++;
}
}
else
{
auto session = it->second.tagset->GetSession ();
if (!session || session->IsTerminated())
it->second.tagset->Expire ();
++it;
}
{
it = m_ECIESx25519Tags.erase (it);
numExpiredTags++;
}
else
++it;
}
}
if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
@@ -916,7 +925,7 @@ namespace garlic
if (session)
{
session->MessageConfirmed (msgID);
LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged");
LogPrint (eLogDebug, "Garlic: Message ", msgID, " acknowledged");
}
}
@@ -1021,7 +1030,7 @@ namespace garlic
switch (deliveryType)
{
case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination");
LogPrint (eLogDebug, "Garlic: Type destination");
buf += 32; // TODO: check destination
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
@@ -1029,37 +1038,39 @@ namespace garlic
// no break here
case eGarlicDeliveryTypeLocal:
{
LogPrint (eLogDebug, "Garlic: type local");
LogPrint (eLogDebug, "Garlic: Type local");
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration
int32_t msgID = bufbe32toh (buf); buf += 4; // msgID
buf += 4; // expiration
ptrdiff_t offset = buf - buf1;
if (offset <= (int)len)
HandleCloveI2NPMessage (typeID, buf, len - offset);
HandleCloveI2NPMessage (typeID, buf, len - offset, msgID);
else
LogPrint (eLogError, "Garlic: clove is too long");
LogPrint (eLogError, "Garlic: Clove is too long");
break;
}
case eGarlicDeliveryTypeTunnel:
{
LogPrint (eLogDebug, "Garlic: type tunnel");
LogPrint (eLogDebug, "Garlic: Type tunnel");
// gwHash and gwTunnel sequence is reverted
const uint8_t * gwHash = buf;
buf += 32;
ptrdiff_t offset = buf - buf1;
if (offset + 13 > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
buf += (4 + 4); // msgID + expiration
uint32_t msgID = bufbe32toh (buf); buf += 4; // msgID
buf += 4; // expiration
offset += 13;
if (GetTunnelPool ())
{
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel)
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID));
else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
}
@@ -1068,7 +1079,7 @@ namespace garlic
break;
}
default:
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
LogPrint (eLogWarning, "Garlic: Unexpected delivery type ", (int)deliveryType);
}
}
@@ -1088,13 +1099,13 @@ namespace garlic
if (it != m_ECIESx25519Sessions.end ())
{
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
{
{
it->second->Terminate (); // detach
m_ECIESx25519Sessions.erase (it);
}
}
else
{
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
return;
}
}
@@ -1110,5 +1121,12 @@ namespace garlic
m_ECIESx25519Sessions.erase (it);
}
}
uint8_t * GarlicDestination::GetPayloadBuffer ()
{
if (!m_PayloadBuffer)
m_PayloadBuffer = new uint8_t[I2NP_MAX_MESSAGE_SIZE];
return m_PayloadBuffer;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -115,7 +115,7 @@ namespace garlic
virtual bool MessageConfirmed (uint32_t msgID);
virtual bool IsRatchets () const { return false; };
virtual bool IsReadyToSend () const { return true; };
virtual bool IsTerminated () const { return !GetOwner (); };
virtual bool IsTerminated () const { return !GetOwner (); };
virtual uint64_t GetLastActivityTimestamp () const { return 0; }; // non-zero for rathets only
void SetLeaseSetUpdated ()
@@ -243,13 +243,14 @@ namespace garlic
std::shared_ptr<I2NPMessage> msg);
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
void AddECIESx25519Key (const uint8_t * key, uint64_t tag); // one tag
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
void RemoveECIESx25519Session (const uint8_t * staticKey);
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
uint8_t * GetPayloadBuffer ();
virtual void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
virtual void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
@@ -260,8 +261,10 @@ namespace garlic
protected:
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
bool HandleECIESx25519TagMessage (uint8_t * buf, size_t len); // return true if found
virtual void HandleI2NPMessage (const uint8_t * buf, size_t len) = 0; // called from clove only
virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) = 0;
virtual bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len, uint32_t msgID) = 0;
void HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg);
void HandleDeliveryStatusMessage (uint32_t msgID);
@@ -276,12 +279,12 @@ namespace garlic
private:
BN_CTX * m_Ctx; // incoming
// outgoing sessions
int m_NumTags;
std::mutex m_SessionsMutex;
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
uint8_t * m_PayloadBuffer; // for ECIESX25519AEADRatchet
// incoming
int m_NumRatchetInboundTags;
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -9,12 +9,15 @@
#include <algorithm>
#include <utility>
#include <stdio.h>
#include "util.h"
#include "HTTP.h"
#include <ctime>
#include "util.h"
#include "Base.h"
#include "HTTP.h"
namespace i2p {
namespace http {
namespace i2p
{
namespace http
{
const std::vector<std::string> HTTP_METHODS = {
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
"COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "SEARCH" // WebDAV methods, for SEARCH see rfc5323
@@ -184,6 +187,8 @@ namespace http {
params.clear();
for (const auto& it : tokens) {
if (!it.length()) // empty
continue;
std::size_t eq = it.find ('=');
if (eq != std::string::npos) {
auto e = std::pair<std::string, std::string>(it.substr(0, eq), it.substr(eq + 1));
@@ -471,12 +476,15 @@ namespace http {
return ptr;
}
std::string UrlDecode(const std::string& data, bool allow_null) {
std::string UrlDecode(const std::string& data, bool allow_null)
{
std::string decoded(data);
size_t pos = 0;
while ((pos = decoded.find('%', pos)) != std::string::npos) {
while ((pos = decoded.find('%', pos)) != std::string::npos)
{
char c = strtol(decoded.substr(pos + 1, 2).c_str(), NULL, 16);
if (c == '\0' && !allow_null) {
if (c == '\0' && !allow_null)
{
pos += 3;
continue;
}
@@ -486,9 +494,11 @@ namespace http {
return decoded;
}
bool MergeChunkedResponse (std::istream& in, std::ostream& out) {
bool MergeChunkedResponse (std::istream& in, std::ostream& out)
{
std::string hexLen;
while (!in.eof ()) {
while (!in.eof ())
{
std::getline (in, hexLen);
errno = 0;
long int len = strtoul(hexLen.c_str(), (char **) NULL, 16);
@@ -506,5 +516,12 @@ namespace http {
}
return true;
}
std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass)
{
if (user.empty () && pass.empty ()) return "";
return "Basic " + i2p::data::ToBase64Standard (user + ":" + pass);
}
} // http
} // i2p

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -166,6 +166,9 @@ namespace http
* @return true on success, false otherwise
*/
bool MergeChunkedResponse (std::istream& in, std::ostream& out);
std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass);
} // http
} // i2p

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -18,6 +18,7 @@
#include "Tunnel.h"
#include "Transports.h"
#include "Garlic.h"
#include "ECIESX25519AEADRatchetSession.h"
#include "I2NPProtocol.h"
#include "version.h"
@@ -35,11 +36,9 @@ namespace i2p
return std::make_shared<I2NPMessageBuffer<I2NP_MAX_SHORT_MESSAGE_SIZE> >();
}
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage ()
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
{
auto msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12
msg->Align (12);
return std::shared_ptr<I2NPMessage>(msg);
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
}
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
@@ -76,7 +75,7 @@ namespace i2p
{
auto msg = NewI2NPMessage (len);
if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length ", msg->maxLen);
LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length ", msg->maxLen);
msg->FillI2NPMessageHeader (msgType, replyMsgID);
return msg;
}
@@ -91,7 +90,7 @@ namespace i2p
msg->from = from;
}
else
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length");
LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length");
return msg;
}
@@ -171,8 +170,8 @@ namespace i2p
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
const uint8_t * replyTag, bool replyECIES)
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
const uint8_t * replyTag, bool replyECIES)
{
int cnt = excludedFloodfills.size ();
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
@@ -210,12 +209,12 @@ namespace i2p
{
memcpy (buf + 33, replyTag, 8); // 8 bytes tag
buf += 41;
}
else
{
}
else
{
memcpy (buf + 33, replyTag, 32); // 32 bytes tag
buf += 65;
}
}
m->len += (buf - m->GetPayload ());
m->FillI2NPMessageHeader (eI2NPDatabaseLookup);
@@ -244,12 +243,18 @@ namespace i2p
return m;
}
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
{
if (!router) // we send own RouterInfo
router = context.GetSharedRouterInfo ();
if (!router->GetBuffer ())
{
LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore");
return nullptr;
}
auto m = NewI2NPShortMessage ();
uint8_t * payload = m->GetPayload ();
@@ -267,12 +272,12 @@ namespace i2p
buf += 32; // reply tunnel gateway
}
else
{
{
memset (buf, 0, 4); // zero tunnelID means direct reply
buf += 4;
memcpy (buf, context.GetIdentHash (), 32);
buf += 32;
}
}
}
uint8_t * sizePtr = buf;
@@ -285,7 +290,7 @@ namespace i2p
{
i2p::data::GzipDeflator deflator;
size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len);
}
}
if (size)
{
htobe16buf (sizePtr, size); // size
@@ -363,7 +368,7 @@ namespace i2p
return g_MaxNumTransitTunnels;
}
bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
static bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
{
for (int i = 0; i < num; i++)
{
@@ -371,83 +376,52 @@ namespace i2p
if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
{
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
BN_CTX * ctx = BN_CTX_new ();
bool success = i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
BN_CTX_free (ctx);
if(!success) return false;
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
uint8_t retCode = 0;
bool isECIES = i2p::context.IsECIES ();
// replace record to reply
if (i2p::context.AcceptsTunnels () &&
i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels &&
!i2p::transport::transports.IsBandwidthExceeded () &&
!i2p::transport::transports.IsTransitBandwidthExceeded ())
{
auto transitTunnel = isECIES ?
i2p::tunnel::CreateTransitTunnel (
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
clearText + ECIES_BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) :
i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40);
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
}
else
retCode = 30; // always reject with bandwidth reason (30)
if (isECIES)
{
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
}
else
{
record[BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
SHA256 (record + BUILD_RESPONSE_RECORD_PADDING_OFFSET, BUILD_RESPONSE_RECORD_PADDING_SIZE + 1, // + 1 byte of ret
record + BUILD_RESPONSE_RECORD_HASH_OFFSET);
}
memset (record + ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
record[ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET] = retCode;
// encrypt reply
i2p::crypto::CBCEncryption encryption;
for (int j = 0; j < num; j++)
{
uint8_t * reply = records + j*TUNNEL_BUILD_RECORD_SIZE;
if (isECIES)
{
if (j == i)
if (j == i)
{
uint8_t nonce[12];
memset (nonce, 0, 12);
auto& noiseState = i2p::context.GetCurrentNoiseState ();
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState.m_H, 32, noiseState.m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{
uint8_t nonce[12];
memset (nonce, 0, 12);
auto noiseState = std::move (i2p::context.GetCurrentNoiseState ());
if (!noiseState || !i2p::crypto::AEADChaCha20Poly1305 (reply, TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState->m_H, 32, noiseState->m_CK, nonce, reply, TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{
LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
return false;
}
LogPrint (eLogWarning, "I2NP: Reply AEAD encryption failed");
return false;
}
else
{
encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply);
}
}
else
{
encryption.SetKey (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
encryption.SetIV (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET);
encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET);
encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply);
}
}
}
return true;
}
@@ -455,13 +429,13 @@ namespace i2p
return false;
}
void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
static void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "VaribleTunnelBuild message of ", num, " records is too short ", len);
LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len);
return;
}
@@ -484,84 +458,38 @@ namespace i2p
}
else
{
if (i2p::context.IsECIES ())
uint8_t clearText[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (HandleBuildRequestRecords (num, buf + 1, clearText))
{
uint8_t clearText[ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (HandleBuildRequestRecords (num, buf + 1, clearText))
if (clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) // we are endpoint of outboud tunnel
{
if (clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outboud tunnel
{
// so we send it to reply tunnel
transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPVariableTunnelBuildReply, buf, len,
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
else
transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
// so we send it to reply tunnel
transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPVariableTunnelBuildReply, buf, len,
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
else
transports.SendMessage (clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
else
{
uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (HandleBuildRequestRecords (num, buf + 1, clearText))
{
if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outboud tunnel
{
// so we send it to reply tunnel
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPVariableTunnelBuildReply, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
else
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
}
}
}
void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
static void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
{
if (i2p::context.IsECIES ())
{
LogPrint (eLogWarning, "TunnelBuild is too old for ECIES router");
return;
}
if (len < NUM_TUNNEL_BUILD_RECORDS*TUNNEL_BUILD_RECORD_SIZE)
{
LogPrint (eLogError, "TunnelBuild message is too short ", len);
return;
}
uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, buf, clearText))
{
if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outbound tunnel
{
// so we send it to reply tunnel
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
eI2NPTunnelBuildReply, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
else
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPTunnelBuild, buf, len,
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
}
LogPrint (eLogWarning, "I2NP: TunnelBuild is too old for ECIES router");
}
void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
static void HandleTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len, bool isShort)
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: VariableTunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1)
LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
if (len < num*recordSize + 1)
{
LogPrint (eLogError, "VaribleTunnelBuildReply message of ", num, " records is too short ", len);
LogPrint (eLogError, "I2NP: TunnelBuildReply message of ", num, " records is too short ", len);
return;
}
@@ -585,10 +513,148 @@ namespace i2p
LogPrint (eLogWarning, "I2NP: Pending tunnel for message ", replyMsgID, " not found");
}
static void HandleShortTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len);
return;
}
auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
if (tunnel)
{
// endpoint of inbound tunnel
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild reply for tunnel ", tunnel->GetTunnelID ());
if (tunnel->HandleTunnelBuildResponse (buf, len))
{
LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created");
tunnel->SetState (i2p::tunnel::eTunnelStateEstablished);
i2p::tunnel::tunnels.AddInboundTunnel (tunnel);
}
else
{
LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined");
tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed);
}
return;
}
const uint8_t * record = buf + 1;
for (int i = 0; i < num; i++)
{
if (!memcmp (record, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
{
LogPrint (eLogDebug, "I2NP: Short request record ", i, " is ours");
uint8_t clearText[SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE];
if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
{
LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i);
return;
}
if (clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE]) // not AES
{
LogPrint (eLogWarning, "I2NP: Unknown layer encryption type ", clearText[SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE], " in short request record");
return;
}
auto& noiseState = i2p::context.GetCurrentNoiseState ();
uint8_t replyKey[32], layerKey[32], ivKey[32];
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
memcpy (replyKey, noiseState.m_CK + 32, 32);
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);
memcpy (layerKey, noiseState.m_CK + 32, 32);
bool isEndpoint = clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG;
if (isEndpoint)
{
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "TunnelLayerIVKey", noiseState.m_CK);
memcpy (ivKey, noiseState.m_CK + 32, 32);
}
else
memcpy (ivKey, noiseState.m_CK , 32);
// check if we accept this tunnel
uint8_t retCode = 0;
if (!i2p::context.AcceptsTunnels () ||
i2p::tunnel::tunnels.GetTransitTunnels ().size () > g_MaxNumTransitTunnels ||
i2p::transport::transports.IsBandwidthExceeded () ||
i2p::transport::transports.IsTransitBandwidthExceeded ())
retCode = 30;
if (!retCode)
{
// create new transit tunnel
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
layerKey, ivKey,
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
}
// encrypt reply
uint8_t nonce[12];
memset (nonce, 0, 12);
uint8_t * reply = buf + 1;
for (int j = 0; j < num; j++)
{
nonce[4] = j; // nonce is record #
if (j == i)
{
memset (reply + SHORT_RESPONSE_RECORD_OPTIONS_OFFSET, 0, 2); // no options
reply[SHORT_RESPONSE_RECORD_RET_OFFSET] = retCode;
if (!i2p::crypto::AEADChaCha20Poly1305 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE - 16,
noiseState.m_H, 32, replyKey, nonce, reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, true)) // encrypt
{
LogPrint (eLogWarning, "I2NP: Short reply AEAD encryption failed");
return;
}
}
else
i2p::crypto::ChaCha20 (reply, SHORT_TUNNEL_BUILD_RECORD_SIZE, replyKey, nonce, reply);
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
}
// send reply
if (isEndpoint)
{
auto replyMsg = NewI2NPShortMessage ();
replyMsg->Concat (buf, len);
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
{
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "RGarlicKeyAndTag", noiseState.m_CK);
uint64_t tag;
memcpy (&tag, noiseState.m_CK, 8);
// we send it to reply tunnel
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
}
else
{
// IBGW is local
uint32_t tunnelID = bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET);
auto tunnel = i2p::tunnel::tunnels.GetTunnel (tunnelID);
if (tunnel)
tunnel->SendTunnelDataMsg (replyMsg);
else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
}
}
else
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
return;
}
record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
}
}
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf)
{
auto msg = NewI2NPTunnelMessage ();
auto msg = NewI2NPTunnelMessage (false);
msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE);
msg->FillI2NPMessageHeader (eI2NPTunnelData);
return msg;
@@ -596,7 +662,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload)
{
auto msg = NewI2NPTunnelMessage ();
auto msg = NewI2NPTunnelMessage (false);
htobe32buf (msg->GetPayload (), tunnelID);
msg->len += 4; // tunnelID
msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4);
@@ -604,9 +670,9 @@ namespace i2p
return msg;
}
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg ()
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg (bool endpoint)
{
auto msg = NewI2NPTunnelMessage ();
auto msg = NewI2NPTunnelMessage (endpoint);
msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE;
return msg;
}
@@ -619,7 +685,7 @@ namespace i2p
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
msg->len += TUNNEL_GATEWAY_HEADER_SIZE;
if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen);
LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
return msg;
}
@@ -650,7 +716,7 @@ namespace i2p
msg->offset += gatewayMsgOffset;
msg->len += gatewayMsgOffset;
if (msg->Concat (buf, len) < len)
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen);
LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
len = msg->GetLength ();
msg->offset -= gatewayMsgOffset;
@@ -665,13 +731,13 @@ namespace i2p
{
if (len < I2NP_HEADER_SIZE_OFFSET + 2)
{
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header");
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return len;
}
auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
if (l > len)
{
LogPrint (eLogError, "I2NP: message length ", l, " exceeds buffer length ", len);
LogPrint (eLogError, "I2NP: Message length ", l, " exceeds buffer length ", len);
l = len;
}
return l;
@@ -681,18 +747,18 @@ namespace i2p
{
if (len < I2NP_HEADER_SIZE)
{
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header");
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return;
}
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + I2NP_HEADER_SIZE;
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
len -= I2NP_HEADER_SIZE;
if (size > len)
{
LogPrint (eLogError, "I2NP: payload size ", size, " exceeds buffer length ", len);
LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
size = len;
}
switch (typeID)
@@ -700,8 +766,14 @@ namespace i2p
case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPVariableTunnelBuildReply:
HandleVariableTunnelBuildReplyMsg (msgID, buf, size);
HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size);
@@ -759,6 +831,8 @@ namespace i2p
case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply:
// forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
@@ -773,7 +847,7 @@ namespace i2p
Flush ();
}
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage>&& msg)
{
if (msg)
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -55,32 +55,12 @@ namespace i2p
// TunnelBuild
const size_t TUNNEL_BUILD_RECORD_SIZE = 528;
//BuildRequestRecordClearText
const size_t BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET = 0;
const size_t BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET = BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET + 4;
const size_t BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET = BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET + 32;
const size_t BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET = BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET + 4;
const size_t BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET = BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET + 32;
const size_t BUILD_REQUEST_RECORD_IV_KEY_OFFSET = BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET + 32;
const size_t BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET = BUILD_REQUEST_RECORD_IV_KEY_OFFSET + 32;
const size_t BUILD_REQUEST_RECORD_REPLY_IV_OFFSET = BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET + 32;
const size_t BUILD_REQUEST_RECORD_FLAG_OFFSET = BUILD_REQUEST_RECORD_REPLY_IV_OFFSET + 16;
const size_t BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET = BUILD_REQUEST_RECORD_FLAG_OFFSET + 1;
const size_t BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET = BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4;
const size_t BUILD_REQUEST_RECORD_PADDING_OFFSET = BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET + 4;
const size_t BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE = 222;
const size_t SHORT_TUNNEL_BUILD_RECORD_SIZE = 218;
// BuildRequestRecordEncrypted
const size_t BUILD_REQUEST_RECORD_TO_PEER_OFFSET = 0;
const size_t BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET = BUILD_REQUEST_RECORD_TO_PEER_OFFSET + 16;
// BuildResponseRecord
const size_t BUILD_RESPONSE_RECORD_HASH_OFFSET = 0;
const size_t BUILD_RESPONSE_RECORD_PADDING_OFFSET = 32;
const size_t BUILD_RESPONSE_RECORD_PADDING_SIZE = 495;
const size_t BUILD_RESPONSE_RECORD_RET_OFFSET = BUILD_RESPONSE_RECORD_PADDING_OFFSET + BUILD_RESPONSE_RECORD_PADDING_SIZE;
// ECIES BuildRequestRecordClearText
const size_t ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET = 0;
const size_t ECIES_BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET = ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET + 4;
@@ -100,7 +80,25 @@ namespace i2p
// ECIES BuildResponseRecord
const size_t ECIES_BUILD_RESPONSE_RECORD_OPTIONS_OFFSET = 0;
const size_t ECIES_BUILD_RESPONSE_RECORD_RET_OFFSET = 511;
// ShortRequestRecordClearText
const size_t SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET = 16;
const size_t SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET = 0;
const size_t SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET = SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET + 4;
const size_t SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET = SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET + 4;
const size_t SHORT_REQUEST_RECORD_FLAG_OFFSET = SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET + 32;
const size_t SHORT_REQUEST_RECORD_MORE_FLAGS_OFFSET = SHORT_REQUEST_RECORD_FLAG_OFFSET + 1;
const size_t SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE = SHORT_REQUEST_RECORD_MORE_FLAGS_OFFSET + 2;
const size_t SHORT_REQUEST_RECORD_REQUEST_TIME_OFFSET = SHORT_REQUEST_RECORD_LAYER_ENCRYPTION_TYPE + 1;
const size_t SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET = SHORT_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4;
const size_t SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET = SHORT_REQUEST_RECORD_REQUEST_EXPIRATION_OFFSET + 4;
const size_t SHORT_REQUEST_RECORD_PADDING_OFFSET = SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET + 4;
const size_t SHORT_REQUEST_RECORD_CLEAR_TEXT_SIZE = 154;
// ShortResponseRecord
const size_t SHORT_RESPONSE_RECORD_OPTIONS_OFFSET = 0;
const size_t SHORT_RESPONSE_RECORD_RET_OFFSET = 201;
enum I2NPMessageType
{
eI2NPDummyMsg = 0,
@@ -115,9 +113,13 @@ namespace i2p
eI2NPTunnelBuild = 21,
eI2NPTunnelBuildReply = 22,
eI2NPVariableTunnelBuild = 23,
eI2NPVariableTunnelBuildReply = 24
eI2NPVariableTunnelBuildReply = 24,
eI2NPShortTunnelBuild = 25,
eI2NPShortTunnelBuildReply = 26
};
const uint8_t TUNNEL_BUILD_RECORD_GATEWAY_FLAG = 0x80;
const uint8_t TUNNEL_BUILD_RECORD_ENDPOINT_FLAG = 0x40;
const int NUM_TUNNEL_BUILD_RECORDS = 8;
// DatabaseLookup flags
@@ -260,7 +262,7 @@ namespace tunnel
std::shared_ptr<I2NPMessage> NewI2NPMessage ();
std::shared_ptr<I2NPMessage> NewI2NPShortMessage ();
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage ();
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint);
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len);
std::shared_ptr<I2NPMessage> CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0);
@@ -271,8 +273,8 @@ namespace tunnel
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
@@ -281,14 +283,9 @@ namespace tunnel
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken = 0, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel = nullptr);
bool IsRouterInfoMsg (std::shared_ptr<I2NPMessage> msg);
bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText);
void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len);
void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len);
void HandleTunnelBuildMsg (uint8_t * buf, size_t len);
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (const uint8_t * buf);
std::shared_ptr<I2NPMessage> CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload);
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg ();
std::shared_ptr<I2NPMessage> CreateEmptyTunnelDataMsg (bool endpoint);
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len);
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType,
@@ -304,7 +301,7 @@ namespace tunnel
public:
~I2NPMessagesHandler ();
void PutNextMessage (std::shared_ptr<I2NPMessage> msg);
void PutNextMessage (std::shared_ptr<I2NPMessage>&& msg);
void Flush ();
private:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -50,42 +50,3 @@ uint64_t be64toh(uint64_t big64)
return u64.raw_value;
}
#endif
/* it can be used in Windows 8
#include <Winsock2.h>
uint16_t htobe16(uint16_t int16)
{
return htons(int16);
}
uint32_t htobe32(uint32_t int32)
{
return htonl(int32);
}
uint64_t htobe64(uint64_t int64)
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/jj710199%28v=vs.85%29.aspx
//return htonll(int64);
return 0;
}
uint16_t be16toh(uint16_t big16)
{
return ntohs(big16);
}
uint32_t be32toh(uint32_t big32)
{
return ntohl(big32);
}
uint64_t be64toh(uint64_t big64)
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/jj710199%28v=vs.85%29.aspx
//return ntohll(big64);
return 0;
}
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -13,10 +13,11 @@
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
#include <endian.h>
#elif defined(__APPLE__) && defined(__MACH__)
#elif defined(__APPLE__) && defined(__MACH__)
#include <libkern/OSByteOrder.h>
#define htobe16(x) OSSwapHostToBigInt16(x)
@@ -34,6 +35,22 @@
#define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(_WIN32)
#define htobe16(x) __builtin_bswap16(x)
#define htole16(x) (x)
#define be16toh(x) __builtin_bswap16(x)
#define le16toh(x) (x)
#define htobe32(x) __builtin_bswap32(x)
#define htole32(x) (x)
#define be32toh(x) __builtin_bswap32(x)
#define le32toh(x) (x)
#define htobe64(x) __builtin_bswap64(x)
#define htole64(x) (x)
#define be64toh(x) __builtin_bswap64(x)
#define le64toh(x) (x)
#else
#define NEEDS_LOCAL_ENDIAN
#include <cstdint>

View File

@@ -19,7 +19,8 @@ namespace data
Identity& Identity::operator=(const Keys& keys)
{
// copy public and signing keys together
memcpy (publicKey, keys.publicKey, sizeof (publicKey) + sizeof (signingKey));
memcpy (publicKey, keys.publicKey, sizeof (publicKey));
memcpy (signingKey, keys.signingKey, sizeof (signingKey));
memset (certificate, 0, sizeof (certificate));
return *this;
}
@@ -42,7 +43,7 @@ namespace data
}
IdentityEx::IdentityEx ():
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
m_ExtendedLen (0)
{
}
@@ -52,9 +53,9 @@ namespace data
{
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
}
else
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
}
else
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{
size_t excessLen = 0;
@@ -119,11 +120,15 @@ namespace data
m_StandardIdentity.certificate[0] = CERTIFICATE_TYPE_KEY;
htobe16buf (m_StandardIdentity.certificate + 1, m_ExtendedLen);
// fill extended buffer
m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
htobe16buf (m_ExtendedBuffer, type);
htobe16buf (m_ExtendedBuffer + 2, cryptoType);
if (excessLen && excessBuf)
{
if (excessLen > MAX_EXTENDED_BUFFER_SIZE - 4)
{
LogPrint (eLogError, "Identity: Unexpected excessive signing key len ", excessLen);
excessLen = MAX_EXTENDED_BUFFER_SIZE - 4;
}
memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen);
delete[] excessBuf;
}
@@ -136,7 +141,6 @@ namespace data
memset (m_StandardIdentity.certificate, 0, sizeof (m_StandardIdentity.certificate));
m_IdentHash = m_StandardIdentity.Hash ();
m_ExtendedLen = 0;
m_ExtendedBuffer = nullptr;
}
CreateVerifier ();
}
@@ -154,26 +158,25 @@ namespace data
}
IdentityEx::IdentityEx (const uint8_t * buf, size_t len):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
m_ExtendedLen (0)
{
FromBuffer (buf, len);
}
IdentityEx::IdentityEx (const IdentityEx& other):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
m_ExtendedLen (0)
{
*this = other;
}
IdentityEx::IdentityEx (const Identity& standard):
m_ExtendedLen (0), m_ExtendedBuffer (nullptr)
m_ExtendedLen (0)
{
*this = standard;
}
IdentityEx::~IdentityEx ()
{
delete[] m_ExtendedBuffer;
delete m_Verifier;
}
@@ -182,15 +185,12 @@ namespace data
memcpy (&m_StandardIdentity, &other.m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
m_IdentHash = other.m_IdentHash;
delete[] m_ExtendedBuffer;
m_ExtendedLen = other.m_ExtendedLen;
if (m_ExtendedLen > 0)
{
m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE;
memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen);
}
else
m_ExtendedBuffer = nullptr;
delete m_Verifier;
m_Verifier = nullptr;
@@ -203,8 +203,6 @@ namespace data
m_StandardIdentity = standard;
m_IdentHash = m_StandardIdentity.Hash ();
delete[] m_ExtendedBuffer;
m_ExtendedBuffer = nullptr;
m_ExtendedLen = 0;
delete m_Verifier;
@@ -217,20 +215,17 @@ namespace data
{
if (len < DEFAULT_IDENTITY_SIZE)
{
LogPrint (eLogError, "Identity: buffer length ", len, " is too small");
LogPrint (eLogError, "Identity: Buffer length ", len, " is too small");
return 0;
}
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
if(m_ExtendedBuffer) delete[] m_ExtendedBuffer;
m_ExtendedBuffer = nullptr;
m_ExtendedLen = bufbe16toh (m_StandardIdentity.certificate + 1);
if (m_ExtendedLen)
{
if (m_ExtendedLen + DEFAULT_IDENTITY_SIZE <= len)
{
m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE;
memcpy (m_ExtendedBuffer, buf + DEFAULT_IDENTITY_SIZE, m_ExtendedLen);
}
else
@@ -241,10 +236,7 @@ namespace data
}
}
else
{
m_ExtendedLen = 0;
m_ExtendedBuffer = nullptr;
}
SHA256(buf, GetFullLen (), m_IdentHash);
delete m_Verifier;
@@ -258,7 +250,7 @@ namespace data
const size_t fullLen = GetFullLen();
if (fullLen > len) return 0; // buffer is too small and may overflow somewhere else
memcpy (buf, &m_StandardIdentity, DEFAULT_IDENTITY_SIZE);
if (m_ExtendedLen > 0 && m_ExtendedBuffer)
if (m_ExtendedLen > 0)
memcpy (buf + DEFAULT_IDENTITY_SIZE, m_ExtendedBuffer, m_ExtendedLen);
return fullLen;
}
@@ -488,7 +480,7 @@ namespace data
size_t ret = m_Public->FromBuffer (buf, len);
auto cryptoKeyLen = GetPrivateKeyLen ();
if (!ret || ret + cryptoKeyLen > len) return 0; // overflow
memcpy (m_PrivateKey, buf + ret, cryptoKeyLen);
memcpy (m_PrivateKey, buf + ret, cryptoKeyLen);
ret += cryptoKeyLen;
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen ();
if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow
@@ -517,7 +509,7 @@ namespace data
if (m_Public->GetSignatureLen () + ret > len) return 0;
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
{
LogPrint (eLogError, "Identity: offline signature verification failed");
LogPrint (eLogError, "Identity: Offline signature verification failed");
return 0;
}
ret += m_Public->GetSignatureLen ();
@@ -662,9 +654,9 @@ namespace data
size_t PrivateKeys::GetPrivateKeyLen () const
{
// private key length always 256, but type 4
return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256;
}
return (m_Public->GetCryptoKeyType () == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) ? 32 : 256;
}
uint8_t * PrivateKeys::GetPadding()
{
if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
@@ -689,7 +681,7 @@ namespace data
break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key);
break;
break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
return std::make_shared<i2p::crypto::ECIESP256Decryptor>(key);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2020, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -84,6 +84,7 @@ namespace data
typedef uint16_t SigningKeyType;
typedef uint16_t CryptoKeyType;
const size_t MAX_EXTENDED_BUFFER_SIZE = 8; // cryptoKeyType + signingKeyType + 4 extra bytes of P521
class IdentityEx
{
public:
@@ -137,7 +138,7 @@ namespace data
mutable i2p::crypto::Verifier * m_Verifier = nullptr;
mutable std::mutex m_VerifierMutex;
size_t m_ExtendedLen;
uint8_t * m_ExtendedBuffer;
uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE];
};
class PrivateKeys // for eepsites
@@ -222,7 +223,7 @@ namespace data
virtual ~RoutingDestination () {};
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const = 0; // encrypt data for
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) const = 0; // encrypt data for
virtual bool IsDestination () const = 0; // for garlic
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
@@ -234,7 +235,7 @@ namespace data
public:
virtual ~LocalDestination() {};
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL) const = 0;
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL) const = 0;
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };

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