Compare commits

..

383 Commits

Author SHA1 Message Date
R4SAS
31936f6025 [make] change daemon sources list, add unix/win32 depending on system
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 23:03:52 +03:00
R4SAS
f3dcc5364f [make] update Unix daemon source name
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 22:57:37 +03:00
R4SAS
fbe2e734c2 [daemon] WIP: rework accessing from webconsole and App
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 22:51:09 +03:00
R4SAS
78193fc8f8 [daemon] WIP: use callbacks to work with daemon
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 19:35:23 +03:00
R4SAS
463d43b0bb [cmake] remove HTTPServer.cpp from daemon sources
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 00:40:50 +03:00
R4SAS
7197fce349 [webconsole] add base templates from current code
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-08 00:37:20 +03:00
R4SAS
5ba387ba2b [cmake] add webconsole library
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-07 22:50:44 +03:00
R4SAS
a843be75f3 start work on webconsole with templates
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-07 22:45:53 +03:00
orignal
47460d86b2 verify signature and send peer test msg 5 2022-06-07 12:55:58 -04:00
orignal
3cd74f0d4f send PeerTest message 2022-06-06 17:28:39 -04:00
R4SAS
690c9f7c6f [FS] add support for windows ProgramData path when running as service
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-06 18:25:22 +03:00
R4SAS
e2718e5a12 [config] change descriptions for deprecated options
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-06 17:44:36 +03:00
orignal
d9fefe757e SSU2/SSU2Session split 2022-06-05 19:33:36 -04:00
orignal
55e4bf6b65 set correct statuc code for peer test 2022-06-05 14:59:33 -04:00
TomasGl
0176e5cf18 Do not show 'Address registration' line if leaseset is encrypted 2022-06-04 19:28:01 +00:00
orignal
4670b12d49 correct buffer size for token request 2022-06-04 08:18:45 -04:00
orignal
321ec8ae4d correct size for Ack block with ranges 2022-06-03 19:16:52 -04:00
orignal
1ccbb8d10b correct offset for nonce in peer test message 2022-06-03 14:02:31 -04:00
orignal
86c0accdce check nonce for peer test msg 5 2022-06-03 13:18:37 -04:00
orignal
38d6c29ce9 correct timestamp size for peer test message 2022-06-03 08:39:54 -04:00
orignal
0cf9478cd4 create SSU2 session for peer test msgs 5-7 2022-06-02 20:12:25 -04:00
orignal
a04abd304a don't send own hash for peer test msg 1 2022-06-02 18:23:51 -04:00
orignal
84aec9fe31 correct msg for first peer test message 2022-06-02 15:40:51 -04:00
orignal
593b9bb6c5 start SSU2 server before peer test 2022-06-02 15:08:38 -04:00
orignal
d3a9cc8fde check if session is established before sending peer test 2022-06-02 15:04:35 -04:00
orignal
87a434c377 start peer test for SSU2 2022-06-01 21:51:02 -04:00
orignal
56022c9442 handle garlic messages from tunnels without pool 2022-05-31 21:43:31 -04:00
orignal
593d6bf466 create initial peer test 2022-05-31 18:31:05 -04:00
R4SAS
29a4366dcf fix mingw build script
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-06-01 00:12:51 +03:00
R4SAS
0a42f414bf [makefile] update support for WSL, remove gcc version detect
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-31 21:59:28 +03:00
R4SAS
9b2ac4349e [cmake] use Threads::Threads (closes #1735)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-31 21:59:28 +03:00
orignal
2d4c7729ad case-insensitive headers 2022-05-29 16:59:15 -04:00
orignal
6ecab66b0e always send Connection: close, strip out Keep-Alive for server HTTP tunnel 2022-05-28 21:54:58 -04:00
orignal
1dded57a1c fix typo in Referer 2022-05-27 13:29:59 -04:00
orignal
1d6104ecf3 addressbook.enabled config param 2022-05-27 13:17:06 -04:00
orignal
14da941ff4 Fixed #1761. Correct section for SSU2 2022-05-25 08:37:36 -04:00
R4SAS
06b87311ea 2.42.1
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-24 15:09:26 +03:00
R4SAS
3b31773117 [deb] remove O3 optimization flag
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-24 15:07:16 +03:00
R4SAS
9c87fe79ea [openssl] suppress deprecation messages
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-24 15:06:01 +03:00
R4SAS
bd00112562 update windows build script
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-24 14:39:11 +03:00
orignal
1c9160c37d correct jump link 2022-05-24 07:09:24 -04:00
orignal
e2ef88229f fixed warning 2022-05-22 12:22:24 -04:00
orignal
fd7b889a0f 2.42.0 2022-05-22 08:26:14 -04:00
R4SAS
a7aa056ec1 [gha] fix typo
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 21:30:14 +03:00
R4SAS
4f74acb2d3 [gha] build docker containers on tags
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 21:26:20 +03:00
R4SAS
22ef1be82b [gha] build docker containers only when pushing to openssl branch
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 21:11:19 +03:00
R4SAS
9ddbf255ba fix const std::map usage
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 21:04:41 +03:00
R4SAS
dfb171d32a [httpproxy] ordered jumps list
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 20:49:26 +03:00
R4SAS
6b4ffcff5a cleanup code (spaces, tabs)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-20 17:44:29 +00:00
R4SAS
d31cd2e5d6 fix incorrect boolean value parsing
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-17 19:02:12 +03:00
R4SAS
396c74e6c6 Revert "Simple refactor of nested if-statements" 2022-05-17 04:55:46 +00:00
R4SAS
609c658a9b [gha] publish releases with latest-release tag
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-15 14:12:26 +03:00
R4SAS
ee6bb40736 remove obsolete msvc define
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-15 11:47:10 +03:00
R4SAS
f8c5ea2b42 [i18n] add french translation
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-15 11:47:10 +03:00
R4SAS
923eb9fdb3 fix udp tunnels reload
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-15 11:47:10 +03:00
orignal
2cd3ebbdb3 copy peer test block 2022-05-14 19:18:58 -04:00
orignal
5e25e30330 check if there is only one unacked packet 2022-05-14 16:36:16 -04:00
orignal
5aa2a8f60f handle peer tests 2022-05-13 20:38:18 -04:00
orbea
0a1e302e8a libi2pd: Fix the build with LibreSSL 3.5.2 2022-05-12 19:11:17 +00:00
orignal
bb705a77cf handle PeerTest message 2022-05-11 17:48:25 -04:00
orignal
cb6155b946 fixed warning 2022-05-11 11:44:27 -04:00
orignal
714d1cc993 close stream if delete requested 2022-05-08 11:49:11 -04:00
orignal
bc8e4494c4 random new profiles cleanup interval 2022-05-07 09:56:58 -04:00
R4SAS
c3a064f980 change int type
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-07 03:40:59 +03:00
R4SAS
eb3feb7dbd [profiles] add daily cleanup
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-07 03:19:32 +03:00
orignal
da3f3ccac9 connect to reachable introducers only 2022-05-06 19:38:48 -04:00
orignal
1a1871e8cd add RouterInfo block before RelayIntro 2022-05-06 15:02:09 -04:00
orignal
c22ab7e1fc use openssl's siphash for 3.0.1 and higher 2022-05-04 18:58:08 -04:00
orignal
436992b069 send and process HolePunch message 2022-05-04 13:58:06 -04:00
orignal
18cb3912e5 fixed imccorect termination 2022-05-02 15:05:44 -04:00
orignal
a818b0ba02 Merge pull request #1748 from voltamperoff/Refactor-I2CP-CreateSessionMessageHandler
Simple refactor of nested if-statements
2022-05-01 17:13:13 -04:00
R4SAS
3716b6f988 move TunnelHopVisitor inside Tunnel class
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-01 23:40:00 +03:00
R4SAS
c9e4e78f41 [webconsole] remove version from title, move tunnel chain print from Tunnel class
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-01 23:25:08 +03:00
R4SAS
9b4e8bf64b [webconsole] do not show registration block when token is not provided
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-01 18:12:43 +03:00
orignal
5aebefe73f connect through introducer 2022-05-01 10:33:25 -04:00
R4SAS
8f2124beab update reseeds
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-30 19:33:30 +03:00
R4SAS
8b8b43df28 [rpm] support rhel 9
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-30 17:54:52 +03:00
R4SAS
c42b991bc9 [rpm] pre-support rhel 9
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-30 17:04:08 +03:00
R4SAS
ec08333bf9 [rpm] fix build on fedora 37
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-30 16:45:53 +03:00
R4SAS
9e5b4e14c9 [rpm] fix build on fedora 37
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-30 16:39:36 +03:00
orignal
1f5ed89a88 set blinded signature type to RedDSA for EdDSA 2022-04-29 12:48:45 -04:00
R4SAS
2304a2bc2e remove android contrib files (moved to android repo)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-29 12:48:40 +03:00
orignal
dc82105226 check status code and verify RelayResponse signature 2022-04-28 20:41:06 -04:00
orignal
5221f3ddc9 one SSU2 session per remote router 2022-04-28 13:11:51 -04:00
orignal
e970deb92b check presense of introducers in SSU2 address 2022-04-28 11:43:33 -04:00
orignal
9db7ec6bb0 create and send RelayRequest 2022-04-27 18:52:44 -04:00
orignal
2e691b6655 check if next manage time is too long 2022-04-26 21:02:39 -04:00
orignal
f22e10537b fixed typo 2022-04-26 20:45:10 -04:00
orignal
6e532c494c create new published SSU2 addresses 2022-04-26 20:30:39 -04:00
orignal
f9ed0d4aa2 fixed crash 2022-04-26 20:01:32 -04:00
orignal
78b1afcc8c publish introducer cap for SSU2 address 2022-04-26 15:20:57 -04:00
orignal
40340cf9c2 handle RelayResponse 2022-04-26 13:59:59 -04:00
orignal
eb6437050f SSU2 introducers 2022-04-25 19:57:46 -04:00
orignal
45ebfe378b correct Ack range 2022-04-23 11:11:49 -04:00
R4SAS
1326597226 use ipv6 preference only when netinet headers not used (entware with musl workaround)'
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-23 13:50:34 +03:00
orignal
751da92c13 send relay response 2022-04-22 20:34:19 -04:00
orignal
e10ca637da handle RelayIntro 2022-04-22 15:03:49 -04:00
orignal
c5d9d71a8a create relay tag and relay request block 2022-04-21 15:47:36 -04:00
orignal
3e0f5d231d send queue after batch of packets 2022-04-18 15:47:35 -04:00
orignal
6990f177ba window size 2022-04-18 13:14:09 -04:00
orignal
98e713166b show port for non-published SSU addresses 2022-04-18 12:27:57 -04:00
orignal
4c91ae0085 check if end of list 2022-04-16 17:01:06 -04:00
orignal
43f74d4d5a resend packet with new packet number 2022-04-16 15:42:11 -04:00
orignal
8c3e716c3f ranges in ack block 2022-04-15 16:26:44 -04:00
orignal
05946125b5 handle single packet 2022-04-13 12:33:59 -04:00
orignal
1e2a0a4549 handle incoming packets in batch 2022-04-12 11:42:51 -04:00
R4SAS
f9f5084dd7 typo
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-11 11:26:10 +03:00
R4SAS
b7e7c6db7b UDP Client: ignore incomming traffic and error when stopping (prevent socket restarting)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-10 23:10:41 +03:00
orignal
f9d67b28ec handle fragmented SessionConfirmed 2022-04-09 19:56:57 -04:00
orignal
46b77cc280 increase RouterInfo buffer size 2022-04-09 14:40:38 -04:00
R4SAS
2f10decf56 daemon: make possible to set datadir before init
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-09 19:57:32 +03:00
orignal
678a1ae0fb send fragmented messages 2022-04-09 11:42:34 -04:00
orignal
51cbffd097 don't lookup session for every sinle packet 2022-04-07 10:57:57 -04:00
orignal
207b13dcab send correct acnt if gaps 2022-04-05 18:23:52 -04:00
orignal
3052dbd1e8 single receive thread for both ipv4 and ipv6 2022-04-05 16:27:52 -04:00
orignal
5891b1ceb2 separate receive thread 2022-04-05 16:14:13 -04:00
orignal
07e14ddda8 check if SSU2 enabled 2022-04-04 20:37:29 -04:00
orignal
db5e90787c update I2NP header after all fragments received 2022-04-04 13:25:08 -04:00
orignal
67e501f5c7 correct nonce for SessionCorfirmed part 2 2022-04-04 11:52:14 -04:00
orignal
2160001167 correct non for token request and retry encryption 2022-04-04 09:58:17 -04:00
orignal
f5f4150d17 fixed typo 2022-04-03 13:43:33 -04:00
R4SAS
887f292612 update install target to use correct share directory, skip dh_auto_install in debian
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-04-02 23:16:39 +03:00
orignal
f5f282af97 cost for published SSU2 address 2022-04-02 14:32:26 -04:00
orignal
82f9585b7a handle fragments 2022-04-02 13:05:11 -04:00
orignal
eb561bb0c2 handle Ack ranges 2022-04-01 15:09:35 -04:00
orignal
81207999eb check token in SessionRequest 2022-03-31 21:07:51 -04:00
orignal
2fef595b83 resend packets 2022-03-31 15:35:55 -04:00
orignal
2024e790ca send I2NP messages 2022-03-30 18:04:12 -04:00
orignal
f9925c7374 hanlde Ack block 2022-03-30 15:03:45 -04:00
orignal
dd774b8dfd store out of sequence packet numbers 2022-03-30 12:31:24 -04:00
orignal
064b8042a5 ssu2.published and update SSU2 ipv4 2022-03-29 14:56:57 -04:00
orignal
7923ed9567 publish SSU2 address 2022-03-29 13:56:56 -04:00
orignal
30b83414ef find SSU2 address by address type 2022-03-28 18:03:22 -04:00
orignal
990906c57f insert garlic tag in destination's thread 2022-03-28 12:15:40 -04:00
orignal
4c323a666a show SSU2 transports in web console 2022-03-27 19:29:50 -04:00
orignal
a3f165d374 handle and send termination 2022-03-27 16:39:58 -04:00
Volt Amperoff
4977f9e6b4 If-statements are simplified. Checks are rearranged for faster errors detection without unnecessary actions. 2022-03-27 18:05:37 +03:00
orignal
7d5f51e357 don't send instant Ack for out-of-sequence message 2022-03-27 09:26:45 -04:00
orignal
371a339b18 encrypt Data header 2022-03-27 07:47:25 -04:00
orignal
7e7aee27b6 handle I2NP message block 2022-03-26 21:59:21 -04:00
orignal
53148fe58f send Ack packet 2022-03-26 16:35:07 -04:00
orignal
56b6de6962 correct header decryption for Data message 2022-03-25 17:57:59 -04:00
orignal
44735681af KDF and process Data message 2022-03-25 15:34:43 -04:00
orignal
ee1c4f4fdc internal numeric id for families 2022-03-24 15:50:20 -04:00
orignal
fb6ecdde1e handle TokenRequest 2022-03-23 21:48:41 -04:00
orignal
861166d8a9 send TokenRequest message: 2022-03-23 19:13:44 -04:00
R4SAS
70dca81c40 dropped MESHNET build option
Dropping MESHNET build option due to lack of usage. That change won't
affect on usage with currently supported Yggdrasil network.

Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-24 01:36:12 +03:00
R4SAS
2774d72888 [makefile] add install target for linux
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-24 01:36:12 +03:00
orignal
2440ffbfc9 handle SSU2 SessionConfirmed 2022-03-23 14:06:55 -04:00
orignal
77c5dde320 send SessionConfirmed 2022-03-21 21:06:14 -04:00
orignal
aa49cad279 correct encrypted payload size for MixHash 2022-03-21 13:21:08 -04:00
orignal
f56ae240ab don't delete peding endpoint if Retry received 2022-03-21 12:56:02 -04:00
orignal
e871a30a78 initialize connid in constructor 2022-03-20 16:53:32 -04:00
orignal
30e6984889 handle Retry message 2022-03-20 15:10:18 -04:00
orignal
324932c758 separate i and key fields for shared SSU address 2022-03-20 10:28:08 -04:00
orignal
421800bc8f recognize SSU address supporting SSU2 2022-03-19 17:34:07 -04:00
orignal
86fb47b2b4 Merge pull request #1744 from WaxySteelWorm/openssl
Added StormyCloud Inc family cert
2022-03-19 12:34:24 -04:00
WaxySteelWorm
715f83bf84 Create stormycloud.crt 2022-03-19 10:59:54 -05:00
orignal
87bf5c2418 cleanup pending sessions 2022-03-18 20:21:31 -04:00
orignal
5c9af1c613 MixHash with encrypted payload after decryption 2022-03-18 15:32:32 -04:00
orignal
765e0e5c6b correct 'i' size for SSU2 2022-03-18 13:33:33 -04:00
orignal
cc296e16dc don't make SSU2 address published is 'i' is presented 2022-03-18 13:02:59 -04:00
orignal
ab9901525b separated sockets for ipv4 and ipv6 2022-03-17 18:45:14 -04:00
orignal
3643a46a0c don't update SSU2 port 2022-03-17 14:47:00 -04:00
orignal
d467e6869d don't update address for SSU2 2022-03-17 13:21:51 -04:00
Dimitris Apostolou
db36018849 Fix typo 2022-03-17 10:41:39 +00:00
orignal
3c5c375f71 connect to SSU2 address 2022-03-16 21:11:48 -04:00
orignal
7473d8c9aa create and handle Address block 2022-03-16 13:13:31 -04:00
R4SAS
33645d7f09 [gha] XP: use make option for XP
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 04:29:02 +03:00
R4SAS
9f1106b14a [gha] XP: noconfirm for pacman
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 04:09:23 +03:00
R4SAS
3dd952b49b [gha] XP: noconfirm for pacman
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 04:03:26 +03:00
R4SAS
6b85bd2cb8 [gha] XP: fix MinGW repo url
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 03:54:32 +03:00
orignal
60b164c853 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2022-03-15 20:50:24 -04:00
orignal
40c8a1bc1d handle payload blocks 2022-03-15 20:49:41 -04:00
R4SAS
22de695f12 [gha] install git to XP builder
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 03:45:55 +03:00
R4SAS
e91f588cd7 [gha] build for winxp
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-16 03:42:10 +03:00
orignal
7b72d91549 receive incoming SSU2 packets 2022-03-14 19:25:59 -04:00
orignal
b3c2e86436 skip unknown address 2022-03-14 15:54:55 -04:00
orignal
908bdc7624 always publish intro key for SSU2 address 2022-03-13 21:55:03 -04:00
orignal
21c1ec9c8c enable SSU2 server 2022-03-13 21:34:11 -04:00
orignal
6d7d71bb16 don't show address:port for non-published addresses 2022-03-13 11:58:19 -04:00
orignal
6eba061c2a show local SSU2 address 2022-03-13 11:04:37 -04:00
orignal
f184f550b9 SSU2 address in config and RouterInfo 2022-03-12 21:51:17 -05:00
orignal
bb7c0fef20 SSU2 address in config and RouterInfo 2022-03-12 21:40:12 -05:00
orignal
5c15a12116 don't allocate buffer from netdb for LocalRouterInfo 2022-03-11 19:03:00 -05:00
orignal
68d015763e recognize SSU2 addresses 2022-03-11 16:17:44 -05:00
orignal
7faa732f38 send SessionCreated 2022-03-08 21:33:21 -05:00
orignal
11f9eeabf1 inbound.lengthVariance and outbound.lengthVariance 2022-03-07 22:20:11 -05:00
orignal
a152f36894 MixHash for SSU2 long header 2022-03-07 18:20:06 -05:00
orignal
d4ede6ff01 process SessionRequest 2022-03-05 18:39:27 -05:00
orignal
35542d803c KDF for session request 2022-03-04 21:51:40 -05:00
orignal
f6ba776c12 SSU2 keys 2022-03-01 21:23:08 -05:00
orignal
1511dcb309 store endpoint and send packet 2022-02-28 21:46:00 -05:00
R4SAS
35afa98112 [reseed] add new reseed
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-03-01 00:23:52 +03:00
R4SAS
df62b40ca7 [win32] return back service control code (#1733)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-02-28 23:02:19 +03:00
orignal
9f1a125ed9 decrypt connID for incoming packet 2022-02-27 20:15:14 -05:00
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
acetone
d599502b1a 1000Gb+ display 2021-06-07 23:49:56 -04:00
acetone
48d9a03aa8 tbytes in WinApp 2021-06-07 12:58:57 -04:00
225 changed files with 34550 additions and 4432 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.4
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,11 +26,50 @@ 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
build-xp:
name: Building for Windows XP
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MINGW32
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc
update: true
- name: Build WinXP-capable CRT packages
run: |
git clone https://github.com/msys2/MINGW-packages
pushd MINGW-packages
pushd mingw-w64-headers-git
sed -i 's/0x601/0x501/' PKGBUILD
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-headers-git-*-any.pkg.tar.zst
popd
pushd mingw-w64-crt-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-crt-git-*-any.pkg.tar.zst
popd
pushd mingw-w64-winpthreads-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst
popd
popd
- name: Build application
run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: i2pd-xp.exe
path: i2pd.exe

View File

@@ -49,7 +49,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-stretch" -M --distribution stretch "trunk build"
debchange -v "`git describe --tags`-stretch" -b -M --distribution stretch "trunk build"
- uses: singingwolfboy/build-dpkg-stretch@v1
id: build
with:
@@ -73,7 +73,7 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-buster" -M --distribution buster "trunk build"
debchange -v "`git describe --tags`-buster" -b -M --distribution buster "trunk build"
- uses: singingwolfboy/build-dpkg-buster@v1
id: build
with:

View File

@@ -1,6 +1,11 @@
name: Build containers
on: [push]
on:
push:
branches:
- openssl
tags:
- '*'
jobs:
docker:
@@ -58,6 +63,8 @@ jobs:
push: true
tags: |
purplei2p/i2pd:latest
purplei2p/i2pd:latest-release
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
ghcr.io/purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:latest-release
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}

4
.gitignore vendored
View File

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

121
ChangeLog
View File

@@ -1,6 +1,95 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.42.1] - 2022-05-24
### Fixed
- Incorrect jump link in HTTP Proxy
## [2.42.0] - 2022-05-22
### Added
- Preliminary SSU2 implementation
- Tunnel length variance
- Localization to French
- Daily cleanup of obsolete peer profiles
- Ordered jump services list in HTTP proxy
- Win32 service
- Show port for local non-published SSU addresses in web console
### Changed
- Maximum RouterInfo length increased to 3K
- Skip unknown addresses in RouterInfo
- Don't pick own router for peer test
- Reseeds list
- Internal numeric id for families
- Use ipv6 preference only when netinet headers not used
- Close stream if delete requested
- Remove version from title in web console
- Drop MESHNET build option
- Set data path before initialization
- Don't show registration block in web console if token is not provided
### Fixed
- Encrypted LeaseSet for EdDSA signature
- Clients tunnels are not built if clock is not synced on start
- Incorrect processing of i2cp.dontPublishLeaseSet param
- UDP tunnels reload
- Build for LibreSSL 3.5.2
- Race condition in short tunnel build message
- Race condition in local RouterInfo buffer allocation
## [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
@@ -18,11 +107,11 @@
- 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
- 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
- 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
@@ -46,7 +135,7 @@
## [2.38.0] - 2021-05-17
### Added
- Publish ipv6 introducers
- Bind ipv6 or yggdrasil NTCP2 acceptor to specified address
- 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
@@ -82,12 +171,12 @@
- 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
- 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
- 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
@@ -109,22 +198,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
@@ -157,7 +246,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
@@ -168,7 +257,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
@@ -185,7 +274,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
@@ -196,11 +285,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
@@ -208,11 +297,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,8 +1,10 @@
.DEFAULT_GOAL := all
SYS := $(shell $(CXX) -dumpmachine)
ifneq (, $(findstring darwin, $(SYS)))
SHARED_SUFFIX = dylib
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
SHARED_SUFFIX = dll
else
SHARED_SUFFIX = so
@@ -10,28 +12,36 @@ endif
SHLIB := libi2pd.$(SHARED_SUFFIX)
ARLIB := libi2pd.a
SHLIB_LANG := libi2pdlang.$(SHARED_SUFFIX)
ARLIB_LANG := libi2pdlang.a
SHLIB_CLIENT := libi2pdclient.$(SHARED_SUFFIX)
ARLIB_CLIENT := libi2pdclient.a
SHLIB_LANG := libi2pdlang.$(SHARED_SUFFIX)
ARLIB_LANG := libi2pdlang.a
SHLIB_WEBCONSOLE := libi2pdwebconsole.$(SHARED_SUFFIX)
ARLIB_WEBCONSOLE := libi2pdwebconsole.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
WEBCONSOLE_SRC_DIR := libi2pd_webconsole
LANG_SRC_DIR := i18n
DAEMON_SRC_DIR := daemon
WRAP_SRC_DIR := libi2pd_wrapper
# import source files lists
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)
DEBUG := $(or $(DEBUG),yes)
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),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
@@ -41,54 +51,58 @@ else
endif
ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
ifeq ($(HOMEBREW),1)
include Makefile.homebrew
else
include Makefile.osx
endif
else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
include Makefile.linux
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonUnix.cpp
include Makefile.bsd
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
include Makefile.mingw
else # not supported
$(error Not supported platform)
endif
ifeq ($(USE_MESHNET),yes)
NEEDED_CXXFLAGS += -DMESHNET
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)
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -I$(WEBCONSOLE_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC))
WEBCONSOLE_OBJS += $(patsubst %.cpp,obj/%.o,$(WEBCONSOLE_SRC))
DAEMON_OBJS += $(patsubst %.cpp,obj/%.o,$(DAEMON_SRC))
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)
DEPS += $(LIB_OBJS:.o=.d) $(LIB_CLIENT_OBJS:.o=.d) $(LANG_OBJS:.o=.d) $(WEBCONSOLE_OBJS:.o=.d) $(DAEMON_OBJS:.o=.d) $(WRAP_LIB_OBJS:.o=.d)
## Build all code (libi2pd, libi2pdclient, libi2pdlang), link it to .a and build binary
all: $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(I2PD)
all: $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(ARLIB_WEBCONSOLE) $(I2PD)
mk_obj_dir:
@mkdir -p obj/$(LIB_SRC_DIR)
@mkdir -p obj/$(LIB_CLIENT_SRC_DIR)
@mkdir -p obj/$(LANG_SRC_DIR)
@mkdir -p obj/$(WEBCONSOLE_SRC_DIR)
@mkdir -p obj/$(DAEMON_SRC_DIR)
@mkdir -p obj/$(WRAP_SRC_DIR)
@mkdir -p obj/Win32
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)
api: $(SHLIB) $(ARLIB)
client: $(SHLIB_CLIENT) $(ARLIB_CLIENT)
lang: $(SHLIB_LANG) $(ARLIB_LANG)
webconsole: $(SHLIB_WEBCONSOLE) $(ARLIB_WEBCONSOLE)
api_client: api client lang webconsole
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.
@@ -103,7 +117,7 @@ obj/%.o: %.cpp | mk_obj_dir
# '-' is 'ignore if missing' on first run
-include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(I2PD): $(DAEMON_OBJS) $(ARLIB_WEBCONSOLE) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS) $(SHLIB_LANG)
@@ -116,12 +130,17 @@ ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) $(SHLIB_LANG)
endif
$(SHLIB_WRAP): $(WRAP_LIB_OBJS)
$(SHLIB_LANG): $(LANG_OBJS)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
endif
$(SHLIB_LANG): $(LANG_OBJS)
$(SHLIB_WEBCONSOLE): $(WEBCONSOLE_OBJS) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
endif
$(SHLIB_WRAP): $(WRAP_LIB_OBJS)
ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS)
endif
@@ -132,18 +151,21 @@ $(ARLIB): $(LIB_OBJS)
$(ARLIB_CLIENT): $(LIB_CLIENT_OBJS)
$(AR) -r $@ $^
$(ARLIB_WRAP): $(WRAP_LIB_OBJS)
$(ARLIB_LANG): $(LANG_OBJS)
$(AR) -r $@ $^
$(ARLIB_LANG): $(LANG_OBJS)
$(ARLIB_WEBCONSOLE): $(WEBCONSOLE_OBJS)
$(AR) -r $@ $^
$(ARLIB_WRAP): $(WRAP_LIB_OBJS)
$(AR) -r $@ $^
clean:
$(RM) -r obj
$(RM) -r docs/generated
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) $(SHLIB_WRAP) $(ARLIB_WRAP)
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT) $(SHLIB_LANG) $(ARLIB_LANG) $(SHLIB_WEBCONSOLE) $(ARLIB_WEBCONSOLE) $(SHLIB_WRAP) $(ARLIB_WRAP)
strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG)
strip: $(I2PD) $(SHLIB) $(SHLIB_CLIENT) $(SHLIB_LANG) $(SHLIB_WEBCONSOLE)
strip $^
LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl)

View File

@@ -39,13 +39,14 @@ ifeq ($(USE_AESNI),yes)
endif
install: all
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
install -m 755 ${I2PD} ${PREFIX}/bin/
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/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
@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
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf

View File

@@ -62,3 +62,16 @@ ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64
NEEDED_CXXFLAGS += -D__AES__ -maes
endif
endif
install: all
install -d ${PREFIX}/bin ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/usr ${PREFIX}/usr/share ${PREFIX}/usr/share/doc/i2pd ${PREFIX}/usr/share/i2pd ${PREFIX}/usr/share/man ${PREFIX}/usr/share/man/man1 ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
install -m 755 ${I2PD} ${PREFIX}/bin/
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
@cp -R contrib/certificates ${PREFIX}/usr/share/i2pd/
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/usr/share/doc/i2pd
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/usr/share/man/man1
@ln -sf ${PREFIX}/usr/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
@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
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf

View File

@@ -3,19 +3,11 @@ USE_WIN32_APP := yes
WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -DWIN32_LEAN_AND_MEAN -fPIC -msse
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
INCFLAGS = -IWin32
LDFLAGS := ${LD_DEBUG} -static
# detect proper flag for c++11 support by compilers
CXXVER := $(shell $(CXX) -dumpversion)
ifeq ($(shell expr match ${CXXVER} "[4]\.[7-9]\|4\.1[0-9]\|[5-6]"),4) # gcc 4.7 - 6
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
NEEDED_CXXFLAGS += -std=c++17
else # not supported
$(error Compiler too old)
endif
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
# Boost libraries suffix
BOOST_SUFFIX = -mt

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

@@ -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
*
@@ -18,7 +18,7 @@
#include "Tunnel.h"
#include "version.h"
#include "resource.h"
#include "Daemon.h"
#include "Win32App.h"
#include "Win32NetState.h"
@@ -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,17 +50,20 @@ 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())
InsertMenu (hPopup, -1,
i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING,
ID_ACCEPT_TRANSIT, "Accept &transit");
if(m_getIsGraceful)
if(m_getIsGraceful())
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING | MF_GRAYED, ID_ACCEPT_TRANSIT, "Accept &transit");
else
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ACCEPT_TRANSIT, "Accept &transit");
else
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config");
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
if (!m_getIsGraceful)
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
else
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown");
@@ -268,7 +272,7 @@ namespace win32
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second
g_GracefulShutdownEndtime = GetTickCount() + 10*60*1000;
i2p::util::DaemonWin32::Instance ().isGraceful = true;
if (m_setIsGraceful) m_setIsGraceful(true);
return 0;
}
case ID_STOP_GRACEFUL_SHUTDOWN:
@@ -277,7 +281,7 @@ namespace win32
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
g_GracefulShutdownEndtime = 0;
i2p::util::DaemonWin32::Instance ().isGraceful = false;
if (m_setIsGraceful) m_setIsGraceful(false);
return 0;
}
case ID_RELOAD:
@@ -303,6 +307,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

@@ -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
*
@@ -22,6 +22,15 @@ namespace win32
int RunWin32App ();
bool GracefulShutdown ();
bool StopGracefulShutdown ();
inline typedef std::function<void (bool)> DaemonSetIsGraceful;
inline DaemonSetIsGraceful m_setIsGraceful;
inline void SetIsGraceful (const DaemonSetIsGraceful& f) { m_setIsGraceful = f; };
inline typedef std::function<bool ()> DaemonGetIsGraceful;
inline DaemonGetIsGraceful m_getIsGraceful;
inline void GetIsGraceful (const DaemonGetIsGraceful& f) { m_getIsGraceful = f; };
}
}
#endif // WIN32APP_H__

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

292
Win32/Win32Service.cpp Normal file
View File

@@ -0,0 +1,292 @@
/*
* 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 "Win32Service.h"
#include <assert.h>
#include <windows.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 error: ", 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, ")");
if(m_daemonStart)
m_daemonStart();
else
{
LogPrint(eLogError, "Win32Service: failed to start: Unable to call callback");
SetServiceStatus(SERVICE_STOPPED);
}
_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 error: ", 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, ")");
if(m_daemonStop)
m_daemonStop();
else
LogPrint(eLogError, "Win32Service: failed to stop: Unable to call callback");
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 error: ", 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 error: ", 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 error: ", 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;
}
}

76
Win32/Win32Service.h Normal file
View File

@@ -0,0 +1,76 @@
/*
* 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 WIN32SERVICE_H__
#define WIN32SERVICE_H__
#include <functional>
#include <thread>
#include <windows.h>
#define SERVICE_NAME "i2pdService"
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();
typedef std::function<bool ()> DaemonStart;
void SetDaemonStart (const DaemonStart& f) { m_daemonStart = f; };
typedef std::function<bool ()> DaemonStop;
void SetDaemonStop (const DaemonStop& f) { m_daemonStop = f; };
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;
private:
DaemonStart m_daemonStart;
DaemonStop m_daemonStop;
};
#endif // WIN32SERVICE_H__

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,8 +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)
@@ -36,11 +33,13 @@ target_architecture(ARCHITECTURE)
set(LIBI2PD_SRC_DIR ../libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
set(WEBCONSOLE_SRC_DIR ../libi2pd_webconsole)
set(LANG_SRC_DIR ../i18n)
set(DAEMON_SRC_DIR ../daemon)
include_directories(${LIBI2PD_SRC_DIR})
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
include_directories(${WEBCONSOLE_SRC_DIR})
include_directories(${LANG_SRC_DIR})
include_directories(${DAEMON_SRC_DIR})
@@ -71,6 +70,18 @@ if(WITH_LIBRARY)
COMPONENT Libraries)
endif()
FILE(GLOB WEBCONSOLE_SRC ${WEBCONSOLE_SRC_DIR}/*.cpp)
add_library(libi2pdwebconsole ${WEBCONSOLE_SRC})
set_target_properties(libi2pdwebconsole PROPERTIES PREFIX "")
if(WITH_LIBRARY)
install(TARGETS libi2pdwebconsole
EXPORT libi2pdwebconsole
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 "")
@@ -85,20 +96,19 @@ endif()
set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
"${DAEMON_SRC_DIR}/I2PControl.cpp"
"${DAEMON_SRC_DIR}/i2pd.cpp"
"${DAEMON_SRC_DIR}/UPnP.cpp"
)
if(WITH_MESHNET)
add_definitions(-DMESHNET)
endif()
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.
@@ -138,7 +148,7 @@ endif()
# compiler flags customization(by system)
if(UNIX)
list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp")
list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/DaemonUnix.cpp")
if(NOT(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE))
# "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8
add_definitions("-D_GLIBCXX_USE_NANOSLEEP=1")
@@ -168,20 +178,8 @@ endif()
# libraries
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
# use imported Threads::Threads instead
set(THREADS_PREFER_PTHREAD_FLAG ON)
if(IOS)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
else()
find_package(Threads REQUIRED)
endif()
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
find_package(Threads REQUIRED)
if(WITH_STATIC)
set(Boost_USE_STATIC_LIBS ON)
@@ -200,22 +198,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_compile_options(libi2pdlang PRIVATE -include libi2pd/stdafx.h)
target_link_libraries(libi2pd stdafx)
endif()
target_link_libraries(libi2pdclient libi2pd libi2pdlang)
target_link_libraries(libi2pdwebconsole libi2pdclient libi2pd libi2pdlang)
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_INCLUDE_DIRS)
@@ -227,6 +210,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")
add_definitions(-DOPENSSL_SUPPRESS_DEPRECATED)
endif()
if(WITH_UPNP)
find_package(MiniUPnPc REQUIRED)
if(NOT MINIUPNPC_FOUND)
@@ -244,15 +231,7 @@ endif()
# load includes
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
# warn if for meshnet
if(WITH_MESHNET)
message(STATUS "Building for testnet")
message(WARNING "This build will NOT work on mainline i2p")
endif()
if(NOT MSYS)
include(CheckAtomic)
endif()
include(CheckAtomic)
# show summary
message(STATUS "---------------------------------------")
@@ -269,8 +248,6 @@ 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 "---------------------------------------")
@@ -282,10 +259,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()
@@ -306,7 +279,7 @@ if(WITH_BINARY)
endif()
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${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}" libi2pdwebconsole libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} Threads::Threads ${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,73 @@ 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 SIGN (
echo Signing enabled
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%"
)
)
if defined SIGNKEY (
set "xSIGNKEYOPTS=/f ^"%SIGNKEY%^""
)
if defined SIGNPASS (
set "xSIGNPASSOPTS=/p ^"%SIGNPASS%^""
)
set "xSIGNOPTS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 %xSIGNKEYOPTS% %xSIGNPASSOPTS%"
)
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 +108,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,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

@@ -1,18 +0,0 @@
gen
tests
bin
libs
log*
obj
.gradle
.idea
.externalNativeBuild
ant.properties
local.properties
build.sh
android.iml
build
gradle
gradlew
gradlew.bat

View File

@@ -1,74 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := i2pd
LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(DAEMON_SRC_PATH)
LOCAL_STATIC_LIBRARIES := \
boost_system \
boost_date_time \
boost_filesystem \
boost_program_options \
crypto ssl \
miniupnpc
LOCAL_LDLIBS := -lz
LOCAL_SRC_FILES := $(IFADDRS_PATH)/ifaddrs.c \
$(wildcard $(LIB_SRC_PATH)/*.cpp)\
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
$(DAEMON_SRC_PATH)/UnixDaemon.cpp \
$(DAEMON_SRC_PATH)/Daemon.cpp \
$(DAEMON_SRC_PATH)/UPnP.cpp \
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
$(DAEMON_SRC_PATH)/I2PControl.cpp \
$(DAEMON_SRC_PATH)/i2pd.cpp
include $(BUILD_EXECUTABLE)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_system
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_date_time
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_filesystem
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := boost_program_options
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
LOCAL_STATIC_LIBRARIES := crypto
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := miniupnpc
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
include $(PREBUILT_STATIC_LIBRARY)

View File

@@ -1,40 +0,0 @@
APP_ABI := all
#APP_ABI += x86
#APP_ABI += x86_64
#APP_ABI += armeabi-v7a
#APP_ABI += arm64-v8a
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
APP_PLATFORM := android-14
NDK_TOOLCHAIN_VERSION := clang
APP_STL := c++_static
# Enable c++17 extensions in source code
APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE
APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP
APP_LDFLAGS += -rdynamic -fPIE -pie
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
APP_CPPFLAGS += -DANDROID_ARM7A
endif
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
#APP_OPTIM := debug
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
# change to your own
I2PD_LIBS_PATH = /path/to/libraries
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
# don't change me
I2PD_SRC_PATH = $(PWD)/../..
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon

View File

@@ -1,2 +0,0 @@
archive
i2pd_*_android_binary.zip

View File

@@ -1,48 +0,0 @@
#!/bin/bash
# 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
GITDESC=$(git describe --tags)
declare -A ABILIST=(
["armeabi-v7a"]="armv7l"
["arm64-v8a"]="aarch64"
["x86"]="x86"
["x86_64"]="x86_64"
)
# Remove old files and archives
if [ -d archive ]; then
rm -r archive
fi
if [ -f ../i2pd_*_android_binary.zip ]; then
rm i2pd_*_android_binary.zip
fi
# Prepare files for package
mkdir archive
for ABI in "${!ABILIST[@]}"; do
if [ -f ../android_binary_only/libs/${ABI}/i2pd ]; then
cp ../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
fi
done
cp i2pd archive/i2pd
cp -rH ../android/assets/certificates archive/
cp -rH ../android/assets/tunnels.conf.d archive/
cp -H ../android/assets/i2pd.conf archive/
cp -H ../android/assets/tunnels.conf archive/
# Compress files
cd archive
zip -r6 ../i2pd_${GITDESC}_android_binary.zip .
# Remove temporary folder
cd ..
rm -r archive

View File

@@ -1,33 +0,0 @@
#!/bin/sh
# 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
#
# That script written for use with Termux.
# https://stackoverflow.com/a/246128
SOURCE="${0}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
arch=$(uname -m)
screenfind=$(which screen)
if [ -z $screenfind ]; then
echo "Can't find 'screen' installed. That script needs it!";
exit 1;
fi
if [ -z i2pd-$arch ]; then
echo "Can't find i2pd binary for your archtecture.";
exit 1;
fi
screen -AmdS i2pd ./i2pd-$arch --datadir=$DIR

View File

@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICKDCCAc6gAwIBAgIUcPHZXtYSqGNRCD6z8gp79WUFtI0wCgYIKoZIzj0EAwIw
gZMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGlu
MRgwFgYDVQQKDA9TdG9ybXlDbG91ZCBJbmMxIzAhBgNVBAMMGnN0b3JteWNsb3Vk
LmZhbWlseS5pMnAubmV0MSQwIgYJKoZIhvcNAQkBFhVhZG1pbkBzdG9ybXljbG91
ZC5vcmcwHhcNMjIwMzE5MTU1MjU2WhcNMzIwMzE2MTU1MjU2WjCBkzELMAkGA1UE
BhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xGDAWBgNVBAoM
D1N0b3JteUNsb3VkIEluYzEjMCEGA1UEAwwac3Rvcm15Y2xvdWQuZmFtaWx5Lmky
cC5uZXQxJDAiBgkqhkiG9w0BCQEWFWFkbWluQHN0b3JteWNsb3VkLm9yZzBZMBMG
ByqGSM49AgEGCCqGSM49AwEHA0IABFUli0hvJEmowNjJVjbKEIWBJhqe973S4VdL
cJuA5yY3dC4Y998abWEox7/Y1BhnBbpJuiodA341bXKkLMXQy/kwCgYIKoZIzj0E
AwIDSAAwRQIgD12F/TfY3iV1/WDF7BSKgbD5g2MfELUIy1dtUlJQuJUCIQD69mZw
V1Z9j2x0ZsuirS3i6AMfVyTDj0RFS3U1jeHzIQ==
-----END CERTIFICATE-----

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,34 @@
-----BEGIN CERTIFICATE-----
MIIFzTCCA7WgAwIBAgIQeUqFi0fHNQopg6BZlBLhVzANBgkqhkiG9w0BAQsFADBy
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEbMBkGA1UEAwwS
aTJwLXJlc2VlZEBtazE2LmRlMB4XDTIyMDIwNTE3MzkzM1oXDTMyMDIwNTE3Mzkz
M1owcjELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwG
A1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGzAZBgNV
BAMMEmkycC1yZXNlZWRAbWsxNi5kZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
AgoCggIBAMYxs2D2xpN/8blGawvAlU9DemHIxApOEwaLNfh8aAvqEdB41NTqcx4U
H8VchSormCfkCvezuMHO+K2HX7ihEZ1v6tbr6aX6hY9UZUyDDYsKmJoB1oKEhddv
5UYfcWPE2eSykdFsWgTQD6Z+cRQWHEoCzb7qc+Jrw6KcnHMD0VrmBrEQPzTBxMHW
4HC97PVkSLJTDArnS6ZiX4IbWRPw/mbpJT6EoVZo8J/it0pdn/X4KodEXDcnEMSe
VRulfZH/nSmOOvKhoHPckmgz/u66BlnuSYXEIB0KfDIcAlSYiPDxGnAemTozJYXA
UVMeFMs+YE5wiPgzzu+vpC31xtZLq0gyaCfgEi1P9j2ES/8pH3Gw6W2OH4kBx+jO
TBsfI+ph6qFZ3WWT23MRVyl3ATuI/GHdczTxD9JaOn74lLI+Hnu8wXnyztVWkTMB
4sAnzjdeHkvNDyQ10vSaN0HnGfg6zuAuUSqFQujFF8Vg8ZCcsh8GouWfzYDvi9mj
9pfxx8v6UCC719I4J9CgFjWnn2Hqez3fO8fFulY61VPyCCZp4gKWbI2SIQP/n5gz
ecYJRrJoem+rYfEQ/fwxROsvm3fCO4D6dt7ILRuX286GDIw2qSvP1zZVAioMwSj3
9CAjKLwD/BhTRiMOlpaVv6IWqjtevbiaIKvbHTnoxvkGsDqe3gJhAgMBAAGjXzBd
MA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
DwYDVR0TAQH/BAUwAwEB/zAbBgNVHQ4EFAQSaTJwLXJlc2VlZEBtazE2LmRlMA0G
CSqGSIb3DQEBCwUAA4ICAQAb+x6XpJdjpVYw2bvWIUbatQJwq0YaEW5W61xGLgIG
a37oll3YZbSY9Vk+N1cE0f61L3ya4Ioz6zlH/MO2zUG/dEk8vqdgIPUYJvyF7wwF
w3/G4VMaDKOJx4bAZNmaiRFGYNhCOhCnZx6uZGrLNIJ2Dc+mflrGmGwYphtXVV3e
Iv+ki3gSRgfXuMfKi4B5bLPnz7XDe4TSmwZZSRac4ly4KqmZUyntqbilRxaGTej3
VYJ1tac8yppyk5N3VopMQNmBarNZG16wSOTD7CtKgn382jgRW8cR7BMeqhORivp0
ZnPJFhzh4uthdlPdXXo6lxfvZjfiwlDPytvEu2QBz3urTgopGqRLcTBnLucWg9li
OSy9z7hNEnIN3iIJJAwI1wBdDa7K0h3PFBbIUa7X2ybn81VeNSfO25Lo8YTZEKsc
wcThJrNV6qOQv8rM/7aXugi6+VzPlCR+18iKRbebCnlqGR2dT1zFtj3negtOkrjo
LH4H6VUr3q2Ie56IubS2hUKiUkDm0ckP3Vum35GGntyEAzl6uyog0hJFOJb3aq30
YQLzyVEOz8NnA+32oMRzJJdDxQ7pqG5fgq7EF4d++YSgEfdVXxvfgXQ6m3jAyC7Z
p/gX4rlxNsjeGU3Ds51wkmhH4IB1aSQr52PE6RaBhhh3SmADEv6S/3eGvE4F4MN5
2Q==
-----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

@@ -81,7 +81,9 @@ ipv6 = false
## 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
@@ -108,7 +110,8 @@ port = 7070
# user = i2pd
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, russian, turkmen, ukrainian and uzbek languages
## Currently supported english (default), afrikaans, armenian, french, german,
## russian, turkmen, ukrainian and uzbek languages
# lang = english
[httpproxy]

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.39.0
Version: 2.42.1
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
@@ -57,8 +57,14 @@ cd build
%endif
%if 0%{?fedora} >= 36
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -71,10 +77,16 @@ pushd build
make %{?_smp_mflags}
%if 0%{?fedora} >= 33
%if 0%{?rhel} == 9
popd
%endif
%if 0%{?fedora} >= 33
%if 0%{?fedora} < 37
popd
%endif
%endif
%if 0%{?mageia} > 7
popd
%endif
@@ -82,8 +94,14 @@ popd
%install
pushd build
%if 0%{?fedora} >= 36
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -99,14 +117,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
@@ -146,6 +164,22 @@ getent passwd i2pd >/dev/null || \
%changelog
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
- update to 2.42.1
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
- update to 2.42.0
* 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

View File

@@ -1,5 +1,5 @@
Name: i2pd
Version: 2.39.0
Version: 2.42.1
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -54,8 +54,14 @@ cd build
%endif
%endif
%if 0%{?fedora} >= 36
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -68,10 +74,16 @@ pushd build
make %{?_smp_mflags}
%if 0%{?fedora} >= 33
%if 0%{?rhel} == 9
popd
%endif
%if 0%{?fedora} >= 33
%if 0%{?fedora} < 37
popd
%endif
%endif
%if 0%{?mageia} > 7
popd
%endif
@@ -79,8 +91,14 @@ popd
%install
pushd build
%if 0%{?fedora} >= 36
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -143,6 +161,21 @@ getent passwd i2pd >/dev/null || \
%changelog
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
- update to 2.42.1
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
- update to 2.42.0
* 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

View File

@@ -1,35 +1,65 @@
/*
* 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: #FAFAFA;
color: #103456;
background: var(--main-bg-color);
color: var(--main-text-color);
}
a, .slide label {
text-decoration: none;
color: #894C84;
color: var(--main-link-color);
}
a:hover, .slide label:hover {
color: #FAFAFA;
background: #894C84;
a:hover, .slide label:hover, button[type=submit]:hover {
color: var(--main-link-hover-color);
background: var(--main-link-color);
}
a.button {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
padding: 0 5px;
border: 1px solid #894C84;
border: 1px solid var(--main-link-color);
}
.header {
font-size: 2.5em;
text-align: center;
margin: 1em 0;
color: #894C84;
color: var(--main-link-color);
}
.wrapper {
@@ -42,6 +72,7 @@ a.button {
display: block;
float: left;
overflow: hidden;
padding: 4px;
max-width: 12em;
white-space: nowrap;
text-overflow: ellipsis;
@@ -63,8 +94,9 @@ a.button {
.content {
float: left;
font-size: 1em;
margin-left: 4em;
max-width: 48em;
margin-left: 2em;
padding: 4px;
max-width: 50em;
overflow: auto;
}
@@ -87,7 +119,7 @@ a.button {
caption {
font-size: 1.5em;
text-align: center;
color: #894C84;
color: var(--main-link-color);
}
table {
@@ -105,6 +137,8 @@ table.services {
}
textarea {
background-color: var(--main-bg-color);
color: var(--main-text-color);
word-break: break-all;
}
@@ -133,24 +167,45 @@ textarea {
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;
}
.menu {
max-width: 10em;
}
.content {
margin-left: 2em;
max-width: 42em;
max-width: 40em;
}
}
@media screen and (max-width: 980px) {
body {
padding: 1.5em 0 0 0;
font: 100%/1.2em sans-serif;
padding: 1.2em 0 0 0;
}
.menu {
@@ -178,9 +233,7 @@ textarea {
}
a, .slide label {
/* margin-right: 10px; */
display: block;
/* font-size: 18px; */
}
.header {
@@ -193,13 +246,12 @@ textarea {
}
a.button {
-webkit-appearance: button;
-moz-appearance: button;
appearance: button;
text-decoration: none;
margin-top: 10px;
padding: 6px;
border: 1px solid #894c84;
border: 2px solid var(--main-link-color);
border-radius: 5px;
width: -webkit-fill-available;
}
@@ -207,8 +259,7 @@ textarea {
width: 35%;
text-align: center;
padding: 5px;
border: 2px solid #ccc;
-webkit-border-radius: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 18px;
}
@@ -221,17 +272,16 @@ textarea {
textarea {
width: -webkit-fill-available;
height: auto;
padding:5px;
border:2px solid #ccc;
-webkit-border-radius: 5px;
padding: 5px;
border: 2px solid var(--main-link-color);
border-radius: 5px;
font-size: 12px;
}
button[type=submit] {
padding: 5px 15px;
background: #ccc;
border: 0 none;
background: transparent;
border: 2px solid var(--main-link-color);
cursor: pointer;
-webkit-border-radius: 5px;
border-radius: 5px;

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
*
@@ -58,12 +58,16 @@ namespace util
bool Daemon_Singleton::IsService () const
{
bool service = false;
#ifndef _WIN32
i2p::config::GetOption("service", service);
#endif
return service;
}
void Daemon_Singleton::setDataDir(std::string path)
{
if (path != "")
DaemonDataDir = path;
}
bool Daemon_Singleton::init(int argc, char* argv[]) {
return init(argc, argv, nullptr);
}
@@ -73,8 +77,14 @@ namespace util
i2p::config::Init();
i2p::config::ParseCmdline(argc, argv);
std::string config; i2p::config::GetOption("conf", config);
std::string datadir; i2p::config::GetOption("datadir", datadir);
std::string config; i2p::config::GetOption("conf", config);
std::string datadir;
if(DaemonDataDir != "") {
datadir = DaemonDataDir;
} else {
i2p::config::GetOption("datadir", datadir);
}
i2p::fs::DetectDataDir(datadir, IsService());
i2p::fs::Init();
@@ -99,9 +109,9 @@ namespace util
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);
std::string logs = ""; i2p::config::GetOption("log", logs);
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
/* setup logging */
@@ -118,26 +128,26 @@ namespace util
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(eLogNone, "i2pd v", VERSION, " starting");
LogPrint(eLogDebug, "FS: main config file: ", config);
LogPrint(eLogDebug, "FS: data directory: ", datadir);
LogPrint(eLogDebug, "FS: certificates directory: ", certsdir);
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);
@@ -151,11 +161,7 @@ namespace util
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"))
@@ -204,7 +210,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);
@@ -244,6 +250,18 @@ namespace util
if (!ipv4 && !ipv6)
i2p::context.SetStatus (eRouterStatusMesh);
}
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
if (ssu2)
{
bool published; i2p::config::GetOption("ssu2.published", published);
if (published)
{
uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port);
i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish
}
else
i2p::context.PublishSSU2Address (0, false, ipv4, ipv6); // unpublish
}
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
@@ -252,7 +270,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
@@ -267,7 +285,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
{
@@ -275,18 +293,18 @@ 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'");
LogPrint(eLogInfo, "Daemon: Floodfill bandwidth set to 'extra'");
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2);
}
else
@@ -301,12 +319,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;
@@ -336,18 +354,18 @@ 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);
}
@@ -360,7 +378,7 @@ namespace util
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);
@@ -377,19 +395,20 @@ namespace util
}
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
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, ssu);
i2p::transport::transports.Start(ntcp2, ssu, ssu2);
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();
@@ -400,24 +419,28 @@ 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));
d.httpServer->SetDaemonStop (std::bind (Daemon_Singleton::stop, this));
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
d.httpServer->SetDaemonGracefulTimer (std::bind (gracefulShutdownInterval, this));
#endif
d.httpServer->Start();
}
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
@@ -425,7 +448,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));
@@ -433,7 +456,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 ());
}
}
@@ -442,10 +465,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)
@@ -460,18 +483,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;
}

View File

@@ -20,27 +20,33 @@ namespace util
class Daemon_Singleton_Private;
class Daemon_Singleton
{
public:
public:
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init(int argc, char* argv[]);
virtual bool start();
virtual bool stop();
virtual void run () {};
virtual bool init (int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
virtual bool init (int argc, char* argv[]);
virtual bool start ();
virtual bool stop ();
virtual void run () {};
bool isDaemon;
bool running;
virtual void setDataDir (std::string path);
protected:
bool isDaemon;
bool running;
Daemon_Singleton();
virtual ~Daemon_Singleton();
protected:
bool IsService () const;
Daemon_Singleton ();
virtual ~Daemon_Singleton ();
// d-pointer for httpServer, httpProxy, etc.
class Daemon_Singleton_Private;
Daemon_Singleton_Private &d;
bool IsService () const;
// d-pointer for httpServer, httpProxy, etc.
class Daemon_Singleton_Private;
Daemon_Singleton_Private &d;
private:
std::string DaemonDataDir;
};
#if defined(QT_GUI_LIB) // check if QT
@@ -69,14 +75,17 @@ namespace util
return instance;
}
bool init(int argc, char* argv[]);
bool start();
bool stop();
bool init (int argc, char* argv[]);
bool start ();
bool stop ();
void run ();
bool isGraceful;
void SetIsGraceful (bool state) { m_isGraceful = state; };
const bool GetIsGraceful () { return m_isGraceful; };
DaemonWin32 ():isGraceful(false) {}
private:
bool m_isGraceful;
};
#elif (defined(ANDROID) && !defined(ANDROID_BINARY))
#define Daemon i2p::util::DaemonAndroid::Instance()
@@ -103,8 +112,8 @@ namespace util
return instance;
}
bool start();
bool stop();
bool start ();
bool stop ();
void run ();
private:

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

View File

@@ -1,11 +1,13 @@
/*
* 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
*
* See full license text in LICENSE file at top of project tree
*/
#ifdef _WIN32
#include <thread>
#include <clocale>
#include "Config.h"
@@ -13,7 +15,7 @@
#include "util.h"
#include "Log.h"
#ifdef _WIN32
#include "Win32Service.h"
#ifdef WIN32_APP
#include <windows.h>
#include "Win32App.h"
@@ -37,8 +39,26 @@ namespace util
}
);
i2p::win32::SetIsGraceful (std::bind (&DaemonWin32::SetIsGraceful, this, std::placeholders::_1));
i2p::win32::GetIsGraceful (std::bind (&DaemonWin32::GetIsGraceful, this));
if (!Daemon_Singleton::init(argc, argv))
return false;
if (isDaemon)
{
LogPrint(eLogDebug, "Daemon: running as service");
I2PService service((PSTR)SERVICE_NAME);
service.SetDaemonStart (std::bind (&DaemonWin32::start, this));
service.SetDaemonStop (std::bind (&DaemonWin32::stop, this));
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
}
return true;
}

View File

@@ -1,3 +1,11 @@
/*
* 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>
@@ -48,39 +56,38 @@ 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);
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
// handlers
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
// I2PControl
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
// RouterInfo
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
&I2PControlService::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
@@ -96,10 +103,10 @@ namespace client
// ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
}
I2PControlService::~I2PControlService ()
@@ -142,7 +149,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 ());
}
}
}
@@ -160,10 +167,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);
}
@@ -176,7 +183,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));
@@ -202,7 +209,7 @@ namespace client
{
if (ecode)
{
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Read error: ", ecode.message ());
return;
}
else
@@ -225,7 +232,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
@@ -250,7 +257,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\"}";
@@ -259,7 +266,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 () << "\"},";
@@ -268,7 +275,7 @@ namespace client
}
catch (...)
{
LogPrint (eLogError, "I2PControl: handle request unknown exception");
LogPrint (eLogError, "I2PControl: Handle request unknown exception");
}
}
}
@@ -278,11 +285,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";
}
@@ -329,7 +341,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 ());
}
}
@@ -379,7 +391,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 ();
}
@@ -395,8 +407,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
@@ -406,7 +418,7 @@ namespace client
void I2PControlService::UptimeHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL));
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
}
void I2PControlService::VersionHandler (std::ostringstream& results)
@@ -466,7 +478,7 @@ namespace client
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
}
@@ -494,7 +506,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode)
{
{
Daemon.running = 0;
});
}
@@ -508,7 +520,7 @@ namespace client
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
m_ShutdownTimer.async_wait (
[](const boost::system::error_code& ecode)
{
{
Daemon.running = 0;
});
}
@@ -577,11 +589,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
@@ -590,12 +602,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);
}

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 ();
}
}
@@ -93,7 +93,7 @@ namespace transport
#endif
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;
@@ -106,7 +106,7 @@ 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;
}
@@ -117,22 +117,22 @@ namespace transport
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;
}
}
@@ -225,7 +225,7 @@ namespace transport
}
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)
{

View File

@@ -51,7 +51,7 @@ namespace transport
private:
void Discover ();
int CheckMapping (const char* port, const char* type);
int CheckMapping (const char* port, const char* type);
void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping ();
@@ -80,7 +80,7 @@ namespace transport
}
}
#else // USE_UPNP
#else // USE_UPNP
namespace i2p {
namespace transport {
/* class stub */

25
debian/changelog vendored
View File

@@ -1,3 +1,28 @@
i2pd (2.42.1-1) unstable; urgency=medium
* updated to version 2.42.1/0.9.54
* remove -O3 optimization flag
-- r4sas <r4sas@i2pmail.org> Tue, 24 May 2022 12:00:00 +0000
i2pd (2.42.0-1) unstable; urgency=medium
* updated to version 2.42.0/0.9.54
-- orignal <orignal@i2pmail.org> Sun, 22 May 2022 16:00:00 +0000
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

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: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -21,7 +21,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)
@@ -31,7 +31,7 @@ include filelist.mk
ifeq ($(DEBUG),yes)
USE_AESNI := $(or $(USE_AESNI),yes)
USE_STATIC := $(or $(USE_STATIC),no)
-USE_UPNP := $(or $(USE_UPNP),no)
+USE_UPNP := $(or $(USE_UPNP),yes)
DEBUG := $(or $(DEBUG),yes)
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string

9
debian/rules vendored
View File

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

View File

@@ -1,26 +1,7 @@
#LIB_SRC = \
# BloomFilter.cpp Gzip.cpp Crypto.cpp Datagram.cpp Garlic.cpp I2NPProtocol.cpp LeaseSet.cpp \
# Log.cpp NTCPSession.cpp NetDb.cpp NetDbRequests.cpp Profiling.cpp \
# Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \
# SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \
# Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \
# Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \
# Config.cpp HTTP.cpp Timestamp.cpp util.cpp api.cpp Gost.cpp
LIB_SRC = $(wildcard $(LIB_SRC_DIR)/*.cpp)
#LIB_CLIENT_SRC = \
# AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp MatchedDestination.cpp \
# SAM.cpp SOCKS.cpp HTTPProxy.cpp I2CP.cpp
LIB_CLIENT_SRC = $(wildcard $(LIB_CLIENT_SRC_DIR)/*.cpp)
# also: Daemon{Linux,Win32}.cpp will be added later
#DAEMON_SRC = \
# HTTPServer.cpp I2PControl.cpp UPnP.cpp Daemon.cpp i2pd.cpp
LANG_SRC = $(wildcard $(LANG_SRC_DIR)/*.cpp)
WEBCONSOLE_SRC = $(wildcard $(WEBCONSOLE_SRC_DIR)/*.cpp)
WRAP_LIB_SRC = $(wildcard $(WRAP_SRC_DIR)/*.cpp)
DAEMON_SRC = $(wildcard $(DAEMON_SRC_DIR)/*.cpp)
DAEMON_SRC = $(DAEMON_SRC_DIR)/Daemon.cpp $(DAEMON_SRC_DIR)/I2PControl.cpp $(DAEMON_SRC_DIR)/i2pd.cpp $(DAEMON_SRC_DIR)/UPnP.cpp

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

102
i18n/French.cpp Normal file
View File

@@ -0,0 +1,102 @@
/*
* 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"
// French localization file
namespace i2p
{
namespace i18n
{
namespace french // language namespace
{
// language name in lowercase
static std::string language = "french";
// 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", "Kio"},
{"MiB", "Mio"},
{"GiB", "Gio"},
{"building", "En construction"},
{"failed", "echoué"},
{"expiring", "expiré"},
{"established", "établi"},
{"unknown", "inconnu"},
{"exploratory", "exploratoire"},
{"<b>i2pd</b> webconsole", "Console web <b>i2pd</b>"},
{"Main page", "Page principale"},
{"Router commands", "Commandes du routeur"},
{"Local Destinations", "Destinations locales"},
{"Tunnels", "Tunnels"},
{"Transit Tunnels", "Tunnels transitoires"},
{"I2P tunnels", "Tunnels I2P"},
{"SAM sessions", "Sessions SAM"},
{"ERROR", "ERREUR"},
{"OK", "OK"},
{"Firewalled", "Derrière un pare-feu"},
{"Error", "Erreur"},
{"Offline", "Hors ligne"},
{"Uptime", "Temps de fonctionnement"},
{"Network status", "État du réseau"},
{"Network status v6", "État du réseau v6"},
{"Stopping in", "Arrêt dans"},
{"Family", "Famille"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Received", "Reçu"},
{"KiB/s", "kio/s"},
{"Sent", "Envoyé"},
{"Transit", "Transit"},
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour regarder."},
{"Router Ident", "Identifiant du routeur"},
{"Router Family", "Famille du routeur"},
{"Version", "Version"},
{"Our external address", "Notre adresse externe"},
{"Client Tunnels", "Tunnels clients"},
{"Services", "Services"},
{"Enabled", "Activé"},
{"Disabled", "Désactivé"},
{"Encrypted B33 address", "Adresse B33 chiffrée"},
{"Domain", "Domaine"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"Address", "Adresse"},
{"ms", "ms"},
{"Outbound tunnels", "Tunnels sortants"},
{"Destination", "Destination"},
{"Local Destination", "Destination locale"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"jour", "jours"}},
{"hours", {"heure", "heures"}},
{"minutes", {"minute", "minutes"}},
{"seconds", {"seconde", "secondes"}},
{"", {"", ""}},
};
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -9,7 +9,7 @@
#ifndef __I18N_H__
#define __I18N_H__
#include "RouterContext.h"
#include "ClientContext.h"
namespace i2p
{
@@ -19,19 +19,19 @@ namespace i18n
{
const auto it = i2p::i18n::languages.find(lang);
if (it == i2p::i18n::languages.end()) // fallback
i2p::context.SetLanguage (i2p::i18n::english::GetLocale());
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
else
i2p::context.SetLanguage (it->second.LocaleFunc());
i2p::client::context.SetLanguage (it->second.LocaleFunc());
}
inline std::string translate (const std::string& arg)
{
return i2p::context.GetLanguage ()->GetString (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::context.GetLanguage ()->GetPlural (arg, arg2, n);
return i2p::client::context.GetLanguage ()->GetPlural (arg, arg2, n);
}
} // i18n
} // i2p

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -72,19 +72,25 @@ namespace i18n
// Add localization here with language name as namespace
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace 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 and name in it's language
* 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} },
{ "french", {"Français", "fr", i2p::i18n::french::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} },

View File

@@ -26,7 +26,7 @@ namespace russian // language namespace
// 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;
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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -198,7 +198,6 @@ namespace turkmen // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
// ShowUptime
{"days", {"gün", "gün"}},
{"hours", {"sagat", "sagat"}},
{"minutes", {"minut", "minut"}},

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, The PurpleI2P Project
* Copyright (c) 2021-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -34,20 +34,21 @@ namespace uzbek // language namespace
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "qurilish"},
{"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"},
{"<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 Tunellar"},
{"Transit Tunnels", "Tranzit Tunellari"},
{"Transports", "Transportlar"},
{"I2P tunnels", "I2P tunnellar"},
{"I2P tunnels", "I2P tunnellari"},
{"SAM sessions", "SAM sessiyalari"},
{"ERROR", "XATO"},
{"OK", "OK"},
@@ -70,25 +71,25 @@ namespace uzbek // language namespace
{"KiB/s", "KiB/s"},
{"Sent", "Yuborilgan"},
{"Transit", "Tranzit"},
{"Data path", "Ma'lumotlar yo'li"},
{"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 Oila"},
{"Router Caps", "Router bayroqlari"},
{"Router Family", "Router oilasi"},
{"Router Caps", "Router Bayroqlari"},
{"Version", "Versiya"},
{"Our external address", "Bizning tashqi manzilimiz"},
{"supported", "qo'llab -quvvatlanadi"},
{"supported", "qo'llab-quvvatlanadi"},
{"Routers", "Routerlar"},
{"Floodfills", "Floodfills"},
{"Client Tunnels", "Mijoz tunellari"},
{"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", "Varatish"},
{"<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."},
{"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"},
@@ -99,10 +100,11 @@ namespace uzbek // language namespace
{"Incoming", "Kiruvchi"},
{"Outgoing", "Chiquvchi"},
{"Destination", "Manzilgoh"},
{"Amount", "Yig'indi"},
{"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"},
@@ -117,14 +119,15 @@ namespace uzbek // language namespace
{"not floodfill", "floodfill emas"},
{"Queue size", "Navbat hajmi"},
{"Run peer test", "Sinovni boshlang"},
{"Decline transit tunnels", "Tranzit tunnellarni rad etish"},
{"Decline transit tunnels", "Tranzit tunnellarini rad etish"},
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qiling"},
{"Start graceful shutdown", "Yumshoq to'xtashni boshlang"},
{"Force shutdown", "Bizning tashqi manzilimiz"},
{"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> bu erda qilingan har qanday harakat doimiy emas va konfiguratsiya fayllarini o'zgartirmaydi."},
{"Transit tunnels limit", "Tranzit tunellar chegarasi"},
{"<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"},
@@ -142,8 +145,8 @@ namespace uzbek // language namespace
{"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", "Belgilangan sahifaga qaytish"},
{"You will be redirected in 5 seconds", "Siz 5 soniyada qayta yo'naltirilasiz"},
{"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"},
@@ -159,29 +162,35 @@ namespace uzbek // language namespace
{"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 tahlil qila olmaydi"},
{"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"},
{"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 proksi -serverni aniqlab olib bolmaydi"},
{"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 soks proksi -serveriga ulanib bo'lmaydi"},
{"Cannot negotiate with socks proxy", "Soks proksi bilan muzokara olib bo'lmaydi"},
{"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", "Ulanmadi"},
{"socks proxy error", "soks proksi xatosi"},
{"failed to send request to upstream", "yuqori http proksi-serveriga ulanib bo'lmadi"},
{"No Reply From socks proxy", "Soks-proksidan javob yo'q"},
{"cannot connect", "ulab bo'lmaydi"},
{"http out proxy not implemented", "tashqi HTTP proksi -serverni qo'llab -quvvatlash amalga oshirilmagan"},
{"cannot connect to upstream http proxy", "yuqori http proksi-serveriga ulanib bo'lmadi"},
{"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."},
{"", ""},
@@ -189,10 +198,10 @@ namespace uzbek // language namespace
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"kun", "kunlar"}},
{"days", {"kun", "kun"}},
{"hours", {"soat", "soat"}},
{"minutes", {"daqiqa", "daqiqalar"}},
{"seconds", {"soniya", "soniyalar"}},
{"minutes", {"daqiqa", "daqiqa"}},
{"seconds", {"soniya", "soniya"}},
{"", {"", ""}},
};

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

@@ -24,8 +24,8 @@ namespace data {
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
/**
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
size_t Base64EncodingBufferSize(const size_t input_size);
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -99,7 +99,7 @@ namespace data
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
{
size_t publicKeyLength = 0;
size_t publicKeyLength = 0;
EC_GROUP * group = nullptr;
switch (sigType)
{
@@ -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)
{
@@ -146,7 +146,10 @@ namespace data
m_PublicKey.resize (len);
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
m_SigType = identity->GetSigningKeyType ();
m_BlindedSigType = m_SigType;
if (m_SigType == i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
m_BlindedSigType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519; // 7 -> 11
else
m_BlindedSigType = m_SigType;
}
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
@@ -156,7 +159,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 +189,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 +259,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;
}
@@ -272,21 +275,21 @@ namespace data
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
publicKeyLength = BlindECDSA (m_SigType, priv, seed, BlindEncodedPrivateKeyECDSA, blindedPriv, blindedPub);
break;
break;
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
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:
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
{
uint8_t exp[64];
i2p::crypto::Ed25519::ExpandPrivateKey (priv, exp);
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;
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;
}
@@ -324,7 +327,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

@@ -28,8 +28,8 @@ namespace data
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes

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
*
@@ -61,7 +61,7 @@ namespace config {
("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)")
@@ -78,9 +78,9 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
;
options_description httpserver("HTTP Server options");
@@ -109,6 +109,8 @@ namespace config {
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
("httpproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy inbound tunnels length variance")
("httpproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy outbound tunnels length variance")
("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels")
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
@@ -130,6 +132,8 @@ namespace config {
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
("socksproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy inbound tunnels length variance")
("socksproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy outbound tunnels length variance")
("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels")
("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels")
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
@@ -203,28 +207,36 @@ 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/,"
"https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/,"
"http://[301:65b9:c7cd:9a36::1]:18801/,"
"http://[320:8936:ec1a:31f1::216]/"
"http://[301:65b9:c7cd:9a36::1]:18801/,"
"http://[320:8936:ec1a:31f1::216]/,"
"http://[306:3834:97b9:a00a::1]/,"
"http://[316:f9e0:f22e:a74f::216]/"
), "Reseed URLs through the Yggdrasil, separated by comma")
;
options_description addressbook("AddressBook options");
addressbook.add_options()
("addressbook.enabled", value<bool>()->default_value(true), "Enable address book lookups and subscritions (default: enabled)")
("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("http://reg.i2p/hosts.txt"), "AddressBook subscriptions URLs, separated by comma")
("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");
@@ -260,6 +272,13 @@ namespace config {
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
;
options_description ssu2("SSU2 Options");
ssu2.add_options()
("ssu2.enabled", value<bool>()->default_value(false), "Enable SSU2 (default: disabled)")
("ssu2.published", value<bool>()->default_value(false), "Publish SSU2 (default: disabled)")
("ssu2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming SSU2 packets (default: auto)")
;
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
@@ -268,8 +287,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");
@@ -309,6 +329,7 @@ namespace config {
.add(websocket) // deprecated
.add(exploratory)
.add(ntcp2)
.add(ssu2)
.add(nettime)
.add(persist)
.add(cpuext)

View File

@@ -29,16 +29,16 @@ namespace config {
extern boost::program_options::variables_map m_Options;
/**
* @brief Initialize list of acceptable parameters
* @brief Initialize list of acceptable parameters
*
* Should be called before any Parse* functions.
*/
void Init();
/**
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
*
* If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0.
@@ -52,8 +52,8 @@ namespace config {
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
/**
* @brief Load and parse given config file
* @param path Path to config file
* @brief Load and parse given config file
* @param path Path to config file
*
* If error occurred when opening file path is points to,
* we show the error message and terminate program.
@@ -67,14 +67,14 @@ namespace config {
void ParseConfig(const std::string& path);
/**
* @brief Used to combine options from cmdline, config and default values
* @brief Used to combine options from cmdline, config and default values
*/
void Finalize();
/**
* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @return this function returns false if parameter not found
*
* Example: uint16_t port; GetOption("sam.port", port);
@@ -98,9 +98,9 @@ namespace config {
bool GetOptionAsAny(const std::string& name, boost::any& value);
/**
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @return true if value set up successful, false otherwise
*
* Example: uint16_t port = 2827; SetOption("bob.port", port);
@@ -116,8 +116,8 @@ namespace config {
}
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false otherwise
*/
bool IsDefault(const char *name);

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
*
@@ -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;
@@ -1330,13 +1305,23 @@ namespace crypto
SHA256_Final (m_H, &ctx);
}
void NoiseSymmetricState::MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs)
{
SHA256_CTX ctx;
SHA256_Init (&ctx);
SHA256_Update (&ctx, m_H, 32);
for (const auto& it: bufs)
SHA256_Update (&ctx, it.first, it.second);
SHA256_Final (m_H, &ctx);
}
void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
{
HKDF (m_CK, sharedSecret, 32, "", m_CK);
// 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)
@@ -1345,23 +1330,23 @@ namespace crypto
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
}
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,8 +1356,23 @@ 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)
{
@@ -1386,9 +1386,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
*
@@ -29,21 +29,25 @@
#include "CPU.h"
// recognize openssl version and features
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3050200fL)) // LibreSSL 3.5.2 and above
# define LEGACY_OPENSSL 0
#elif ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# define OPENSSL_SIPHASH 1
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 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
# endif
#endif
namespace i2p
@@ -93,7 +97,7 @@ namespace crypto
bool IsElligatorIneligible () const { return m_IsElligatorIneligible; }
void SetElligatorIneligible () { m_IsElligatorIneligible = true; }
private:
uint8_t m_PublicKey[32];
@@ -104,17 +108,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 +319,15 @@ 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 MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs);
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 ();
@@ -379,7 +385,7 @@ inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
if (dh->p) BN_free (dh->p);
if (dh->q) BN_free (dh->q);
if (dh->g) BN_free (dh->g);
dh->p = p; dh->q = q; dh->g = g; return 1;
dh->p = p; dh->q = q; dh->g = g; return 1;
}
inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_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
*
@@ -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)
@@ -316,7 +324,7 @@ namespace datagram
auto path = m_RoutingSession->GetSharedRoutingPath();
if (path && m_RoutingSession->IsRatchets () &&
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
{
m_RoutingSession->SetSharedRoutingPath (nullptr);
path = nullptr;
@@ -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
*
@@ -13,7 +13,6 @@
#include <vector>
#include <boost/algorithm/string.hpp>
#include "Crypto.h"
#include "Config.h"
#include "Log.h"
#include "FS.h"
#include "Timestamp.h"
@@ -35,6 +34,8 @@ namespace client
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE;
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
int numTags = DEFAULT_TAGS_TO_SEND;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
try
@@ -53,10 +54,16 @@ namespace client
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY);
if (it != params->end ())
outQty = std::stoi(it->second);
it = params->find (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE);
if (it != params->end ())
inVar = std::stoi(it->second);
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE);
if (it != params->end ())
outVar = std::stoi(it->second);
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));
@@ -86,10 +93,8 @@ namespace client
if (it != params->end ())
{
// oveeride isPublic
bool dontpublish = false;
i2p::config::GetOption (it->second, dontpublish);
m_IsPublic = !dontpublish;
}
m_IsPublic = (it->second != "true");
}
it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ())
m_LeaseSetType = std::stoi(it->second);
@@ -112,7 +117,7 @@ namespace client
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{
LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second);
LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr);
}
}
@@ -120,10 +125,10 @@ 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);
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar);
if (explicitPeers)
m_Pool->SetExplicitPeers (explicitPeers);
if(params)
@@ -136,7 +141,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);
}
}
@@ -251,7 +256,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;
@@ -331,6 +336,22 @@ namespace client
return true;
}
void LeaseSetDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
{
struct
{
uint8_t k[32];
uint64_t t;
} data;
memcpy (data.k, key, 32);
data.t = tag;
auto s = shared_from_this ();
m_Service.post ([s,data](void)
{
s->AddECIESx25519Key (data.k, data.t);
});
}
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
@@ -367,8 +388,8 @@ namespace client
HandleDatabaseSearchReplyMessage (payload, len);
break;
case eI2NPShortTunnelBuildReply: // might come as garlic encrypted
i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID));
break;
i2p::HandleI2NPMessage (CreateI2NPMessage (typeID, payload, len, msgID));
break;
default:
LogPrint (eLogWarning, "Destination: Unexpected I2NP message type ", typeID);
return false;
@@ -395,8 +416,8 @@ 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 () &&
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
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))
@@ -487,7 +508,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
}
}
@@ -555,16 +576,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);
@@ -574,6 +588,33 @@ namespace client
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);
@@ -618,7 +659,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 ();
@@ -630,7 +671,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;
@@ -639,7 +680,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 ();
});
@@ -751,10 +792,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)
@@ -767,11 +808,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 (
{
@@ -866,8 +907,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)
@@ -910,22 +951,22 @@ namespace client
for (auto& it: encryptionKeyTypes)
{
auto encryptionKey = new EncryptionKey (it);
if (isPublic)
if (IsPublic ())
PersistTemporaryKeys (encryptionKey, isSingleKey);
else
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);
}
if (isPublic)
if (IsPublic ())
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
try
@@ -938,8 +979,8 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ())
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
m_IsStreamingAnswerPings = (it->second == "true");
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
// authentication for encrypted LeaseSet
@@ -966,7 +1007,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());
}
}
@@ -1042,7 +1083,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]);
}
}
@@ -1050,7 +1091,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);
@@ -1074,7 +1115,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 ();
@@ -1096,6 +1137,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)
@@ -1153,18 +1223,18 @@ namespace client
auto ret = it->second;
m_StreamingDestinationsByPorts.erase (it);
return ret;
}
}
}
return nullptr;
}
}
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
{
if (m_DatagramDestination == nullptr)
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
return m_DatagramDestination;
}
}
std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
{
std::vector<std::shared_ptr<const i2p::stream::Stream> > ret;
@@ -1245,15 +1315,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-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -53,6 +53,10 @@ namespace client
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
const char I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE[] = "inbound.lengthVariance";
const int DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE = 0;
const char I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE[] = "outbound.lengthVariance";
const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0;
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
@@ -68,8 +72,8 @@ namespace client
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
// latency
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
@@ -80,7 +84,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;
@@ -134,11 +138,13 @@ namespace client
// override GarlicDestination
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag);
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
void SetLeaseSetUpdated ();
bool IsPublic () const { return m_IsPublic; };
void SetPublic (bool pub) { m_IsPublic = pub; };
protected:
@@ -242,19 +248,21 @@ namespace client
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;

View File

@@ -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,21 +115,21 @@ namespace garlic
auto session = GetSession ();
if (!session) return false;
return session->HandleNextMessage (buf, len, shared_from_this (), index);
}
}
SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
memcpy (m_Key, key, 32);
Expire ();
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
{
@@ -137,33 +137,33 @@ namespace garlic
return false;
}
// we assume 1 I2NP block with delivery type local
if (offset + 3 > len)
{
if (offset + 3 > len)
{
LogPrint (eLogWarning, "Garlic: Symmetric key tagset is too short ", len);
return false;
}
}
if (buf[offset] != eECIESx25519BlkGalicClove)
{
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: 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 attachLeaseSetNS):
GarlicRoutingSession (owner, true)
{
if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
if (!attachLeaseSetNS) SetLeaseSetUpdateStatus (eLeaseSetUpToDate);
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
}
@@ -181,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
@@ -194,7 +194,7 @@ namespace garlic
}
else
i2p::transport::transports.ReuseX25519KeysPair (m_EphemeralKeys);
}
}
// we still didn't find elligator eligible pair
for (int i = 0; i < 25; i++)
{
@@ -208,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;
@@ -229,7 +229,7 @@ namespace garlic
// we are Bob
// KDF1
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");
@@ -239,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
@@ -263,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
@@ -280,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;
@@ -314,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
@@ -322,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++)
@@ -334,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);
@@ -381,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);
@@ -424,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");
}
}
@@ -446,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)
@@ -468,7 +468,7 @@ namespace garlic
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return false;
}
}
MixKey (sharedSecret);
// encrypt flags/static key section
uint8_t nonce[12];
@@ -478,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
@@ -486,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);
@@ -503,10 +503,10 @@ 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 ())
{
@@ -514,11 +514,11 @@ namespace garlic
InitNewSessionTagset (tagsetNsr);
tagsetNsr->Expire (); // let non-replied session expire
GenerateMoreReceiveTags (tagsetNsr, ECIESX25519_NSR_NUM_GENERATED_TAGS);
}
}
}
return true;
}
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Bob
@@ -534,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
@@ -545,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);
@@ -584,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
@@ -618,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
@@ -637,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];
@@ -700,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)
@@ -736,7 +736,7 @@ namespace garlic
}
HandlePayload (payload, len - 16, receiveTagset, index);
if (GetOwner ())
{
{
int moreTags = 0;
if (GetOwner ()->GetNumRatchetInboundTags () > 0) // override in settings?
{
@@ -745,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;
}
@@ -774,13 +774,13 @@ 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:
@@ -792,7 +792,7 @@ namespace garlic
}
return true;
}
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
{
uint8_t * payload = GetOwner ()->GetPayloadBuffer ();
@@ -829,7 +829,7 @@ namespace garlic
if (!NewOutgoingSessionMessage (payload, len, buf, m->maxLen, false))
return nullptr;
len += 96;
break;
break;
default:
return nullptr;
}
@@ -844,18 +844,18 @@ namespace garlic
{
m_State = eSessionStateOneTime;
return WrapSingleMessage (msg);
}
}
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
@@ -896,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;
@@ -912,9 +912,9 @@ namespace garlic
{
if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
{
LogPrint (eLogError, "Garlic: payload length ", payloadLen, " is too long");
LogPrint (eLogError, "Garlic: Payload length ", payloadLen, " is too long");
return 0;
}
}
m_LastSentTimestamp = ts;
size_t offset = 0;
// DateTime
@@ -993,7 +993,7 @@ namespace garlic
htobe16buf (payload + offset, paddingSize); offset += 2;
memset (payload + offset, 0, paddingSize); offset += paddingSize;
}
}
}
return payloadLen;
}
@@ -1050,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)
@@ -1073,9 +1073,9 @@ namespace garlic
RouterIncomingRatchetSession::RouterIncomingRatchetSession (const i2p::crypto::NoiseSymmetricState& initState):
ECIESX25519AEADRatchetSession (&i2p::context, false)
{
SetLeaseSetUpdateStatus (eLeaseSetDoNotSend);
SetLeaseSetUpdateStatus (eLeaseSetDoNotSend);
SetNoiseState (initState);
}
}
bool RouterIncomingRatchetSession::HandleNextMessage (const uint8_t * buf, size_t len)
{
@@ -1084,16 +1084,16 @@ namespace garlic
// we are Bob
m_CurrentNoiseState.MixHash (buf, 32);
uint8_t sharedSecret[32];
if (!GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) // x25519(bsk, aepk)
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;
buf += 32; len -= 32;
uint8_t nonce[12];
CreateNonce (0, nonce);
std::vector<uint8_t> payload (len - 16);
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
{
@@ -1102,20 +1102,20 @@ namespace garlic
}
HandlePayload (payload.data (), len - 16, nullptr, 0);
return true;
}
}
static size_t CreateGarlicPayload (std::shared_ptr<const I2NPMessage> msg, uint8_t * payload,
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;
payload[0] = eECIESx25519BlkDateTime;
htobe16buf (payload + 1, 4);
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
htobe32buf (payload + 3, i2p::util::GetSecondsSinceEpoch ());
len = 7;
}
}
// I2NP
payload += len;
uint16_t cloveSize = msg->GetPayloadLength () + 10;
@@ -1139,14 +1139,14 @@ namespace garlic
delta -= 3;
if (paddingSize > delta) paddingSize %= delta;
}
payload[0] = eECIESx25519BlkPadding;
htobe16buf (payload + 1, paddingSize);
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 ();
@@ -1188,8 +1188,8 @@ namespace garlic
{
LogPrint (eLogWarning, "Garlic: Incorrect Bob static key");
return nullptr;
}
noiseState.MixKey (sharedSecret);
}
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];
@@ -1205,6 +1205,6 @@ namespace garlic
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
return m;
}
}
}
}

View File

@@ -1,4 +1,3 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
*
@@ -28,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
@@ -46,7 +45,7 @@ namespace garlic
RatchetTagSet () {};
virtual ~RatchetTagSet () {};
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
void NextSessionTagRatchet ();
uint64_t GetNextSessionTag ();
@@ -57,14 +56,14 @@ namespace garlic
int GetTagSetID () const { return m_TagSetID; };
void SetTagSetID (int tagsetID) { m_TagSetID = tagsetID; };
private:
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;
};
@@ -74,27 +73,27 @@ 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 SymmetricKeyTagSet: public ReceiveRatchetTagSet
{
@@ -104,13 +103,13 @@ namespace garlic
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,
@@ -128,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>
{
@@ -158,10 +157,10 @@ namespace garlic
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<ReceiveRatchetTagSet> receiveTagset, int index = 0);
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
std::shared_ptr<I2NPMessage> 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:
{
@@ -171,19 +170,19 @@ 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:
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:
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
@@ -198,7 +197,7 @@ namespace garlic
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);
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);
@@ -213,7 +212,7 @@ namespace garlic
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
m_LastSentTimestamp = 0; // in milliseconds
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRSendTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
@@ -221,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
@@ -230,7 +229,7 @@ namespace garlic
{
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
}
};
};
// single session for all incoming messages
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
@@ -240,12 +239,12 @@ namespace garlic
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);
}

View File

@@ -33,7 +33,7 @@ namespace crypto
BN_add (l, l, tmp);
BN_sub_word (two_252_2, 2); // 2^252 - 2
// -121665*inv(121666)
// -121665*inv(121666)
d = BN_new ();
BN_set_word (tmp, 121666);
BN_mod_inverse (tmp, tmp, q, ctx);
@@ -61,7 +61,7 @@ namespace crypto
BN_mod (By, By, q, ctx); // % q
// precalculate Bi256 table
Bi256Carry = { Bx, By }; // B
Bi256Carry = { Bx, By }; // B
for (int i = 0; i < 32; i++)
{
Bi256[i][0] = Bi256Carry; // first point
@@ -215,7 +215,7 @@ namespace crypto
if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); }
if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); }
BN_mul (t3, t1, t2, ctx);
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
if (p1.z)
{
@@ -264,9 +264,9 @@ namespace crypto
else
{
BN_mul (t2, p.x, p.y, ctx); // t = x*y
BN_sqr (t2, t2, ctx); // t2 = t^2
BN_sqr (t2, t2, ctx); // t2 = t^2
}
BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2
BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2
if (p.z)
BN_sqr (z2, p.z, ctx); // z2 = D = z^2
else
@@ -349,7 +349,7 @@ namespace crypto
BN_mod_inverse (y, p.z, q, ctx);
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
return EDDSAPoint{x, y};
return EDDSAPoint{x, y};
}
else
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
@@ -506,13 +506,13 @@ namespace crypto
std::swap (z2, z3);
}
BN_mod_inverse (z2, z2, q, ctx);
BIGNUM * res = BN_new (); // not from ctx
BIGNUM * res = BN_new (); // not from ctx
BN_mod_mul(res, x2, z2, q, ctx);
BN_CTX_end (ctx);
return res;
}
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM * p1 = DecodeBN<32> (p);
uint8_t k[32];
@@ -524,7 +524,7 @@ namespace crypto
BN_free (p1); BN_free (n); BN_free (q1);
}
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
uint8_t k[32];

View File

@@ -85,8 +85,8 @@ namespace crypto
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
#if !OPENSSL_X25519
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
#endif
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32

View File

@@ -189,7 +189,7 @@ namespace crypto
// assume a < p, so don't check for a % p = 0, but a = 0 only
if (BN_is_zero(a)) return 0;
BIGNUM * r = BN_CTX_get (ctx);
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
if (BN_is_word(r, 1))
return 1;
else if (BN_is_zero(r))

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
*
@@ -60,10 +60,38 @@ namespace fs {
}
void DetectDataDir(const std::string & cmdline_param, bool isService) {
// with 'datadir' option
if (cmdline_param != "") {
dataDir = cmdline_param;
return;
}
#if !defined(MAC_OSX) && !defined(ANDROID)
// with 'service' option
if (isService) {
#ifdef _WIN32
wchar_t commonAppData[MAX_PATH];
if(SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, commonAppData) != S_OK)
{
#ifdef WIN32_APP
MessageBox(NULL, TEXT("Unable to get common AppData path!"), TEXT("I2Pd: error"), MB_ICONERROR | MB_OK);
#else
fprintf(stderr, "Error: Unable to get common AppData path!");
#endif
exit(1);
}
else
{
dataDir = boost::filesystem::wpath(commonAppData).string() + "\\" + appName;
}
#else
dataDir = "/var/lib/" + appName;
#endif
return;
}
#endif
// detect directory as usual
#ifdef _WIN32
wchar_t localAppData[MAX_PATH];
@@ -117,12 +145,10 @@ namespace fs {
dataDir = std::string (ext) + "/" + appName;
return;
}
#endif
// otherwise use /data/files
#endif // ANDROID
// use /home/user/.i2pd or /tmp/i2pd
char *home = getenv("HOME");
if (isService) {
dataDir = "/var/lib/" + appName;
} else if (home != NULL && strlen(home) > 0) {
if (home != NULL && strlen(home) > 0) {
dataDir = std::string(home) + "/." + appName;
} else {
dataDir = "/tmp/" + appName;

View File

@@ -83,8 +83,8 @@ namespace fs {
/**
* @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
*
* Examples of autodetected paths:
*
@@ -93,11 +93,11 @@ 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>
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
*
* Examples of autodetected paths:
*
@@ -106,7 +106,7 @@ namespace fs {
* 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);
void SetCertsDir(const std::string & cmdline_certsdir);
/**
* @brief Create subdirectories inside datadir
@@ -115,7 +115,7 @@ namespace fs {
/**
* @brief Get list of files in directory
* @param path Path to directory
* @param path Path to directory
* @param files Vector to store found files
* @return true on success and false if directory not exists
*/

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
*
@@ -88,7 +88,7 @@ namespace data
}
EVP_PKEY_free (pkey);
if (verifier && cn)
m_SigningKeys[cn] = verifier;
m_SigningKeys.emplace (cn, std::make_pair(verifier, m_SigningKeys.size () + 1));
}
SSL_free (ssl);
}
@@ -121,7 +121,7 @@ namespace data
}
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
const char * signature, const char * key)
const char * signature, const char * key) const
{
uint8_t buf[100], signatureBuf[64];
size_t len = family.length (), signatureLen = strlen (signature);
@@ -137,11 +137,19 @@ namespace data
Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
auto it = m_SigningKeys.find (family);
if (it != m_SigningKeys.end ())
return it->second->Verify (buf, len, signatureBuf);
return it->second.first->Verify (buf, len, signatureBuf);
// TODO: process key
return true;
}
FamilyID Families::GetFamilyID (const std::string& family) const
{
auto it = m_SigningKeys.find (family);
if (it != m_SigningKeys.end ())
return it->second.second;
return 0;
}
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident)
{
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));

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 @@ namespace i2p
{
namespace data
{
typedef int FamilyID;
class Families
{
public:
@@ -27,7 +28,8 @@ namespace data
~Families ();
void LoadCertificates ();
bool VerifyFamily (const std::string& family, const IdentHash& ident,
const char * signature, const char * key = nullptr);
const char * signature, const char * key = nullptr) const;
FamilyID GetFamilyID (const std::string& family) const;
private:
@@ -35,7 +37,7 @@ namespace data
private:
std::map<std::string, std::shared_ptr<i2p::crypto::Verifier> > m_SigningKeys;
std::map<std::string, std::pair<std::shared_ptr<i2p::crypto::Verifier>, FamilyID> > m_SigningKeys; // family -> (verifier, id)
};
std::string CreateFamilySignature (const std::string& family, const IdentHash& 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
*
@@ -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)++;
@@ -295,14 +293,14 @@ namespace garlic
size_t size = 0;
if (isDestination)
{
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
size++;
memcpy (buf + size, m_Destination->GetIdentHash (), 32);
size += 32;
}
else
{
buf[size] = 0;// delivery instructions flag local
buf[size] = 0;// delivery instructions flag local
size++;
}
@@ -435,12 +433,10 @@ namespace garlic
GarlicDestination::GarlicDestination (): m_NumTags (32), // 32 tags by default
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;
}
@@ -456,7 +452,7 @@ namespace garlic
{
it.second->Terminate ();
it.second->SetOwner (nullptr);
}
}
m_ECIESx25519Sessions.clear ();
m_ECIESx25519Tags.clear ();
}
@@ -474,27 +470,32 @@ namespace garlic
uint64_t t;
memcpy (&t, tag, 8);
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);
return true;
}
void GarlicDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
{
AddECIESx25519Key (key, tag);
}
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
uint8_t * buf = msg->GetPayload ();
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
@@ -502,10 +503,10 @@ namespace garlic
bool found = false;
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
// try ECIESx25519 tag
// 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
@@ -523,7 +524,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
{
@@ -531,7 +532,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
@@ -546,37 +547,37 @@ 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
// 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");
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 == missingTag)
{
LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated");
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");
}
}
}
}
@@ -589,14 +590,14 @@ namespace garlic
{
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");
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)
{
@@ -633,7 +634,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);
@@ -643,7 +644,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];
@@ -658,7 +659,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;
@@ -666,35 +667,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);
@@ -725,32 +726,32 @@ 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
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
buf += 4; // CloveID
buf += 8; // Date
buf += 3; // Certificate
offset = buf - buf1;
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: clove is too long");
LogPrint (eLogError, "Garlic: Clove is too long");
break;
}
len -= offset;
@@ -763,10 +764,10 @@ namespace garlic
if (router->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
return WrapECIESX25519MessageForRouter (msg, router->GetIdentity ()->GetEncryptionPublicKey ());
else
{
{
auto session = GetRoutingSession (router, false);
return session->WrapSingleMessage (msg);
}
}
}
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
@@ -777,17 +778,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);
@@ -844,7 +845,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);
}
@@ -883,18 +884,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 = m_ECIESx25519Tags.erase (it);
numExpiredTags++;
}
}
else
++it;
}
}
}
if (numExpiredTags > 0)
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
@@ -929,7 +930,7 @@ namespace garlic
if (session)
{
session->MessageConfirmed (msgID);
LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged");
LogPrint (eLogDebug, "Garlic: Message ", msgID, " acknowledged");
}
}
@@ -1023,7 +1024,7 @@ namespace garlic
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it);
i2p::fs::Remove (it);
}
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
@@ -1034,7 +1035,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]];
@@ -1042,7 +1043,7 @@ namespace garlic
// no break here
case eGarlicDeliveryTypeLocal:
{
LogPrint (eLogDebug, "Garlic: type local");
LogPrint (eLogDebug, "Garlic: Type local");
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
int32_t msgID = bufbe32toh (buf); buf += 4; // msgID
buf += 4; // expiration
@@ -1050,19 +1051,19 @@ namespace garlic
if (offset <= (int)len)
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;
@@ -1083,7 +1084,7 @@ namespace garlic
break;
}
default:
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
LogPrint (eLogWarning, "Garlic: Unexpected delivery type ", (int)deliveryType);
}
}
@@ -1103,13 +1104,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;
}
}
@@ -1131,6 +1132,6 @@ namespace garlic
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-2022, 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 ()
@@ -245,13 +245,14 @@ namespace garlic
void AddSessionKey (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
virtual void SubmitECIESx25519Key (const uint8_t * key, uint64_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);
virtual void SetLeaseSetUpdated ();
@@ -279,7 +280,6 @@ namespace garlic
private:
BN_CTX * m_Ctx; // incoming
// outgoing sessions
int m_NumTags;
std::mutex m_SessionsMutex;

View File

@@ -96,7 +96,7 @@ namespace crypto
EC_POINT * C = EC_POINT_new (m_Group);
EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub
BIGNUM * x = BN_CTX_get (ctx);
GetXY (C, x, nullptr); // Cx
GetXY (C, x, nullptr); // Cx
BN_mod (x, x, q, ctx); // Cx % q
bool ret = !BN_cmp (x, r); // Cx = r ?
EC_POINT_free (C);
@@ -111,8 +111,8 @@ namespace crypto
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry)
EC_POINT * Q = nullptr;
if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx))
EC_POINT * Q = nullptr;
if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx))
{
EC_POINT * S = EC_POINT_new (m_Group); // S = s*P
EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx);

View File

@@ -14,9 +14,9 @@
#include "Base.h"
#include "HTTP.h"
namespace i2p
namespace i2p
{
namespace http
namespace http
{
const std::vector<std::string> HTTP_METHODS = {
"GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "CONNECT", // HTTP basic methods
@@ -279,7 +279,7 @@ namespace http
method = tokens[0];
uri = tokens[1];
version = tokens[2];
expect = HEADER_LINE;
expect = HEADER_LINE;
}
else
{
@@ -363,7 +363,7 @@ namespace http
return false; /* no header */
if (it->second.find("gzip") != std::string::npos)
return true; /* gotcha! */
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
return true;
return false;
}
@@ -409,7 +409,7 @@ namespace http
/* all ok */
version = tokens[0];
status = tokens[2];
expect = HEADER_LINE;
expect = HEADER_LINE;
} else {
std::string line = str.substr(pos, eol - pos);
auto p = parse_header_line(line);
@@ -460,7 +460,7 @@ namespace http
case 304: ptr = "Not Modified"; break;
case 307: ptr = "Temporary Redirect"; break;
/* client error */
case 400: ptr = "Bad Request"; break;
case 400: ptr = "Bad Request"; break;
case 401: ptr = "Unauthorized"; break;
case 403: ptr = "Forbidden"; break;
case 404: ptr = "Not Found"; break;
@@ -471,19 +471,19 @@ namespace http
case 502: ptr = "Bad Gateway"; break;
case 503: ptr = "Not Implemented"; break;
case 504: ptr = "Gateway Timeout"; break;
default: ptr = "Unknown Status"; break;
default: ptr = "Unknown Status"; break;
}
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;
@@ -494,10 +494,10 @@ 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;
@@ -522,6 +522,6 @@ namespace http
if (user.empty () && pass.empty ()) return "";
return "Basic " + i2p::data::ToBase64Standard (user + ":" + pass);
}
} // http
} // i2p

View File

@@ -161,14 +161,14 @@ namespace http
/**
* @brief Merge HTTP response content with Transfer-Encoding: chunked
* @param in Input stream
* @param in Input stream
* @param out Output stream
* @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);
std::string CreateBasicAuthorizationString (const std::string& user, const std::string& pass);
} // http
} // i2p

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -38,20 +38,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
{
I2NPMessage * msg = nullptr;
if (endpoint)
{
// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6
msg->Align (6);
msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header
}
else
{
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)
@@ -88,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;
}
@@ -103,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;
}
@@ -183,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 ();
@@ -222,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);
@@ -256,7 +243,7 @@ namespace i2p
return m;
}
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
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
@@ -267,7 +254,7 @@ namespace i2p
LogPrint (eLogError, "I2NP: Invalid RouterInfo buffer for DatabaseStore");
return nullptr;
}
auto m = NewI2NPShortMessage ();
uint8_t * payload = m->GetPayload ();
@@ -285,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;
@@ -303,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
@@ -391,78 +378,50 @@ namespace i2p
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
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] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) :
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] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_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 = 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
{
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;
}
@@ -499,75 +458,28 @@ 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] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) // 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] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) // 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)));
}
}
}
}
static void HandleTunnelBuildMsg (uint8_t * buf, size_t len)
{
if (i2p::context.IsECIES ())
{
LogPrint (eLogWarning, "I2NP: TunnelBuild is too old for ECIES router");
return;
}
if (len < NUM_TUNNEL_BUILD_RECORDS*TUNNEL_BUILD_RECORD_SIZE)
{
LogPrint (eLogError, "I2NP: 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] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG) // 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");
}
static void HandleTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len, bool isShort)
@@ -603,11 +515,6 @@ namespace i2p
static void HandleShortTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len)
{
if (!i2p::context.IsECIES ())
{
LogPrint (eLogWarning, "I2NP: ShortTunnelBuild can be handled by ECIES router only");
return;
}
int num = buf[0];
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
@@ -640,8 +547,8 @@ namespace i2p
{
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))
{
if (!i2p::context.DecryptTunnelShortRequestRecord (record + SHORT_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
{
LogPrint (eLogWarning, "I2NP: Can't decrypt short request record ", i);
return;
}
@@ -649,19 +556,19 @@ namespace i2p
{
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];
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);
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);
@@ -673,7 +580,7 @@ namespace i2p
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),
@@ -684,46 +591,46 @@ namespace i2p
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,
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;
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 (),
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);
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)));
}
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
}
else
{
// IBGW is local
@@ -733,18 +640,18 @@ namespace i2p
tunnel->SendTunnelDataMsg (replyMsg);
else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
}
}
else
}
}
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 (false);
@@ -778,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;
}
@@ -809,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;
@@ -824,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;
@@ -840,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)
@@ -861,13 +768,13 @@ namespace i2p
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size);
break;
break;
case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break;
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size);
break;
@@ -895,13 +802,8 @@ namespace i2p
break;
case eI2NPGarlic:
{
if (msg->from)
{
if (msg->from->GetTunnelPool ())
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
else
LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore");
}
if (msg->from && msg->from->GetTunnelPool ())
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
else
i2p::context.ProcessGarlicMessage (msg);
break;
@@ -924,8 +826,8 @@ namespace i2p
case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply:
case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply:
// forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
@@ -940,7 +842,7 @@ namespace i2p
Flush ();
}
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage>&& msg)
{
if (msg)
{

View File

@@ -56,32 +56,11 @@ namespace i2p
// TunnelBuild
const size_t TUNNEL_BUILD_RECORD_SIZE = 528;
const size_t SHORT_TUNNEL_BUILD_RECORD_SIZE = 218;
//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;
// 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;
@@ -119,7 +98,7 @@ namespace i2p
// ShortResponseRecord
const size_t SHORT_RESPONSE_RECORD_OPTIONS_OFFSET = 0;
const size_t SHORT_RESPONSE_RECORD_RET_OFFSET = 201;
enum I2NPMessageType
{
eI2NPDummyMsg = 0,
@@ -171,7 +150,7 @@ namespace tunnel
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
// header accessors
uint8_t * GetHeader () { return GetBuffer (); };
@@ -294,9 +273,9 @@ 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 uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
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);
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel = nullptr);
@@ -322,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;
@@ -63,7 +64,7 @@ namespace data
{
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
{
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
break;
@@ -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);
@@ -796,7 +788,7 @@ namespace data
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
// recreate signer
keys.m_Signer = nullptr;

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:
@@ -119,7 +120,7 @@ namespace data
CryptoKeyType GetCryptoKeyType () const;
void DropVerifier () const; // to save memory
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
void RecalculateIdentHash(uint8_t * buff=nullptr);
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
@@ -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
@@ -221,8 +222,8 @@ namespace data
RoutingDestination () {};
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 std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
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 (); };

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,7 +61,7 @@ namespace data
size_t size = m_Identity->GetFullLen ();
if (size > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", m_BufferLen);
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
@@ -77,23 +77,23 @@ namespace data
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
}
uint8_t num = m_Buffer[size];
size++; // num
LogPrint (eLogDebug, "LeaseSet: read num=", (int)num);
LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num);
if (!num || num > MAX_NUM_LEASES)
{
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num);
LogPrint (eLogError, "LeaseSet: Rncorrect number of leases", (int)num);
m_IsValid = false;
return;
}
if (size + num*LEASE_SIZE > m_BufferLen)
{
if (size + num*LEASE_SIZE > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
}
UpdateLeasesBegin ();
// process leases
m_ExpirationTime = 0;
@@ -112,7 +112,7 @@ namespace data
}
if (!m_ExpirationTime)
{
LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped");
LogPrint (eLogWarning, "LeaseSet: All leases are expired. Dropped");
m_IsValid = false;
return;
}
@@ -121,16 +121,16 @@ namespace data
// verify
if (verifySignature)
{
{
auto signedSize = leases - m_Buffer;
if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen);
m_IsValid = false;
}
}
else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
{
LogPrint (eLogWarning, "LeaseSet: verification failed");
LogPrint (eLogWarning, "LeaseSet: Verification failed");
m_IsValid = false;
}
}
@@ -254,12 +254,12 @@ namespace data
return ts > m_ExpirationTime;
}
void LeaseSet::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
void LeaseSet::Encrypt (const uint8_t * data, uint8_t * encrypted) const
{
if (!m_EncryptionKey) return;
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
if (encryptor)
encryptor->Encrypt (data, encrypted, ctx, true);
encryptor->Encrypt (data, encrypted);
}
void LeaseSet::SetBuffer (const uint8_t * buf, size_t len)
@@ -274,7 +274,7 @@ namespace data
{
if (len <= m_BufferLen) m_BufferLen = len;
else
LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
LogPrint (eLogError, "LeaseSet2: Actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
}
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
@@ -331,7 +331,7 @@ namespace data
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
if (!m_TransientVerifier)
{
LogPrint (eLogError, "LeaseSet2: offline signature failed");
LogPrint (eLogError, "LeaseSet2: Offline signature failed");
return;
}
}
@@ -378,7 +378,7 @@ namespace data
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
const_cast<uint8_t *>(buf)[-1] = c;
if (!verified)
LogPrint (eLogWarning, "LeaseSet2: verification failed");
LogPrint (eLogWarning, "LeaseSet2: Verification failed");
return verified;
}
@@ -489,7 +489,7 @@ namespace data
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
if (!m_TransientVerifier)
{
LogPrint (eLogError, "LeaseSet2: offline signature failed");
LogPrint (eLogError, "LeaseSet2: Offline signature failed");
return;
}
}
@@ -515,7 +515,7 @@ namespace data
key->GetBlindedKey (date, blinded.data ());
if (memcmp (blindedPublicKey, blinded.data (), blindedKeyLen))
{
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match");
LogPrint (eLogError, "LeaseSet2: Blinded public key doesn't match");
return;
}
}
@@ -569,7 +569,7 @@ namespace data
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
}
else
LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
LogPrint (eLogError, "LeaseSet2: Unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
}
else
{
@@ -582,7 +582,7 @@ namespace data
// helper for ExtractClientAuthData
static inline bool GetAuthCookie (const uint8_t * authClients, int numClients, const uint8_t * okm, uint8_t * authCookie)
{
// try to find clientCookie_i for clientID_i = okm[44:51]
// try to find clientCookie_i for clientID_i = okm[44:51]
for (int i = 0; i < numClients; i++)
{
if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i
@@ -606,7 +606,7 @@ namespace data
{
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
if (offset > len)
{
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
@@ -632,7 +632,7 @@ namespace data
{
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
if (offset > len)
{
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
@@ -653,16 +653,16 @@ namespace data
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
}
else
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag);
LogPrint (eLogError, "LeaseSet2: Unknown client auth type ", (int)flag);
}
return offset - 1;
}
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted) const
{
auto encryptor = m_Encryptor; // TODO: atomic
if (encryptor)
encryptor->Encrypt (data, encrypted, ctx, true);
encryptor->Encrypt (data, encrypted);
}
uint64_t LeaseSet2::ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const
@@ -737,7 +737,7 @@ namespace data
htobe64buf (m_Buffer + offset, ts);
offset += 8; // end date
}
// we don't sign it yet. must be signed later on
// we don't sign it yet. must be signed later on
}
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
@@ -768,7 +768,7 @@ namespace data
size_t size = ident.GetFullLen ();
if (size > sz)
{
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz);
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", sz);
return false;
}
// encryption key
@@ -779,7 +779,7 @@ namespace data
++size;
if (!numLeases || numLeases > MAX_NUM_LEASES)
{
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases);
LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)numLeases);
return false;
}
const uint8_t * leases = ptr + size;
@@ -863,17 +863,17 @@ namespace data
}
// update expiration
if (expirationTime)
{
{
SetExpirationTime (expirationTime*1000LL);
auto expires = (int)expirationTime - timestamp;
htobe16buf (expiresBuf, expires > 0 ? expires : 0);
}
}
else
{
// no tunnels or withdraw
SetExpirationTime (timestamp*1000LL);
memset (expiresBuf, 0, 2); // expires immeditely
}
}
// sign
keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type
}
@@ -912,6 +912,11 @@ namespace data
uint8_t blindedPriv[64], blindedPub[128]; // 64 and 128 max
size_t publicKeyLen = blindedKey.BlindPrivateKey (keys.GetSigningPrivateKey (), date, blindedPriv, blindedPub);
std::unique_ptr<i2p::crypto::Signer> blindedSigner (i2p::data::PrivateKeys::CreateSigner (blindedKey.GetBlindedSigType (), blindedPriv));
if (!blindedSigner)
{
LogPrint (eLogError, "LeaseSet2: Can't create blinded signer for signature type ", blindedKey.GetSigType ());
return;
}
auto offset = 1;
htobe16buf (m_Buffer + offset, blindedKey.GetBlindedSigType ()); offset += 2; // Blinded Public Key Sig Type
memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key
@@ -979,7 +984,7 @@ namespace data
m_StoreHash = blindedKey->GetStoreHash ();
}
else
LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer");
LogPrint (eLogError, "LeaseSet2: Couldn't extract inner layer");
}
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const
@@ -990,7 +995,7 @@ namespace data
ek.GenerateKeys (); // esk and epk
memcpy (authData, ek.GetPublicKey (), 32); authData += 32; // epk
htobe16buf (authData, authKeys->size ()); authData += 2; // num clients
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
memcpy (authInput + 64, subcredential, 36);
for (auto& it: *authKeys)
{

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
*
@@ -93,7 +93,7 @@ namespace data
// implements RoutingDestination
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
void Encrypt (const uint8_t * data, uint8_t * encrypted) const;
bool IsDestination () const { return true; };
protected:
@@ -128,8 +128,8 @@ namespace data
};
/**
validate lease set buffer signature and extract expiration timestamp
@returns true if the leaseset is well formed and signature is valid
* validate lease set buffer signature and extract expiration timestamp
* @returns true if the leaseset is well formed and signature is valid
*/
bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires);
@@ -156,7 +156,7 @@ namespace data
bool IsNewer (const uint8_t * buf, size_t len) const;
// implements RoutingDestination
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
void Encrypt (const uint8_t * data, uint8_t * encrypted) const;
CryptoKeyType GetEncryptionType () const { return m_EncryptionType; };
private:

View File

@@ -46,7 +46,7 @@ namespace log {
#ifndef _WIN32
/**
* @brief Maps our log levels to syslog one
* @brief Maps our log levels to syslog one
* @return syslog priority LOG_*, as defined in syslog.h
*/
static inline int GetSyslogPrio (enum LogLevel l) {
@@ -113,11 +113,11 @@ namespace log {
std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct
);
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct
);
return s;
}
@@ -129,10 +129,10 @@ namespace log {
else if (level == "info") { m_MinLevel = eLogInfo; }
else if (level == "debug") { m_MinLevel = eLogDebug; }
else {
LogPrint(eLogError, "Log: unknown loglevel: ", level);
LogPrint(eLogError, "Log: Unknown loglevel: ", level);
return;
}
LogPrint(eLogInfo, "Log: min messages level set to ", level);
LogPrint(eLogInfo, "Log: Logging level set to ", level);
}
const char * Log::TimeAsString(std::time_t t) {
@@ -170,7 +170,7 @@ namespace log {
break;
case eLogStdout:
default:
std::cout << TimeAsString(msg->timestamp)
std::cout << TimeAsString(msg->timestamp)
<< "@" << short_tid
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
<< " - " << msg->text << std::endl;
@@ -212,7 +212,7 @@ namespace log {
m_LogStream = os;
return;
}
LogPrint(eLogError, "Log: can't open file ", path);
LogPrint(eLogError, "Log: Can't open file ", path);
}
void Log::SendTo (std::shared_ptr<std::ostream> os) {

View File

@@ -52,7 +52,7 @@ namespace log {
{
private:
enum LogType m_Destination;
enum LogType m_Destination;
enum LogLevel m_MinLevel;
std::shared_ptr<std::ostream> m_LogStream;
std::string m_Logfile;
@@ -75,7 +75,7 @@ namespace log {
/**
* @brief Makes formatted string from unix timestamp
* @param ts Second since epoch
* @param ts Second since epoch
*
* This function internally caches the result for last provided value
*/
@@ -86,52 +86,52 @@ namespace log {
Log ();
~Log ();
LogType GetLogType () { return m_Destination; };
LogType GetLogType () { return m_Destination; };
LogLevel GetLogLevel () { return m_MinLevel; };
void Start ();
void Stop ();
/**
* @brief Sets minimal allowed level for log messages
* @param level String with wanted minimal msg level
* @brief Sets minimal allowed level for log messages
* @param level String with wanted minimal msg level
*/
void SetLogLevel (const std::string& level);
void SetLogLevel (const std::string& level);
/**
* @brief Sets log destination to logfile
* @param path Path to logfile
* @param path Path to logfile
*/
void SendTo (const std::string &path);
/**
* @brief Sets log destination to given output stream
* @param os Output stream
* @param os Output stream
*/
void SendTo (std::shared_ptr<std::ostream> os);
/**
* @brief Sets format for timestamps in log
* @param format String with timestamp format
* @brief Sets format for timestamps in log
* @param format String with timestamp format
*/
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
#ifndef _WIN32
/**
* @brief Sets log destination to syslog
* @param name Wanted program name
* @param name Wanted program name
* @param facility Wanted log category
*/
void SendTo (const char *name, int facility);
#endif
/**
* @brief Format log message and write to output stream/syslog
* @param msg Pointer to processed message
* @brief Format log message and write to output stream/syslog
* @param msg Pointer to processed message
*/
void Append(std::shared_ptr<i2p::log::LogMsg> &);
/** @brief Reopen log file */
/** @brief Reopen log file */
void Reopen();
};
@@ -144,8 +144,8 @@ namespace log {
*/
struct LogMsg {
std::time_t timestamp;
std::string text; /**< message text as single string */
LogLevel level; /**< message level */
std::string text; /**< message text as single string */
LogLevel level; /**< message level */
std::thread::id tid; /**< id of thread that generated message */
LogMsg (LogLevel lvl, std::time_t ts, std::string&& txt): timestamp(ts), text(std::move(txt)), level(lvl) {}
@@ -153,7 +153,7 @@ namespace log {
Log & Logger();
typedef std::function<void (const std::string&)> ThrowFunction;
typedef std::function<void (const std::string&)> ThrowFunction;
ThrowFunction GetThrowFunction ();
void SetThrowFunction (ThrowFunction f);
} // log

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
*
@@ -23,7 +23,7 @@
#include "HTTP.h"
#include "util.h"
#ifdef __linux__
#if defined(__linux__) && !defined(_NETINET_IN_H)
#include <linux/in6.h>
#endif
@@ -32,14 +32,12 @@ namespace i2p
namespace transport
{
NTCP2Establisher::NTCP2Establisher ():
m_SessionRequestBuffer (nullptr), m_SessionCreatedBuffer (nullptr), m_SessionConfirmedBuffer (nullptr)
m_SessionConfirmedBuffer (nullptr)
{
}
NTCP2Establisher::~NTCP2Establisher ()
{
delete[] m_SessionRequestBuffer;
delete[] m_SessionCreatedBuffer;
delete[] m_SessionConfirmedBuffer;
}
@@ -61,14 +59,14 @@ namespace transport
void NTCP2Establisher::KDF1Bob ()
{
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
}
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
{
MixHash (sessionRequest + 32, 32); // encrypted payload
int paddingLength = sessionRequestLen - 64;
int paddingLength = sessionRequestLen - 64;
if (paddingLength > 0)
MixHash (sessionRequest + 64, paddingLength);
MixHash (epub, 32);
@@ -93,7 +91,7 @@ namespace transport
void NTCP2Establisher::KDF3Alice ()
{
uint8_t inputKeyMaterial[32];
i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
i2p::context.GetNTCP2StaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
MixKey (inputKeyMaterial);
}
@@ -112,9 +110,8 @@ namespace transport
void NTCP2Establisher::CreateSessionRequestMessage ()
{
// create buffer and fill padding
auto paddingLength = rand () % (287 - 64); // message length doesn't exceed 287 bytes
auto paddingLength = rand () % (NTCP2_SESSION_REQUEST_MAX_SIZE - 64); // message length doesn't exceed 287 bytes
m_SessionRequestBufferLen = paddingLength + 64;
m_SessionRequestBuffer = new uint8_t[m_SessionRequestBufferLen];
RAND_bytes (m_SessionRequestBuffer + 64, paddingLength);
// encrypt X
i2p::crypto::CBCEncryption encryption;
@@ -133,7 +130,7 @@ namespace transport
// m3p2Len
auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen ();
m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options
htobe16buf (options + 4, m3p2Len);
htobe16buf (options + 4, m3p2Len);
// fill m3p2 payload (RouterInfo block)
m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
@@ -152,9 +149,8 @@ namespace transport
void NTCP2Establisher::CreateSessionCreatedMessage ()
{
auto paddingLen = rand () % (287 - 64);
auto paddingLen = rand () % (NTCP2_SESSION_CREATED_MAX_SIZE - 64);
m_SessionCreatedBufferLen = paddingLen + 64;
m_SessionCreatedBuffer = new uint8_t[m_SessionCreatedBufferLen];
RAND_bytes (m_SessionCreatedBuffer + 64, paddingLen);
// encrypt Y
i2p::crypto::CBCEncryption encryption;
@@ -199,8 +195,9 @@ namespace transport
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
}
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen)
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew)
{
clockSkew = false;
// decrypt X
i2p::crypto::CBCDecryption decryption;
decryption.SetKey (i2p::context.GetIdentHash ());
@@ -236,7 +233,8 @@ namespace transport
if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW)
{
LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew");
return false;
clockSkew = true;
// we send SessionCreate to let Alice know our time and then close session
}
}
else
@@ -322,26 +320,27 @@ namespace transport
}
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
m_Server (server), m_Socket (m_Server.GetService ()),
m_IsEstablished (false), m_IsTerminated (false),
m_Establisher (new NTCP2Establisher),
m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr),
#if OPENSSL_SIPHASH
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
#else
m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr),
#endif
m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr),
m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), m_IsSending (false),
m_NextPaddingSize (16)
m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0),
m_IsSending (false), m_IsReceiving (false), m_NextPaddingSize (16)
{
if (in_RemoteRouter) // Alice
{
m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash ();
if (addr)
{
memcpy (m_Establisher->m_RemoteStaticKey, addr->ntcp2->staticKey, 32);
memcpy (m_Establisher->m_IV, addr->ntcp2->iv, 16);
memcpy (m_Establisher->m_RemoteStaticKey, addr->s, 32);
memcpy (m_Establisher->m_IV, addr->i, 16);
m_RemoteEndpoint = boost::asio::ip::tcp::endpoint (addr->host, addr->port);
}
else
@@ -356,8 +355,6 @@ namespace transport
delete[] m_NextReceivedBuffer;
delete[] m_NextSendBuffer;
#if OPENSSL_SIPHASH
if (m_SendSipKey) EVP_PKEY_free (m_SendSipKey);
if (m_ReceiveSipKey) EVP_PKEY_free (m_ReceiveSipKey);
if (m_SendMDCtx) EVP_MD_CTX_destroy (m_SendMDCtx);
if (m_ReceiveMDCtx) EVP_MD_CTX_destroy (m_ReceiveMDCtx);
#endif
@@ -377,7 +374,7 @@ namespace transport
transports.PeerDisconnected (shared_from_this ());
m_Server.RemoveNTCP2Session (shared_from_this ());
m_SendQueue.clear ();
LogPrint (eLogDebug, "NTCP2: session terminated");
LogPrint (eLogDebug, "NTCP2: Session terminated");
}
}
@@ -405,6 +402,29 @@ namespace transport
htole64buf (nonce + 4, seqn);
}
void NTCP2Session::CreateNextReceivedBuffer (size_t size)
{
if (m_NextReceivedBuffer)
{
if (size <= m_NextReceivedBufferSize)
return; // buffer is good, do nothing
else
delete[] m_NextReceivedBuffer;
}
m_NextReceivedBuffer = new uint8_t[size];
m_NextReceivedBufferSize = size;
}
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
{
if (m_NextReceivedBuffer && !m_IsReceiving &&
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
{
delete[] m_NextReceivedBuffer;
m_NextReceivedBuffer = nullptr;
m_NextReceivedBufferSize = 0;
}
}
void NTCP2Session::KeyDerivationFunctionDataPhase ()
{
@@ -435,12 +455,11 @@ namespace transport
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogWarning, "NTCP2: couldn't send SessionRequest message: ", ecode.message ());
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionRequest message: ", ecode.message ());
Terminate ();
}
else
{
m_Establisher->m_SessionCreatedBuffer = new uint8_t[287]; // TODO: determine actual max size
// we receive first 64 bytes (32 Y, and 32 ChaCha/Poly frame) first
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionCreatedBuffer, 64), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionCreatedReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
@@ -459,18 +478,25 @@ namespace transport
{
LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred);
uint16_t paddingLen = 0;
if (m_Establisher->ProcessSessionRequestMessage (paddingLen))
bool clockSkew = false;
if (m_Establisher->ProcessSessionRequestMessage (paddingLen, clockSkew))
{
if (paddingLen > 0)
if (clockSkew)
{
if (paddingLen <= 287 - 64) // session request is 287 bytes max
// we don't care about padding, send SessionCreated and close session
SendSessionCreated ();
m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ()));
}
else if (paddingLen > 0)
{
if (paddingLen <= NTCP2_SESSION_REQUEST_MAX_SIZE - 64) // session request is 287 bytes max
{
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
else
{
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
Terminate ();
}
}
@@ -516,14 +542,14 @@ namespace transport
{
if (paddingLen > 0)
{
if (paddingLen <= 287 - 64) // session created is 287 bytes max
if (paddingLen <= NTCP2_SESSION_CREATED_MAX_SIZE - 64) // session created is 287 bytes max
{
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionCreatedBuffer + 64, paddingLen), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionCreatedPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
else
{
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
Terminate ();
}
}
@@ -566,7 +592,7 @@ namespace transport
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogWarning, "NTCP2: couldn't send SessionConfirmed message: ", ecode.message ());
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionConfirmed message: ", ecode.message ());
Terminate ();
}
else
@@ -593,7 +619,7 @@ namespace transport
(void) bytes_transferred;
if (ecode)
{
LogPrint (eLogWarning, "NTCP2: couldn't send SessionCreated message: ", ecode.message ());
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionCreated message: ", ecode.message ());
Terminate ();
}
else
@@ -636,7 +662,7 @@ namespace transport
// process RI
if (buf[0] != eNTCP2BlkRouterInfo)
{
LogPrint (eLogWarning, "NTCP2: unexpected block ", (int)buf[0], " in SessionConfirmed");
LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed");
Terminate ();
return;
}
@@ -664,7 +690,7 @@ namespace transport
auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey);
if (!addr)
{
LogPrint (eLogError, "NTCP2: No NTCP2 address wth static key found in SessionConfirmed");
LogPrint (eLogError, "NTCP2: No NTCP2 address with static key found in SessionConfirmed");
Terminate ();
return;
}
@@ -693,17 +719,19 @@ namespace transport
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
{
#if OPENSSL_SIPHASH
m_SendSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16);
EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16);
m_SendMDCtx = EVP_MD_CTX_create ();
EVP_PKEY_CTX *ctx = nullptr;
EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, m_SendSipKey);
EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, sipKey);
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
EVP_PKEY_free (sipKey);
m_ReceiveSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16);
sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16);
m_ReceiveMDCtx = EVP_MD_CTX_create ();
ctx = nullptr;
EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, m_ReceiveSipKey);
EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, sipKey);
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
EVP_PKEY_free (sipKey);
#else
m_SendSipKey = sendSipKey;
m_ReceiveSipKey = receiveSipKey;
@@ -719,7 +747,6 @@ namespace transport
void NTCP2Session::ServerLogin ()
{
m_Establisher->CreateEphemeralKey ();
m_Establisher->m_SessionRequestBuffer = new uint8_t[287]; // 287 bytes max for now
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
@@ -730,7 +757,7 @@ namespace transport
if (IsTerminated ()) return;
#ifdef __linux__
const int one = 1;
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
@@ -741,7 +768,7 @@ namespace transport
if (ecode)
{
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogWarning, "NTCP2: receive length read error: ", ecode.message ());
LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ());
Terminate ();
}
else
@@ -756,11 +783,10 @@ namespace transport
#endif
// m_NextReceivedLen comes from the network in BigEndian
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
LogPrint (eLogDebug, "NTCP2: Received length ", m_NextReceivedLen);
if (m_NextReceivedLen >= 16)
{
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
CreateNextReceivedBuffer (m_NextReceivedLen);
boost::system::error_code ec;
size_t moreBytes = m_Socket.available(ec);
if (!ec && moreBytes >= m_NextReceivedLen)
@@ -774,7 +800,7 @@ namespace transport
}
else
{
LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short");
LogPrint (eLogError, "NTCP2: Received length ", m_NextReceivedLen, " is too short");
Terminate ();
}
}
@@ -787,6 +813,7 @@ namespace transport
const int one = 1;
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
#endif
m_IsReceiving = true;
boost::asio::async_read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (),
std::bind(&NTCP2Session::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
}
@@ -796,7 +823,7 @@ namespace transport
if (ecode)
{
if (ecode != boost::asio::error::operation_aborted)
LogPrint (eLogWarning, "NTCP2: receive read error: ", ecode.message ());
LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ());
Terminate ();
}
else
@@ -808,9 +835,9 @@ namespace transport
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
{
LogPrint (eLogDebug, "NTCP2: received message decrypted");
LogPrint (eLogDebug, "NTCP2: Received message decrypted");
ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16);
delete[] m_NextReceivedBuffer; m_NextReceivedBuffer = nullptr; // we don't need received buffer anymore
m_IsReceiving = false;
ReceiveLength ();
}
else
@@ -839,10 +866,10 @@ namespace transport
switch (blk)
{
case eNTCP2BlkDateTime:
LogPrint (eLogDebug, "NTCP2: datetime");
LogPrint (eLogDebug, "NTCP2: Datetime");
break;
case eNTCP2BlkOptions:
LogPrint (eLogDebug, "NTCP2: options");
LogPrint (eLogDebug, "NTCP2: Options");
break;
case eNTCP2BlkRouterInfo:
{
@@ -858,25 +885,29 @@ namespace transport
LogPrint (eLogError, "NTCP2: I2NP block is too long ", size);
break;
}
auto nextMsg = NewI2NPMessage (size);
nextMsg->Align (12); // for possible tunnel msg
auto nextMsg = (frame[offset] == eI2NPTunnelData) ? NewI2NPTunnelMessage (true) : NewI2NPMessage (size);
nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
nextMsg->FromNTCP2 ();
m_Handler.PutNextMessage (nextMsg);
if (nextMsg->len <= nextMsg->maxLen)
{
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
nextMsg->FromNTCP2 ();
m_Handler.PutNextMessage (std::move (nextMsg));
}
else
LogPrint (eLogError, "NTCP2: I2NP block is too long for I2NP message");
break;
}
case eNTCP2BlkTermination:
if (size >= 9)
{
LogPrint (eLogDebug, "NTCP2: termination. reason=", (int)(frame[offset + 8]));
LogPrint (eLogDebug, "NTCP2: Termination. reason=", (int)(frame[offset + 8]));
Terminate ();
}
else
LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size);
break;
case eNTCP2BlkPadding:
LogPrint (eLogDebug, "NTCP2: padding");
LogPrint (eLogDebug, "NTCP2: Padding");
break;
default:
LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk);
@@ -888,7 +919,7 @@ namespace transport
void NTCP2Session::SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf)
{
#if OPENSSL_SIPHASH
#if OPENSSL_SIPHASH
EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr);
EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8);
size_t l = 8;
@@ -898,7 +929,7 @@ namespace transport
#endif
// length must be in BigEndian
htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key));
LogPrint (eLogDebug, "NTCP2: sent length ", frameLen);
LogPrint (eLogDebug, "NTCP2: Sent length ", frameLen);
}
void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs)
@@ -951,7 +982,7 @@ namespace transport
{
// allocate send buffer
m_NextSendBuffer = new uint8_t[287]; // can be any size > 16, we just allocate 287 frequently
// crate padding block
// create padding block
auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16);
// and padding block to encrypt and send
if (paddingLen)
@@ -1059,15 +1090,15 @@ namespace transport
size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100;
if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3;
if (paddingSize > len) paddingSize = len;
if (paddingSize)
if (paddingSize)
{
if (m_NextPaddingSize >= 16)
{
RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes));
m_NextPaddingSize = 0;
}
}
paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize;
}
}
buf[0] = eNTCP2BlkPadding; // blk
htobe16buf (buf + 1, paddingSize); // size
memset (buf + 3, 0, paddingSize);
@@ -1093,7 +1124,13 @@ namespace transport
void NTCP2Session::SendTermination (NTCP2TerminationReason reason)
{
if (!m_SendKey || !m_SendSipKey) return;
if (!m_SendKey ||
#if OPENSSL_SIPHASH
!m_SendMDCtx
#else
!m_SendSipKey
#endif
) return;
m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block
// termination block
m_NextSendBuffer[2] = eNTCP2BlkTermination;
@@ -1126,8 +1163,8 @@ namespace transport
SendQueue ();
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
{
LogPrint (eLogWarning, "NTCP2: outgoing messages queue size to ",
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ",
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate ();
}
}
@@ -1140,7 +1177,7 @@ namespace transport
NTCP2Server::NTCP2Server ():
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
m_ProxyType(eNoProxy), m_Resolver(GetService ())
m_ProxyType(eNoProxy), m_Resolver(GetService ())
{
}
@@ -1206,7 +1243,7 @@ namespace transport
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
#ifdef __linux__
#if defined(__linux__) && !defined(_NETINET_IN_H)
if (!m_Address6 && !m_YggdrasilAddress) // only if not binded to address
{
// Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others
@@ -1232,7 +1269,7 @@ namespace transport
}
catch ( std::exception & ex )
{
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
LogPrint(eLogError, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what());
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
continue;
}
@@ -1273,7 +1310,7 @@ namespace transport
auto it = m_NTCP2Sessions.find (ident);
if (it != m_NTCP2Sessions.end ())
{
LogPrint (eLogWarning, "NTCP2: session to ", ident.ToBase64 (), " already exists");
LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists");
if (incoming)
// replace by new session
it->second->Terminate ();
@@ -1342,7 +1379,7 @@ namespace transport
boost::system::error_code ec;
conn->GetSocket ().bind (*localAddress, ec);
if (ec)
LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
LogPrint (eLogError, "NTCP2: Can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
}
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
}
@@ -1448,6 +1485,8 @@ namespace transport
LogPrint (eLogDebug, "NTCP2: No activity for ", session->GetTerminationTimeout (), " seconds");
session->TerminateByTimeout (); // it doesn't change m_NTCP2Session right a way
}
else
it.second->DeleteNextReceiveBuffer (ts);
// pending
for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();)
{
@@ -1509,7 +1548,7 @@ namespace transport
{
if (ecode)
{
LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message());
LogPrint(eLogWarning, "NTCP2: Failed to connect to proxy ", ecode.message());
timer->cancel();
conn->Terminate();
return;
@@ -1526,7 +1565,7 @@ namespace transport
(void) transferred;
if(ec)
{
LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message());
LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message());
}
});
auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
@@ -1535,7 +1574,7 @@ namespace transport
{
if(ec)
{
LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message());
LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message());
timer->cancel();
conn->Terminate();
return;
@@ -1549,14 +1588,14 @@ namespace transport
}
else if ((*readbuff)[1] == 0xff)
{
LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication");
LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication");
timer->cancel();
conn->Terminate();
return;
}
LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]);
}
LogPrint(eLogError, "NTCP2: socks5 server gave invalid response");
LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response");
timer->cancel();
conn->Terminate();
});
@@ -1584,7 +1623,7 @@ namespace transport
{
(void) transferred;
if(ec)
LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message());
LogPrint(eLogError, "NTCP2: HTTP proxy write error ", ec.message());
});
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
@@ -1593,7 +1632,7 @@ namespace transport
{
if(ec)
{
LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message());
LogPrint(eLogError, "NTCP2: HTTP proxy read error ", ec.message());
timer->cancel();
conn->Terminate();
}
@@ -1611,10 +1650,10 @@ namespace transport
return;
}
else
LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code);
LogPrint(eLogError, "NTCP2: HTTP proxy rejected request ", res.code);
}
else
LogPrint(eLogError, "NTCP2: http proxy gave malformed response");
LogPrint(eLogError, "NTCP2: HTTP proxy gave malformed response");
timer->cancel();
conn->Terminate();
delete readbuff;
@@ -1623,7 +1662,7 @@ namespace transport
break;
}
default:
LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state");
LogPrint(eLogError, "NTCP2: Unknown proxy type, invalid state");
}
}
@@ -1664,7 +1703,7 @@ namespace transport
{
if(ec)
{
LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message());
LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message());
return;
}
});
@@ -1674,7 +1713,7 @@ namespace transport
{
if(e)
{
LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message());
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
}
else if(transferred == sz)
{

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
*
@@ -28,12 +28,15 @@ namespace transport
{
const size_t NTCP2_UNENCRYPTED_FRAME_MAX_SIZE = 65519;
const size_t NTCP2_SESSION_REQUEST_MAX_SIZE = 287;
const size_t NTCP2_SESSION_CREATED_MAX_SIZE = 287;
const int NTCP2_MAX_PADDING_RATIO = 6; // in %
const int NTCP2_CONNECT_TIMEOUT = 5; // 5 seconds
const int NTCP2_ESTABLISH_TIMEOUT = 10; // 10 seconds
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
const int NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT = 3; // 3 seconds
const int NTCP2_ROUTERINFO_RESEND_INTERVAL = 25*60; // 25 minuntes in seconds
const int NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD = 25*60; // 25 minuntes
@@ -104,7 +107,7 @@ namespace transport
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
@@ -115,7 +118,8 @@ namespace transport
i2p::data::IdentHash m_RemoteIdentHash;
uint16_t m3p2Len;
uint8_t * m_SessionRequestBuffer, * m_SessionCreatedBuffer, * m_SessionConfirmedBuffer;
uint8_t m_SessionRequestBuffer[NTCP2_SESSION_REQUEST_MAX_SIZE],
m_SessionCreatedBuffer[NTCP2_SESSION_CREATED_MAX_SIZE], * m_SessionConfirmedBuffer;
size_t m_SessionRequestBufferLen, m_SessionCreatedBufferLen;
};
@@ -132,6 +136,7 @@ namespace transport
void TerminateByTimeout ();
void Done ();
void Close () { m_Socket.close (); }; // for accept
void DeleteNextReceiveBuffer (uint64_t ts);
boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; };
const boost::asio::ip::tcp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
@@ -151,6 +156,7 @@ namespace transport
void Established ();
void CreateNonce (uint64_t seqn, uint8_t * nonce);
void CreateNextReceivedBuffer (size_t size);
void KeyDerivationFunctionDataPhase ();
void SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey);
@@ -199,13 +205,13 @@ namespace transport
uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32];
const uint8_t * m_SendKey, * m_ReceiveKey;
#if OPENSSL_SIPHASH
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
#else
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
#endif
uint16_t m_NextReceivedLen;
uint8_t * m_NextReceivedBuffer, * m_NextSendBuffer;
size_t m_NextReceivedBufferSize;
union
{
uint8_t buf[8];
@@ -215,12 +221,12 @@ namespace transport
i2p::I2NPMessagesHandler m_Handler;
bool m_IsSending;
bool m_IsSending, m_IsReceiving;
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
uint64_t m_NextRouterInfoResendTime; // seconds since epoch
uint16_t m_PaddingSizes[16];
int m_NextPaddingSize;
int m_NextPaddingSize;
};
class NTCP2Server: private i2p::util::RunnableServiceWithWork
@@ -252,7 +258,7 @@ namespace transport
void UseProxy(ProxyType proxy, const std::string& address, uint16_t port, const std::string& user, const std::string& pass);
void SetLocalAddress (const boost::asio::ip::address& localAddress);
private:
void HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error);
@@ -261,7 +267,7 @@ namespace transport
void HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
void HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
void AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer);
// timer
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
@@ -279,7 +285,7 @@ namespace transport
boost::asio::ip::tcp::resolver m_Resolver;
std::unique_ptr<boost::asio::ip::tcp::endpoint> m_ProxyEndpoint;
std::shared_ptr<boost::asio::ip::tcp::endpoint> m_Address4, m_Address6, m_YggdrasilAddress;
public:
// for HTTP/I2PControl

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -55,8 +55,10 @@ namespace data
Load ();
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
if (m_RouterInfos.size () < threshold || m_Floodfills.size () < NETDB_MIN_FLOODFILLS) // reseed if # of router less than threshold or too few floodfiils
{
Reseed ();
}
else if (!GetRandomRouter (i2p::context.GetSharedRouterInfo (), false))
Reseed (); // we don't have a router we can connect to. Trying to reseed
@@ -64,14 +66,14 @@ namespace data
if (it != m_RouterInfos.end ())
{
// remove own router
m_RouterInfos.erase (it);
m_Floodfills.remove (it->second);
m_RouterInfos.erase (it);
}
// insert own router
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
if (i2p::context.IsFloodfill ())
m_Floodfills.push_back (i2p::context.GetSharedRouterInfo ());
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
m_IsRunning = true;
@@ -105,7 +107,10 @@ namespace data
{
i2p::util::SetThreadName("NetDB");
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
int16_t profilesCleanupVariance = 0;
while (m_IsRunning)
{
try
@@ -116,7 +121,7 @@ namespace data
int numMsgs = 0;
while (msg)
{
LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
LogPrint(eLogDebug, "NetDb: Got request with type ", (int) msg->GetTypeID ());
switch (msg->GetTypeID ())
{
case eI2NPDatabaseStore:
@@ -136,7 +141,7 @@ namespace data
HandleNTCP2RouterInfoMsg (msg);
break;
default: // WTF?
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
LogPrint (eLogError, "NetDb: Unexpected message type ", (int) msg->GetTypeID ());
//i2p::HandleI2NPMessage (msg);
}
if (numMsgs > 100) break;
@@ -146,13 +151,14 @@ namespace data
}
if (!m_IsRunning) break;
if (!i2p::transport::transports.IsOnline ()) continue; // don't manage netdb when offline
uint64_t ts = i2p::util::GetSecondsSinceEpoch ();
if (ts - lastManageRequest >= 15) // manage requests every 15 seconds
{
m_Requests.ManageRequests ();
lastManageRequest = ts;
}
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
{
if (lastSave)
@@ -162,14 +168,22 @@ namespace data
}
lastSave = ts;
}
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
i2p::context.CleanupDestination ();
lastDestinationCleanup = ts;
}
// publish
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance))
{
DeleteObsoleteProfiles ();
lastProfilesCleanup = ts;
profilesCleanupVariance = (rand () % (2 * i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE) - i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE);
}
// publish
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
{
bool publish = false;
if (m_PublishReplyToken)
@@ -177,15 +191,15 @@ namespace data
// next publishing attempt
if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true;
}
else if (i2p::context.GetLastUpdateTime () > lastPublish ||
ts - lastPublish >= NETDB_PUBLISH_INTERVAL)
{
else if (i2p::context.GetLastUpdateTime () > lastPublish ||
ts - lastPublish >= NETDB_PUBLISH_INTERVAL)
{
// new publish
m_PublishExcluded.clear ();
if (i2p::context.IsFloodfill ())
m_PublishExcluded.insert (i2p::context.GetIdentHash ()); // do publish to ourselves
publish = true;
}
}
if (publish) // update timestamp and publish
{
i2p::context.UpdateTimestamp (ts);
@@ -193,6 +207,7 @@ namespace data
lastPublish = ts;
}
}
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
{
auto numRouters = m_RouterInfos.size ();
@@ -214,7 +229,7 @@ namespace data
}
catch (std::exception& ex)
{
LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
LogPrint (eLogError, "NetDb: Runtime exception: ", ex.what ());
}
}
}
@@ -288,7 +303,7 @@ namespace data
if (inserted)
{
LogPrint (eLogInfo, "NetDb: RouterInfo added: ", ident.ToBase64());
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
{
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
m_Floodfills.push_back (r);
@@ -341,7 +356,7 @@ namespace data
updated = true;
}
else
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32());
LogPrint (eLogError, "NetDb: New LeaseSet validation failed: ", ident.ToBase32());
}
return updated;
}
@@ -371,7 +386,7 @@ namespace data
}
}
else
LogPrint (eLogError, "NetDb: new LeaseSet2 validation failed: ", ident.ToBase32());
LogPrint (eLogError, "NetDb: New LeaseSet2 validation failed: ", ident.ToBase32());
return false;
}
@@ -428,7 +443,7 @@ namespace data
int riLen = ri->GetBufferLen();
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
// bad router info
LogPrint(eLogError, "NetDb: bad router info");
LogPrint(eLogError, "NetDb: Bad router info");
return;
}
m_FloodfillBootstrap = ri;
@@ -443,7 +458,7 @@ namespace data
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
{
LogPrint(eLogInfo, "NetDB: reseeding from floodfill ", ri.GetIdentHashBase64());
LogPrint(eLogInfo, "NetDB: Reseeding from floodfill ", ri.GetIdentHashBase64());
std::vector<std::shared_ptr<i2p::I2NPMessage> > requests;
i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash();
@@ -470,22 +485,22 @@ namespace data
i2p::transport::transports.SendMessages(ih, requests);
}
bool NetDb::LoadRouterInfo (const std::string & path)
bool NetDb::LoadRouterInfo (const std::string& path, uint64_t ts)
{
auto r = std::make_shared<RouterInfo>(path);
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses ())
{
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
{
r->DeleteBuffer ();
r->ClearProperties (); // properties are not used for regular routers
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
{
{
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
m_Floodfills.push_back (r);
}
}
}
else
{
LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid. Delete");
LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid or too old. Delete");
i2p::fs::Remove(path);
}
return true;
@@ -566,19 +581,20 @@ namespace data
m_RouterInfos.clear ();
m_Floodfills.clear ();
m_LastLoad = i2p::util::GetSecondsSinceEpoch();
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
std::vector<std::string> files;
m_Storage.Traverse(files);
for (const auto& path : files)
LoadRouterInfo(path);
LoadRouterInfo (path, ts);
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)");
}
void NetDb::SaveUpdated ()
{
int updatedCount = 0, deletedCount = 0;
int updatedCount = 0, deletedCount = 0, deletedFloodfillsCount = 0;
auto total = m_RouterInfos.size ();
auto totalFloodfills = m_Floodfills.size ();
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
auto uptime = i2p::context.GetUptime ();
@@ -588,24 +604,24 @@ namespace data
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
auto own = i2p::context.GetSharedRouterInfo ();
auto own = i2p::context.GetSharedRouterInfo ();
for (auto& it: m_RouterInfos)
{
if (it.second == own) continue; // skip own
std::string ident = it.second->GetIdentHashBase64();
std::string path = m_Storage.Path(ident);
if (it.second->IsUpdated ())
{
it.second->SaveToFile (path);
it.second->SaveToFile (m_Storage.Path(ident));
it.second->SetUpdated (false);
it.second->SetUnreachable (false);
it.second->DeleteBuffer ();
updatedCount++;
continue;
}
// make router reachable back if too few routers
if (it.second->IsUnreachable () && total - deletedCount < NETDB_MIN_ROUTERS)
it.second->SetUnreachable (false);
// make router reachable back if too few routers or floodfills
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
it.second->SetUnreachable (false);
// find & mark expired routers
if (!it.second->IsReachable () && it.second->IsSSU (false))
{
@@ -618,18 +634,21 @@ namespace data
if (it.second->IsUnreachable ())
{
if (it.second->IsFloodfill ()) deletedFloodfillsCount++;
// delete RI file
m_Storage.Remove(ident);
deletedCount++;
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false;
}
} // m_RouterInfos iteration
m_RouterInfoBuffersPool.CleanUpMt ();
if (updatedCount > 0)
LogPrint (eLogInfo, "NetDb: saved ", updatedCount, " new/updated routers");
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
if (deletedCount > 0)
{
LogPrint (eLogInfo, "NetDb: deleting ", deletedCount, " unreachable routers");
LogPrint (eLogInfo, "NetDb: Deleting ", deletedCount, " unreachable routers");
// clean up RouterInfos table
{
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
@@ -661,7 +680,7 @@ namespace data
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
if (!dest)
{
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already");
LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already");
return;
}
@@ -669,24 +688,24 @@ namespace data
if (floodfill)
{
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
direct = false; // floodfill can't be reached directly
if (direct)
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
else
{
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr;
auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
if (outbound && inbound)
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
else
{
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no tunnels found");
m_Requests.RequestComplete (destination, nullptr);
}
}
}
m_Requests.RequestComplete (destination, nullptr);
}
}
}
else
{
LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found");
@@ -700,10 +719,10 @@ namespace data
auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory
if (!dest)
{
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already");
LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already");
return;
}
LogPrint(eLogInfo, "NetDb: destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64());
LogPrint(eLogInfo, "NetDb: Destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64());
// direct
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
}
@@ -727,7 +746,7 @@ namespace data
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
if (ident.IsZero ())
{
LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped");
LogPrint (eLogDebug, "NetDb: Database store with zero ident, dropped");
return;
}
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
@@ -746,14 +765,14 @@ namespace data
if (outbound)
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
else
LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found");
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
}
offset += 32;
}
// we must send reply back before this check
if (ident == i2p::context.GetIdentHash ())
{
LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped");
LogPrint (eLogDebug, "NetDb: Database store with own RouterInfo received, dropped");
return;
}
size_t payloadOffset = offset;
@@ -766,24 +785,24 @@ namespace data
{
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
{
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32());
LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32());
updated = AddLeaseSet (ident, buf + offset, len - offset);
}
else // all others are considered as LeaseSet2
{
LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
}
}
}
else // RouterInfo
{
LogPrint (eLogDebug, "NetDb: store request: RouterInfo");
LogPrint (eLogDebug, "NetDb: Store request: RouterInfo");
size_t size = bufbe16toh (buf + offset);
offset += 2;
if (size > MAX_RI_BUFFER_SIZE || size > len - offset)
{
LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size);
LogPrint (eLogError, "NetDb: Invalid RouterInfo length ", (int)size);
return;
}
uint8_t uncompressed[MAX_RI_BUFFER_SIZE];
@@ -792,7 +811,7 @@ namespace data
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
else
{
LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize);
LogPrint (eLogInfo, "NetDb: Decompression failed ", uncompressedSize);
return;
}
}
@@ -867,7 +886,7 @@ namespace data
m_Requests.RequestComplete (ident, nullptr);
}
else if(!m_FloodfillBootstrap)
LogPrint (eLogWarning, "NetDb: requested destination for ", key, " not found");
LogPrint (eLogWarning, "NetDb: Requested destination for ", key, " not found");
// try responses
for (int i = 0; i < num; i++)
@@ -882,7 +901,7 @@ namespace data
if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL)
{
// router with ident not found or too old (1 hour)
LogPrint (eLogDebug, "NetDb: found new/outdated router. Requesting RouterInfo ...");
LogPrint (eLogDebug, "NetDb: Found new/outdated router. Requesting RouterInfo...");
if(m_FloodfillBootstrap)
RequestDestinationFrom(router, m_FloodfillBootstrap->GetIdentHash(), true);
else
@@ -923,14 +942,14 @@ namespace data
excluded += 2;
if (numExcluded > 512)
{
LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512");
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " exceeds 512");
return;
}
std::shared_ptr<I2NPMessage> replyMsg;
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
{
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
std::set<IdentHash> excludedRouters;
for (int i = 0; i < numExcluded; i++)
{
@@ -952,13 +971,14 @@ namespace data
else
{
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
{
auto router = FindRouter (ident);
if (router)
{
LogPrint (eLogDebug, "NetDb: requested RouterInfo ", key, " found");
router->LoadBuffer ();
LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found");
if (!router->GetBuffer ())
router->LoadBuffer (m_Storage.Path (router->GetIdentHashBase64 ()));
if (router->GetBuffer ())
replyMsg = CreateDatabaseStoreMsg (router);
}
@@ -971,11 +991,11 @@ namespace data
if (!leaseSet)
{
// no lease set found
LogPrint(eLogDebug, "NetDb: requested LeaseSet not found for ", ident.ToBase32());
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
}
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
{
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found");
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
}
}
@@ -1020,10 +1040,10 @@ namespace data
replyMsg = garlic.WrapSingleMessage (replyMsg);
}
if (!replyMsg)
LogPrint (eLogError, "NetDb: failed to wrap message");
LogPrint (eLogError, "NetDb: Failed to wrap message");
}
else
LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided");
LogPrint(eLogWarning, "NetDb: Encrypted reply requested but no tags provided");
}
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
@@ -1045,8 +1065,8 @@ namespace data
m_PublishExcluded.clear ();
m_PublishReplyToken = 0;
}
}
}
void NetDb::Explore (int numDestinations)
{
// new requests
@@ -1057,14 +1077,14 @@ namespace data
uint8_t randomHash[32];
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ...");
LogPrint (eLogInfo, "NetDb: Exploring new ", numDestinations, " routers ...");
for (int i = 0; i < numDestinations; i++)
{
RAND_bytes (randomHash, 32);
auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory
if (!dest)
{
LogPrint (eLogWarning, "NetDb: exploratory destination is requested already");
LogPrint (eLogWarning, "NetDb: Exploratory destination is requested already");
return;
}
auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ());
@@ -1106,7 +1126,7 @@ namespace data
LogPrint (eLogError, "NetDb: Couldn't publish our RouterInfo to ", NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS, " closest routers. Try again");
m_PublishExcluded.clear ();
}
auto floodfill = GetClosestFloodfill (i2p::context.GetIdentHash (), m_PublishExcluded);
if (floodfill)
{
@@ -1116,19 +1136,19 @@ namespace data
m_PublishExcluded.insert (floodfill->GetIdentHash ());
m_PublishReplyToken = replyToken;
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
// send directly
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
else
{
// otherwise through exploratory
// otherwise through exploratory
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
if (inbound && outbound)
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
}
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
}
}
}
@@ -1168,7 +1188,8 @@ namespace data
{
return !router->IsHidden () && router != compatibleWith &&
(reverse ? compatibleWith->IsReachableFrom (*router) :
router->IsReachableFrom (*compatibleWith));
router->IsReachableFrom (*compatibleWith)) &&
router->IsECIES ();
});
}
@@ -1177,17 +1198,27 @@ namespace data
return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsPeerTesting (v4) &&
!excluded.count (router->GetIdentHash ());
return !router->IsHidden () && router->IsECIES () &&
router->IsPeerTesting (v4) && !excluded.count (router->GetIdentHash ());
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const
{
return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsECIES () &&
router->IsSSU2PeerTesting (v4) && !excluded.count (router->GetIdentHash ());
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
{
return GetRandomRouter (
[](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsSSUV6 ();
return !router->IsHidden () && router->IsECIES () && router->IsSSUV6 ();
});
}
@@ -1196,8 +1227,8 @@ namespace data
return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{
return router->IsIntroducer (v4) && !excluded.count (router->GetIdentHash ()) &&
!router->IsHidden () && !router->IsFloodfill (); // floodfills don't send relay tag
return !router->IsHidden () && router->IsECIES () && !router->IsFloodfill () && // floodfills don't send relay tag
router->IsIntroducer (v4) && !excluded.count (router->GetIdentHash ());
});
}
@@ -1210,11 +1241,8 @@ namespace data
(reverse ? compatibleWith->IsReachableFrom (*router) :
router->IsReachableFrom (*compatibleWith)) &&
(router->GetCaps () & RouterInfo::eHighBandwidth) &&
#if defined(__x86_64__)
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION;
#else
router->GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
#endif
router->GetVersion () >= NETDB_MIN_HIGHBANDWIDTH_VERSION &&
router->IsECIES ();
});
}
@@ -1234,12 +1262,12 @@ namespace data
return it->second;
// try some routers around
auto it1 = m_RouterInfos.begin ();
if (inds[0])
if (inds[0])
{
// before
inds[1] %= inds[0];
inds[1] %= inds[0];
std::advance (it1, (inds[1] + inds[0])/2);
}
}
else
it1 = it;
auto it2 = it;
@@ -1250,14 +1278,14 @@ namespace data
std::advance (it2, inds[2]);
}
// it1 - from, it2 - to
it = it1;
it = it1;
while (it != it2 && it != m_RouterInfos.end ())
{
if (!it->second->IsUnreachable () && filter (it->second))
return it->second;
it++;
}
// still not found, try from the begining
// still not found, try from the beginning
it = m_RouterInfos.begin ();
while (it != it1 && it != m_RouterInfos.end ())
{
@@ -1265,7 +1293,7 @@ namespace data
return it->second;
it++;
}
// still not found, try to the begining
// still not found, try to the beginning
it = it2;
while (it != m_RouterInfos.end ())
{
@@ -1359,7 +1387,8 @@ namespace data
return res;
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily (FamilyID fam) const
{
return GetRandomRouter(
[fam](std::shared_ptr<const RouterInfo> router)->bool
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2021, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -30,19 +30,22 @@
#include "NetDbRequests.h"
#include "Family.h"
#include "version.h"
#include "util.h"
namespace i2p
{
namespace data
{
const int NETDB_MIN_ROUTERS = 90;
const int NETDB_MIN_FLOODFILLS = 5;
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days
const int NETDB_PUBLISH_INTERVAL = 60 * 40;
const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36
const int NETDB_MIN_FLOODFILL_VERSION = MAKE_VERSION_NUMBER(0, 9, 38); // 0.9.38
const int NETDB_MIN_SHORT_TUNNEL_BUILD_VERSION = MAKE_VERSION_NUMBER(0, 9, 51); // 0.9.51
@@ -87,13 +90,14 @@ namespace data
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
std::shared_ptr<const RouterInfo> GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily (FamilyID fam) const;
void SetUnreachable (const IdentHash& ident, bool unreachable);
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
@@ -119,13 +123,14 @@ namespace data
size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
void ClearRouterInfos () { m_RouterInfos.clear (); };
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
private:
void Load ();
bool LoadRouterInfo (const std::string & path);
bool LoadRouterInfo (const std::string& path, uint64_t ts);
void SaveUpdated ();
void Run (); // exploratory thread
void Explore (int numDestinations);
@@ -152,7 +157,6 @@ namespace data
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
bool m_IsRunning;
uint64_t m_LastLoad;
std::thread * m_Thread;
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
@@ -174,6 +178,8 @@ namespace data
std::set<IdentHash> m_PublishExcluded;
uint32_t m_PublishReplyToken = 0;
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
};
extern NetDb netdb;

View File

@@ -60,7 +60,7 @@ namespace data
void Start ();
void Stop ();
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
void ManageRequests ();

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