Compare commits

..

179 Commits

Author SHA1 Message Date
R4SAS
1c970b0714 2.17.0 2017-12-04 21:40:32 +03:00
orignal
6636e432d7 2.17.0 2017-12-04 13:05:04 -05:00
orignal
158889b85c check for invalid params 2017-12-01 16:25:32 -05:00
R4SAS
92bebb7ecc webconsole update (#1017)
* webconsole exploratory tunnel mark
* loglevel on commands page
* fix line break on destination page
2017-12-01 22:18:04 +03:00
orignal
fff34e77f5 pass signature and crypto type to newkeys 2017-12-01 13:43:00 -05:00
orignal
df18692af9 check I2NP messsage buffer size 2017-12-01 12:57:05 -05:00
orignal
a1e820182c CRYPTO_TYPE for DEST GENERATE 2017-11-28 13:24:07 -05:00
orignal
272090fc8f don't accept streams from RSA detinations 2017-11-28 11:33:51 -05:00
orignal
ab6bc52a0f don't create destination with RSA signature 2017-11-28 10:59:11 -05:00
R4SAS
c69c369502 close div, update qt gitignore 2017-11-26 12:30:18 +03:00
orignal
a5b1b24fee implement i2p.streaming.connectDelay option 2017-11-24 15:37:17 -05:00
orignal
40cfbc5d61 Merge pull request #1016 from majestrate/fix-streaming-overflow
fix overflow
2017-11-23 13:54:34 -05:00
Jeff Becker
ffad1ecd6d reduce buffer size 2017-11-23 13:46:04 -05:00
Jeff Becker
e1b5803902 fix overflow 2017-11-23 12:27:28 -05:00
orignal
492d71a924 transient keys 2017-11-22 14:49:45 -05:00
R4SAS
6d01a3a7d1 fix (quote) 2017-11-21 21:33:24 +03:00
orignal
b71e20dfa3 changed back 2017-11-21 13:25:40 -05:00
orignal
474158dd18 rollback. build error 2017-11-21 11:04:32 -05:00
orignal
914db816c2 Merge pull request #1014 from AMDmi3/patch-1
Fix flags
2017-11-21 07:17:49 -05:00
Dmitry Marakasov
4485d6fdf4 Fix flags
-stdlib should not be changed. It breaks build on e.g. FreeBSD where libc++ is used.
2017-11-21 14:35:39 +03:00
orignal
2c394661a6 Merge pull request #1011 from hypnosis-i2p/openssl
updated qt to build and to reflect some core changes like log dest
2017-11-19 07:14:50 -05:00
hypnosis-i2p
611c1a7502 updated qt to build and to reflect some core changes like log dest 2017-11-19 19:26:36 +08:00
orignal
4e8858a764 Merge pull request #1009 from majestrate/reseed-proxy
reseed proxy
2017-11-18 16:15:37 -05:00
R4SAS
fb46de5ca6 Delete old R4SAS's reseed cert 2017-11-18 23:56:52 +03:00
Jeff Becker
65db96e663 reseed proxy 2017-11-18 09:50:30 -05:00
orignal
5109d40d8e don't publish unknown crypto type to Java floodfill again 2017-11-17 14:28:48 -05:00
R4SAS
1ba1fa37f9 update travis-ci stuff (#1006)
* enable osx in travis config
* fix brew commands, change comiler
* disable clang build with make on linux
* update README
* tabulation fix in Crypto.cpp
2017-11-17 20:43:00 +03:00
R4SAS
9c97ee6407 check for existing addressbook record 2017-11-16 01:13:42 +03:00
R4SAS
7477d2c219 fix forgotten log colors 2017-11-15 21:51:03 +03:00
R4SAS
a6fb3b602e add loglevel none (closing #998) 2017-11-15 21:46:20 +03:00
R4SAS
d9b9457b56 update webconsole 2017-11-15 00:49:32 +03:00
orignal
cfb6ddbfc6 CRYPTO_TYPE for SAM destinations 2017-11-14 15:05:07 -05:00
orignal
7de21c1f93 show proxy tunnel name 2017-11-14 13:20:54 -05:00
R4SAS
100f3380c4 fix upnp definitions and make cmake silent (#999) 2017-11-14 08:38:45 +03:00
R4SAS
20e484bb8b travis-ci cmake fix 2017-11-14 06:34:57 +03:00
R4SAS
94fc1a1cee debian wheezy upnp fix 2017-11-14 03:41:01 +03:00
R4SAS
ae28df5276 2.16.0 2017-11-13 22:20:41 +03:00
orignal
3a4f1382f3 2.16.0 2017-11-13 14:09:55 -05:00
orignal
01a7e08585 0.2.16 2017-11-13 14:01:04 -05:00
orignal
847fd15af2 0.2.16 2017-11-13 13:59:41 -05:00
orignal
a21fb17d73 renamed ECIES-P256 2017-11-13 11:50:17 -05:00
orignal
0c34bd440b reject routers with RSA signatures 2017-11-13 11:25:42 -05:00
orignal
34d6eb52d0 Merge pull request #996 from majestrate/stream-limits
Stream limits
2017-11-13 07:46:06 -05:00
Jeff Becker
5820425b6c Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into stream-limits 2017-11-13 07:26:32 -05:00
Jeff Becker
a4b39a3648 disable connection limiting by default 2017-11-13 07:26:27 -05:00
R4SAS
3dc5542a28 update mingw makefile 2017-11-13 04:46:19 +03:00
R4SAS
dde4643e77 fix shutdown from webconsole in windows 2017-11-13 03:30:52 +03:00
R4SAS
7a857e08c1 update windows build batch 2017-11-13 03:30:52 +03:00
orignal
80a3bd6a3b correct new key pair 2017-11-12 17:31:00 -05:00
orignal
7fb8ee60b4 correct random padding for ICIES public key 2017-11-11 22:10:54 -05:00
orignal
dca4cf2edb fixed #993. bind inbound tunnel to inhost 2017-11-10 11:27:20 -05:00
orignal
2bc33f22df fixed #994. check if keys are set 2017-11-10 09:49:50 -05:00
orignal
d14c6e2829 cryptotype for server tunnels 2017-11-09 16:18:59 -05:00
orignal
a4ce224cd1 pass correct crypto type to identity 2017-11-09 15:49:27 -05:00
orignal
ab1cd3f5cf ECIES for GOST R 34.10 2017-11-09 15:01:07 -05:00
orignal
1e75de9bb8 514 bytes ECIES block 2017-11-08 21:06:58 -05:00
orignal
19a03c42a5 use generic Decrypt instead ElGamalDecrypt 2017-11-08 20:45:53 -05:00
orignal
9e5d1bf0fc cryptotype tunnel configuration parameter added 2017-11-08 15:59:41 -05:00
orignal
c5f784719d implement Decrypt for all local destination 2017-11-08 13:49:48 -05:00
orignal
60aa459dfc 0.9.32 2017-11-08 11:01:00 -05:00
orignal
53d71d29ff call RoutingDestination::Encrypt instead ElGamalEncrypt 2017-11-07 20:30:05 -05:00
orignal
81658d2ff9 generic encryption for RoutingDestination 2017-11-07 15:05:22 -05:00
orignal
9fa67b0e0a crypto key encryptor and decryptor 2017-11-06 15:54:18 -05:00
orignal
88ba494701 fixed build error 2017-11-06 15:12:51 -05:00
orignal
efacfced45 CryptoKey added 2017-11-06 13:40:58 -05:00
orignal
b3c836f298 Merge pull request #987 from majestrate/gcc-7-ubuntu-artsy-fix
fix gcc 7 on ubuntu
2017-11-05 06:22:49 -05:00
Jeff Becker
3330bf4f2f fix gcc 7 on ubuntu 2017-11-04 07:53:24 -04:00
orignal
e634c89995 generate non-ElGamal encryption keys pair 2017-11-02 16:13:10 -04:00
orignal
5aa53eee43 GetIdentity for RoutingDestination 2017-11-02 14:50:57 -04:00
orignal
00bbb81375 ECICS gerenarate keys 2017-11-01 14:06:55 -04:00
orignal
5271cdacf2 ECICSDecrypt 2017-11-01 10:59:36 -04:00
orignal
6d01726961 use AES-CBC for ECICS 2017-11-01 10:20:11 -04:00
orignal
12feac1f50 fixed build error for wheezy 2017-10-31 21:25:52 -04:00
orignal
39c1c3567b ECICSEncrypt added 2017-10-30 16:16:21 -04:00
orignal
63ae6850d3 Fix #979. Router without host but with introducers is considered as SSU v4 2017-10-30 12:58:20 -04:00
Jeff
bec24e052c Merge pull request #983 from majestrate/i2np-transport-limits
fix limits when not specififed
2017-10-30 09:54:28 -04:00
Jeff Becker
91eb2b2c4a fix limits when not specififed 2017-10-30 09:53:41 -04:00
orignal
0bae2a3397 Merge pull request #982 from majestrate/i2np-transport-limits
I2np transport limits
2017-10-30 09:23:47 -04:00
Jeff Becker
42ec6db746 Merge remote-tracking branch 'purple/openssl' into i2np-transport-limits 2017-10-30 08:39:58 -04:00
Jeff Becker
7a9dc0eec0 use terminate 2017-10-30 08:37:54 -04:00
Jeff Becker
6441c9d5d8 initial ntcp soft/hard limits 2017-10-30 08:27:55 -04:00
orignal
2930d39ce7 Merge pull request #978 from majestrate/http-i2p-outproxy
support i2p outproxy in httpproxy
2017-10-29 10:30:03 -04:00
Jeff Becker
1500e805dd add is_i2p 2017-10-29 09:56:51 -04:00
Jeff Becker
b14d1801f0 support i2p outproxy 2017-10-27 08:43:54 -04:00
orignal
bc11181d5e tables for GOST R 34.11 2017-10-23 14:25:26 -04:00
R4SAS
9739e677aa Merge pull request #975 from chris-barry/974-apparmor-debian
Add apparmor profile to debian. #974
2017-10-16 01:19:35 +03:00
Chris Barry
056f076ae8 Add apparmor profile to debian. #974 2017-10-15 13:40:59 -04:00
R4SAS
7dfb6f4a13 update makefiles 2017-10-13 21:46:10 +03:00
orignal
b347b719f3 fixed race condition 2017-10-13 14:38:32 -04:00
orignal
7b537a4e94 Merge pull request #972 from radfish/PR--cmake-stdlib-args-for-clang
cmake: add stdlib args for clang build on Linux
2017-10-08 21:46:32 -04:00
redfish
291f28fcce cmake: add stdlib args for clang build on Linux
Otherwise linking fails with undefined symbol ... basic_string ... and
libstdc++: DSO not on included in link command.
2017-10-08 19:11:12 -04:00
orignal
fa9c39732d change max bandwidth limit 2017-10-05 10:37:28 -04:00
R4SAS
bfdf006bd2 add SAM session in webconsole 2017-10-05 05:29:07 +03:00
R4SAS
057d6ca05b windows warnings, tabulation workaround 2017-10-04 20:16:34 +03:00
orignal
7d7f5ff4e2 set default nickname after initialization 2017-10-04 12:40:43 -04:00
orignal
6e32f4bc85 set nickname for destination 2017-10-04 12:27:08 -04:00
orignal
8460a8f4ef update local destination if changed 2017-09-29 15:34:26 -04:00
orignal
8c09a7429c Merge pull request #967 from brain5lug/openssl
missed self assigment check for EDDSAPoint
2017-09-29 06:40:19 -04:00
brain5lug
346bf14b7b added missed invariant for MemoryPool 2017-09-29 10:17:23 +03:00
brain5lug
8e3c9410dc missed self assigment check for EDDSAPoint 2017-09-29 00:48:14 +03:00
orignal
cb0552e20d Merge pull request #966 from brain5lug/openssl
fixed perfect forwarding for the memory pool
2017-09-28 17:38:58 -04:00
brain5lug
8c8127dda6 fixed perfect forwarding for the memory pool 2017-09-29 00:03:07 +03:00
R4SAS
1d8a481d59 fix tabulation 2017-09-27 23:41:34 +03:00
R4SAS
dd4f066e95 add graceful shutdown in webconsole for windows
add stop graceful shutdown menu item
add reload menu item
2017-09-27 23:30:30 +03:00
orignal
5e0d4163a2 Merge pull request #965 from majestrate/fix-leak-2017-09-27
try fixing leak
2017-09-27 10:34:34 -04:00
Jeff Becker
7fb2d13a8b use BN_CTX_start and BN_CTX_end instead of removing BN_CTX_start 2017-09-27 09:49:43 -04:00
Jeff Becker
acde10b46e Merge remote-tracking branch 'purple/openssl' into fix-leak-2017-09-27 2017-09-27 09:48:19 -04:00
Jeff Becker
c0bcab8bc5 try fixing leak 2017-09-27 09:05:52 -04:00
orignal
fd6d0922ab Merge pull request #964 from radfish/PR--cmake-openssl-warn
cmake: issue a non-fatal warning for openssl >=1.1
2017-09-26 21:16:20 -04:00
redfish
8179e7dbf8 cmake: issue a non-fatal warning for openssl >=1.1 2017-09-26 20:46:06 -04:00
Jeff
eabeeaccfe Merge pull request #963 from radfish/PR--cmake-check-openssl-ver
cmake: check openssl version
2017-09-26 12:34:31 -04:00
redfish
94bba69dee cmake: check openssl version
See #835 for memory leak issues with OpenSSL >= 1.1
2017-09-26 10:56:02 -04:00
orignal
4d23de96d5 Merge pull request #961 from l-n-s/small_patches
fixed typo + added optional full date in logs `logclftime=true`
2017-09-19 22:02:30 -04:00
Darknet Villain
681810ea38 Use setter method for m_TimeFormat, set time format in Daemon.cpp instead of Log.cpp 2017-09-19 19:46:28 -04:00
Darknet Villain
d500fe66fd Add option logclftime=true for writing full date and time to logs 2017-09-18 18:49:03 -04:00
Darknet Villain
05c2adeefd fix typo 2017-09-18 15:24:53 -04:00
orignal
d46e0fb474 Merge pull request #958 from majestrate/macos-static
fix up homebrew makefile to allow static linking
2017-09-11 10:00:39 -04:00
Jeff
330fab2efa update macos i2pd qt build to statically compile in libraries for portability 2017-09-11 08:57:43 -04:00
Jeff
d59d36f93c fix up homebrew makefile 2017-09-11 07:48:10 -04:00
R4SAS
fd6827fdca add space 2017-09-09 20:13:45 +03:00
orignal
dca94f17d7 Merge pull request #952 from hypnosis-i2p/openssl
ui beautifying + fixed tunnels invalid ui data handling
2017-09-08 15:07:25 -04:00
hypnosis-i2p
d4e16881ff fixed tunnels invalid ui data handling 3 2017-09-09 01:13:42 +08:00
hypnosis-i2p
cd3f274763 fixed tunnels invalid ui data handling 2 2017-09-09 01:09:31 +08:00
hypnosis-i2p
1947be4957 fixed tunnels invalid ui data handling 2017-09-08 23:25:25 +08:00
hypnosis-i2p
21de4709ea ui beautifying more 2017-09-08 23:16:54 +08:00
hypnosis-i2p
ec76381a0b ui beautifying 2017-09-08 23:07:37 +08:00
orignal
66661417d7 Merge pull request #950 from hypnosis-i2p/openssl
ui critical fixes
2017-09-08 08:54:38 -04:00
hypnosis-i2p
81b79e6e53 ui critical fixes 2017-09-08 19:43:27 +08:00
orignal
5ae93d852e Merge pull request #948 from hypnosis-i2p/openssl
fixes #945 and #935
2017-09-08 07:00:30 -04:00
hypnosis-i2p
96cb663fa8 some work + fixed red errors on malformed input 2017-09-08 18:58:04 +08:00
hypnosis-i2p
1efc2a9b5d little ui fixes 2017-09-08 18:02:12 +08:00
hypnosis-i2p
9441c1cffe fixed #935 2017-09-08 17:57:15 +08:00
hypnosis-i2p
ef30d2d3b6 fixes #945 2017-09-08 15:59:19 +08:00
orignal
1673966e36 Merge pull request #942 from Markovskij/openssl
Make tunnels.conf more readable with QT GUI
2017-09-07 09:37:07 -04:00
Markovskij
1d8f913364 Merge branch 'openssl' of github.com:Markovskij/i2pd into openssl 2017-09-04 07:25:06 +03:00
Markovskij
a549ebc25f Add constants 2017-09-04 07:23:59 +03:00
Markovskij
ce853786b5 Merge pull request #2 from PurpleI2P/openssl
Update
2017-09-04 06:52:57 +03:00
orignal
7e0ab6d0b1 Merge pull request #943 from majestrate/connect-proxy
HTTP CONNECT in http proxy
2017-09-03 15:28:28 -04:00
Jeff Becker
d6f907a05b make it work 2017-09-03 11:13:43 -04:00
Jeff Becker
b2d1962b81 add http connect to http proxy (untested) 2017-09-03 09:46:55 -04:00
Markovskij
b0a6c9fa53 Make tunnels.conf more readable 2017-09-03 15:55:51 +03:00
Markovskij
7a0337f3db Merge pull request #1 from PurpleI2P/openssl
Update
2017-09-03 14:10:25 +03:00
orignal
c1dbd3ffd0 Merge pull request #940 from majestrate/defer-connect
Defer connect
2017-09-01 11:40:26 -04:00
Jeff Becker
1ea6d2016d add initial connection timeout for i2ptunnel 2017-08-31 12:08:22 -04:00
Jeff Becker
416589cc93 Revert "add deferred ready checking for destination"
This reverts commit 3f409d0e28.
2017-08-31 10:38:26 -04:00
Jeff Becker
41ce9d47e5 Revert "re trigger timer"
This reverts commit f87a51034e.
2017-08-31 10:37:58 -04:00
Jeff Becker
d7e4deab4e Revert "tabify"
This reverts commit 897cfad399.
2017-08-31 10:37:57 -04:00
Jeff Becker
27782ceddd Revert "clarify"
This reverts commit 7af3b751d4.
2017-08-31 10:37:56 -04:00
Jeff Becker
a6f62a99b9 Revert "use shared from this"
This reverts commit 4e4def4fb9.
2017-08-31 10:37:53 -04:00
Jeff Becker
4e4def4fb9 use shared from this 2017-08-31 10:24:07 -04:00
Jeff Becker
7af3b751d4 clarify 2017-08-31 10:14:06 -04:00
Jeff Becker
897cfad399 tabify 2017-08-31 10:12:59 -04:00
Jeff Becker
f87a51034e re trigger timer 2017-08-31 10:07:09 -04:00
Jeff Becker
3f409d0e28 add deferred ready checking for destination 2017-08-31 09:59:04 -04:00
orignal
543566840c Merge pull request #936 from hypnosis-i2p/openssl
ReloadConfig + --log fix
2017-08-27 13:43:09 -04:00
hypnosis-i2p
1c3174a277 fixed #841 2017-08-27 21:16:52 +08:00
hypnosis-i2p
fc2ae6f887 fixed ReloadConfig(); fixed --log 2017-08-27 20:52:55 +08:00
hypnosis-i2p
63e175d389 fixed #913 2017-08-27 20:39:10 +08:00
orignal
9bfbba6fea Merge pull request #934 from hypnosis-i2p/openssl
various small qt gui fixes
2017-08-27 07:28:15 -04:00
Jeff
69d245c4bd Merge pull request #933 from myfingerhurt/openssl
Fix deformed json result with an extra comma
2017-08-27 06:44:02 -04:00
hypnosis-i2p
7738eae4b0 general settings widget ui revolution for convenience + widget locks: fixed #927 2017-08-27 16:10:09 +08:00
hypnosis-i2p
3d5fb07ca8 various small qt gui fixes 2017-08-27 12:41:10 +08:00
NeverExist
0f0fb266c7 Fix deformed json result with an extra comma
{"id":1,"result":{"i2p.router.net.bw.in":48,"i2p.router.net.bw.out":48,},"jsonrpc":"2.0"}
You can see there is an extra comma behind the number 48.
2017-08-27 12:57:06 +09:00
orignal
5c3d6298b0 Merge branch 'openssl' of https://github.com/PurpleI2P/i2pd into openssl 2017-08-25 14:46:24 -04:00
orignal
028f0bdb8d Fixed #931. don't insert null pointer into DHkeys list 2017-08-25 14:45:58 -04:00
Jeff
44bcdc6866 Merge pull request #932 from Markovskij/openssl
Web interface fix
2017-08-24 20:46:21 -04:00
Markovskij
b9f6f92bad Web interface fix 2017-08-25 02:37:01 +03:00
orignal
1607535416 strip out Accept and From headers 2017-08-24 15:13:15 -04:00
orignal
f6ced9279b new reseed added 2017-08-20 17:34:53 -04:00
orignal
95af716a96 Merge pull request #925 from hypnosis-i2p/openssl
Qt GUI now shows buttons under Status and their corresponding info panes
2017-08-20 06:56:39 -04:00
hypnosis-i2p
07fe51fa25 some qt gui changes 2017-08-20 13:40:14 +08:00
hypnosis-i2p
822995cbaf ignored android/libs/ 2017-08-20 13:40:14 +08:00
hypnosis-i2p
db0e02c05d qt ui - status commands are now pushbuttons with no handlers 2017-08-20 13:40:14 +08:00
hypnosis-i2p
856dda68db qt ui - now all buttons have handlers 2017-08-20 13:40:14 +08:00
hypnosis-i2p
163cbcb89d qt ui - status main page now works 2017-08-20 13:40:14 +08:00
hypnosis-i2p
a79f614e12 qt ui - now pixel perfect buttons 2017-08-20 13:40:14 +08:00
hypnosis-i2p
7d3a818565 qt ui - laid out better 2017-08-20 13:40:14 +08:00
hypnosis-i2p
978bb47b92 qt ui - settings buttons renamed to *Settings 2017-08-20 13:40:14 +08:00
hypnosis-i2p
b791a6a348 qt ui - status buttons done 2017-08-20 13:40:14 +08:00
109 changed files with 8244 additions and 4892 deletions

2
.gitignore vendored
View File

@@ -262,3 +262,5 @@ qt/i2pd_qt/*.ui.autosave
qt/i2pd_qt/*.ui.bk*
qt/i2pd_qt/*.ui_*
#unknown android stuff
android/libs/

View File

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

View File

@@ -1,6 +1,40 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.17.0] - 2017-12-04
### Added
- Reseed through HTTP and SOCKS proxy
- Show status of client services through web console
- Change log level through web connsole
- transient keys for tunnels
- i2p.streaming.initialAckDelay parameter
- CRYPTO_TYPE for SAM destination
- signature and crypto type for newkeys BOB command
### Changed
- Correct publication of ECIES destinations
- Disable RSA signatures completely
### Fixed
- CVE-2017-17066
- Possible buffer overflow for RSA-4096
- Shutdown from web console for Windows
- Web console page layout
## [2.16.0] - 2017-11-13
### Added
- https and "Connect" method for HTTP proxy
- outproxy for HTTP proxy
- initial support of ECIES crypto
- NTCP soft and hard descriptors limits
- Support full timestamps in logs
### Changed
- Faster implmentation of GOST R 34.11 hash
- Reject routers with RSA signtures
- Reload config and shudown from Windows GUI
- Update tunnels address(destination) without restart
### Fixed
- BOB crashes if destination is not set
- Correct SAM tunnel name
- QT GUI issues
## [2.15.0] - 2017-08-17
### Added
- QT GUI

View File

@@ -89,14 +89,14 @@ $(SHLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
$(CXX) $(LDFLAGS) $(LDLIBS) -shared -o $@ $^
$(ARLIB): $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
ar -r $@ $^
$(AR) -r $@ $^
$(ARLIB_CLIENT): $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
ar -r $@ $^
$(AR) -r $@ $^
clean:
rm -rf obj
rm -rf docs/generated
$(RM) -r obj
$(RM) -r docs/generated
$(RM) $(I2PD) $(SHLIB) $(ARLIB) $(SHLIB_CLIENT) $(ARLIB_CLIENT)
strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)

View File

@@ -1,17 +1,32 @@
# root directory holding homebrew
BREWROOT = /usr/local/
BREWROOT = /usr/local
BOOSTROOT = ${BREWROOT}/opt/boost
SSLROOT = ${BREWROOT}/opt/libressl
CXX = clang++
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
UPNPROOT = ${BREWROOT}/opt/miniupnpc
CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
ifndef TRAVIS
CXX = clang++
endif
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
else
LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
endif
ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
LDLIBS += -lminiupnpc
INCFLAGS += -I${UPNPROOT}/include
ifeq ($(USE_STATIC),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
else
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif
# OSX Notes

View File

@@ -21,6 +21,8 @@ else ifeq ($(shell expr match ${CXXVER} "4\.6"),3) # = 4.6
NEEDED_CXXFLAGS += -std=c++0x
else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 ubuntu
NEEDED_CXXFLAGS += -std=c++11
else # not supported
$(error Compiler too old)
endif

View File

@@ -4,8 +4,8 @@ WINDRES = windres
CXXFLAGS = -Os -D_MT -DWIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN
NEEDED_CXXFLAGS = -std=c++11
BOOST_SUFFIX = -mt
INCFLAGS = -I/usr/include/ -I/usr/local/include/ -I. -Idaemon
LDFLAGS = -Wl,-rpath,/usr/local/lib -Wl,-Bstatic -static-libgcc -static-libstdc++ -L/usr/local/lib
INCFLAGS = -Idaemon -I.
LDFLAGS = -s -Wl,-rpath,/usr/local/lib -Wl,-Bstatic -static-libgcc -static-libstdc++
# UPNP Support
ifeq ($(USE_UPNP),yes)
@@ -30,7 +30,7 @@ LDLIBS += \
ifeq ($(USE_WIN32_APP), yes)
CXXFLAGS += -DWIN32_APP
LDFLAGS += -mwindows -s
LDFLAGS += -mwindows
DAEMON_RC += Win32/Resource.rc
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif
@@ -47,8 +47,7 @@ ifeq ($(USE_AVX),1)
endif
ifeq ($(USE_ASLR),yes)
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va \
-Wl,--dynamicbase,--export-all-symbols
LDFLAGS += -Wl,--nxcompat -Wl,--high-entropy-va -Wl,--dynamicbase,--export-all-symbols
endif
obj/%.o : %.rc

View File

@@ -5,29 +5,29 @@ INCFLAGS = -I/usr/local/include
LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
else
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
endif
ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
ifeq ($(USE_STATIC),yes)
LDLIBS += /usr/local/lib/libminiupnpc.a
else
LDLIBS += -lminiupnpc
endif
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
ifeq ($(USE_STATIC),yes)
LDLIBS += /usr/local/lib/libminiupnpc.a
else
LDLIBS += -lminiupnpc
endif
endif
ifeq ($(USE_AESNI),1)
CXXFLAGS += -maes -DAESNI
CXXFLAGS += -maes -DAESNI
else
CXXFLAGS += -msse
CXXFLAGS += -msse
endif
ifeq ($(USE_AVX),1)
CXXFLAGS += -mavx
CXXFLAGS += -mavx
endif
# Disabled, since it will be the default make rule. I think its better

View File

@@ -54,9 +54,9 @@ Build instructions:
**Supported systems:**
* GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
* Mac OS X
* GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd)
* Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd)
* FreeBSD
* Android
* iOS

View File

@@ -6,7 +6,6 @@
#include "Log.h"
#ifdef _WIN32
#include "Win32/Win32Service.h"
#ifdef WIN32_APP
#include "Win32/Win32App.h"
@@ -14,99 +13,99 @@
namespace i2p
{
namespace util
namespace util
{
bool DaemonWin32::init(int argc, char* argv[])
{
bool DaemonWin32::init(int argc, char* argv[])
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
if (!Daemon_Singleton::init(argc, argv))
return false;
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
if (serviceControl == "install")
{
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
if (!Daemon_Singleton::init(argc, argv))
return false;
std::string serviceControl; i2p::config::GetOption("svcctl", serviceControl);
if (serviceControl == "install")
{
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
InstallService(
SERVICE_NAME, // Name of service
SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
SERVICE_DEPENDENCIES, // Dependencies
SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
);
return false;
}
else if (serviceControl == "remove")
{
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
UninstallService(SERVICE_NAME);
return false;
}
if (isDaemon)
{
LogPrint(eLogDebug, "Daemon: running as service");
I2PService service(SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
}
else
LogPrint(eLogDebug, "Daemon: running as user");
return true;
LogPrint(eLogInfo, "WinSVC: installing ", SERVICE_NAME, " as service");
InstallService(
SERVICE_NAME, // Name of service
SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
SERVICE_DEPENDENCIES, // Dependencies
SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
);
return false;
}
else if (serviceControl == "remove")
{
LogPrint(eLogInfo, "WinSVC: uninstalling ", SERVICE_NAME, " service");
UninstallService(SERVICE_NAME);
return false;
}
bool DaemonWin32::start()
if (isDaemon)
{
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App ()) return false;
LogPrint(eLogDebug, "Daemon: running as service");
I2PService service(SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
}
else
LogPrint(eLogDebug, "Daemon: running as user");
return true;
}
// override log
i2p::config::SetOption("log", std::string ("file"));
bool DaemonWin32::start()
{
setlocale(LC_CTYPE, "");
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
setlocale(LC_ALL, "Russian");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App ()) return false;
// override log
i2p::config::SetOption("log", std::string ("file"));
#endif
bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
{
// TODO: find out where this garbage to console comes from
SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
}
bool insomnia; i2p::config::GetOption("insomnia", insomnia);
if (insomnia)
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
return ret;
}
bool DaemonWin32::stop()
bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile)
{
// TODO: find out where this garbage to console comes from
SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
}
bool insomnia; i2p::config::GetOption("insomnia", insomnia);
if (insomnia)
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
return ret;
}
bool DaemonWin32::stop()
{
#ifdef WIN32_APP
i2p::win32::StopWin32App ();
i2p::win32::StopWin32App ();
#endif
return Daemon_Singleton::stop();
}
return Daemon_Singleton::stop();
}
void DaemonWin32::run ()
{
void DaemonWin32::run ()
{
#ifdef WIN32_APP
i2p::win32::RunWin32App ();
i2p::win32::RunWin32App ();
#else
while (running)
while (running)
{
std::this_thread::sleep_for (std::chrono::seconds(1));
}
#endif
}
}
}
#endif
}
#endif //_WIN32

View File

@@ -9,6 +9,7 @@
#include "Tunnel.h"
#include "version.h"
#include "resource.h"
#include "Daemon.h"
#include "Win32App.h"
#include <stdio.h>
@@ -21,6 +22,8 @@
#define ID_CONSOLE 2002
#define ID_APP 2003
#define ID_GRACEFUL_SHUTDOWN 2004
#define ID_STOP_GRACEFUL_SHUTDOWN 2005
#define ID_RELOAD 2006
#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)
@@ -39,7 +42,11 @@ namespace win32
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);
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload configs");
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
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");
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
@@ -68,7 +75,7 @@ namespace win32
nid.uCallbackMessage = WM_TRAYICON;
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
strcpy (nid.szTip, "i2pd");
strcpy (nid.szInfo, "i2pd is running");
strcpy (nid.szInfo, "i2pd is starting");
Shell_NotifyIcon(NIM_ADD, &nid );
}
@@ -120,6 +127,7 @@ namespace win32
static void PrintMainWindowText (std::stringstream& s)
{
s << "\n";
s << "Status: ";
switch (i2p::context.GetStatus())
{
@@ -153,6 +161,7 @@ namespace win32
s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; ";
s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; ";
s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n";
s << "\n";
}
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -192,6 +201,22 @@ namespace win32
{
i2p::context.SetAcceptsTunnels (false);
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
i2p::util::DaemonWin32::Instance ().isGraceful = true;
return 0;
}
case ID_STOP_GRACEFUL_SHUTDOWN:
{
i2p::context.SetAcceptsTunnels (true);
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
i2p::util::DaemonWin32::Instance ().isGraceful = false;
return 0;
}
case ID_RELOAD:
{
i2p::client::context.ReloadConfig();
std::stringstream text;
text << "I2Pd reloading configs...";
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
return 0;
}
case ID_CONSOLE:
@@ -322,7 +347,7 @@ namespace win32
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
RegisterClassEx (&wclx);
// create new window
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 180, NULL, NULL, hInst, NULL))
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL))
{
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
@@ -343,6 +368,9 @@ namespace win32
void StopWin32App ()
{
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
}
@@ -350,8 +378,17 @@ namespace win32
{
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
return hWnd;
}
bool StopGracefulShutdown ()
{
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
return hWnd;
}
}
}

View File

@@ -7,10 +7,11 @@ namespace i2p
{
namespace win32
{
bool StartWin32App ();
void StopWin32App ();
int RunWin32App ();
bool GracefulShutdown ();
bool StartWin32App ();
void StopWin32App ();
int RunWin32App ();
bool GracefulShutdown ();
bool StopGracefulShutdown ();
}
}
#endif // WIN32APP_H__

View File

@@ -15,7 +15,6 @@ I2PService *I2PService::s_service = NULL;
BOOL I2PService::isService()
{
BOOL bIsService = FALSE;
HWINSTA hWinStation = GetProcessWindowStation();
if (hWinStation != NULL)
{
@@ -31,28 +30,23 @@ BOOL I2PService::isService()
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);
}
@@ -61,12 +55,12 @@ 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;
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;
}
}
@@ -76,11 +70,8 @@ I2PService::I2PService(PSTR pszServiceName,
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;
@@ -90,15 +81,13 @@ I2PService::I2PService(PSTR pszServiceName,
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
if (fCanPauseContinue)
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
m_status.dwControlsAccepted = dwControlsAccepted;
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);
@@ -108,7 +97,6 @@ I2PService::I2PService(PSTR pszServiceName,
}
}
I2PService::~I2PService(void)
{
if (m_hStoppedEvent)
@@ -118,92 +106,73 @@ I2PService::~I2PService(void)
}
}
void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
{
try
{
SetServiceStatus(SERVICE_START_PENDING);
OnStart(dwArgc, pszArgv);
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Start", dwError);
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to start.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_STOPPED);
}
}
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
{
LogPrint(eLogInfo, "Win32Service in OnStart", EVENTLOG_INFORMATION_TYPE);
Daemon.start();
//i2p::util::config::OptionParser(dwArgc, pszArgv);
//i2p::util::filesystem::ReadConfigFile(i2p::util::config::mapArgs, i2p::util::config::mapMultiArgs);
//i2p::context.OverrideNTCPAddress(i2p::util::config::GetCharArg("-host", "127.0.0.1"),
// i2p::util::config::GetArg("-port", 17070));
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
}
void I2PService::WorkerThread()
{
while (!m_fStopping)
{
::Sleep(1000); // Simulate some lengthy operations.
}
// Signal the stopped event.
SetEvent(m_hStoppedEvent);
}
void I2PService::Stop()
{
DWORD dwOriginalState = m_status.dwCurrentState;
try
{
SetServiceStatus(SERVICE_STOP_PENDING);
OnStop();
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
LogPrint(eLogInfo, "Win32Service Stop", dwError);
SetServiceStatus(dwOriginalState);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to stop.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(dwOriginalState);
}
}
void I2PService::OnStop()
{
// Log a service stop message to the Application log.
LogPrint(eLogInfo, "Win32Service in OnStop", EVENTLOG_INFORMATION_TYPE);
Daemon.stop();
m_fStopping = TRUE;
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
{
@@ -213,57 +182,46 @@ void I2PService::OnStop()
delete _worker;
}
void I2PService::Pause()
{
try
{
SetServiceStatus(SERVICE_PAUSE_PENDING);
OnPause();
SetServiceStatus(SERVICE_PAUSED);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Pause", dwError);
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to pause.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_RUNNING);
}
}
void I2PService::OnPause()
{
}
void I2PService::Continue()
{
try
{
SetServiceStatus(SERVICE_CONTINUE_PENDING);
OnContinue();
SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
LogPrint(eLogError, "Win32Service Continue", dwError);
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
LogPrint(eLogError, "Win32Service failed to resume.", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_PAUSED);
}
}
@@ -277,7 +235,6 @@ void I2PService::Shutdown()
try
{
OnShutdown();
SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
@@ -299,11 +256,9 @@ void I2PService::SetServiceStatus(DWORD dwCurrentState,
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)) ?
@@ -328,7 +283,7 @@ void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
}
}
void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType, PSTR pszDependencies, PSTR pszAccount, PSTR pszPassword)
void InstallService(PCSTR pszServiceName, PCSTR pszDisplayName, DWORD dwStartType, PCSTR pszDependencies, PCSTR pszAccount, PCSTR pszPassword)
{
printf("Try to install Win32Service (%s).\n", pszServiceName);
@@ -383,7 +338,7 @@ void InstallService(PSTR pszServiceName, PSTR pszDisplayName, DWORD dwStartType,
FreeHandles(schSCManager, schService);
}
void UninstallService(PSTR pszServiceName)
void UninstallService(PCSTR pszServiceName)
{
printf("Try to uninstall Win32Service (%s).\n", pszServiceName);

View File

@@ -4,7 +4,6 @@
#include <thread>
#include <windows.h>
#ifdef _WIN32
// Internal name of the service
#define SERVICE_NAME "i2pdService"
@@ -25,7 +24,6 @@
#define SERVICE_PASSWORD NULL
#endif
class I2PService
{
public:
@@ -72,13 +70,15 @@ private:
std::thread* _worker;
};
void InstallService(PSTR pszServiceName,
PSTR pszDisplayName,
void InstallService(
PCSTR pszServiceName,
PCSTR pszDisplayName,
DWORD dwStartType,
PSTR pszDependencies,
PSTR pszAccount,
PSTR pszPassword);
PCSTR pszDependencies,
PCSTR pszAccount,
PCSTR pszPassword
);
void UninstallService(PSTR pszServiceName);
void UninstallService(PCSTR pszServiceName);
#endif // WIN_32_SERVICE_H__

View File

@@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.15.0"
#define I2Pd_ver "2.17.0"
#define I2Pd_Publisher "PurpleI2P"
[Setup]

View File

@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd"
android:versionCode="1"
android:versionName="2.15.0"
android:versionName="2.17.0"
android:installLocation="auto">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="25"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

View File

@@ -1,6 +1,7 @@
#APP_ABI := all
#APP_ABI := armeabi-v7a x86
#APP_ABI := x86
#APP_ABI := x86_64
APP_ABI := armeabi-v7a
#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

View File

@@ -1,4 +1,4 @@
version: 2.15.{build}
version: 2.17.{build}
pull_requests:
do_not_increment_build_number: true
branches:

View File

@@ -36,6 +36,7 @@ set (LIBI2PD_SRC
"${LIBI2PD_SRC_DIR}/BloomFilter.cpp"
"${LIBI2PD_SRC_DIR}/Config.cpp"
"${LIBI2PD_SRC_DIR}/Crypto.cpp"
"${LIBI2PD_SRC_DIR}/CryptoKey.cpp"
"${LIBI2PD_SRC_DIR}/Garlic.cpp"
"${LIBI2PD_SRC_DIR}/Gzip.cpp"
"${LIBI2PD_SRC_DIR}/HTTP.cpp"
@@ -149,7 +150,7 @@ else()
if (MSYS OR MINGW)
add_definitions( -DWIN32_LEAN_AND_MEAN )
endif ()
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter" )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic" )
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail (libssp & libc)
@@ -178,6 +179,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif ()
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# more tweaks
if (NOT (MSVC OR MSYS OR APPLE))
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" )
endif()
endif ()
if (WITH_HARDENING AND MSVC)
@@ -322,6 +326,10 @@ endif()
find_package ( OpenSSL REQUIRED )
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
else()
if(NOT (OPENSSL_VERSION VERSION_LESS 1.1))
message(WARNING "Your OpenSSL version ${OPENSSL_VERSION} >=1.1 is experimental: build with v1.0 when possible.")
endif()
endif()
if (WITH_UPNP)
@@ -393,7 +401,7 @@ message(STATUS " UPnP : ${WITH_UPNP}")
message(STATUS " PCH : ${WITH_PCH}")
message(STATUS " MESHNET : ${WITH_MESHNET}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THEADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS " I2LUA : ${WITH_I2LUA}")
message(STATUS " WEBSOCKETS : ${WITH_WEBSOCKETS}")
message(STATUS "---------------------------------------")
@@ -453,6 +461,12 @@ if (WITH_BINARY)
fixup_bundle(\"${APPS}\" \"\" \"${DIRS}\")
" COMPONENT Runtime)
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if (NOT (MSVC OR MSYS OR APPLE)) # for Clang build on Linux
target_link_libraries("${PROJECT_NAME}" stdc++)
endif()
endif()
endif ()
install(FILES ../LICENSE

View File

@@ -18,22 +18,27 @@ set MSYS2_PATH_TYPE=inherit
set CHERE_INVOKING=enabled_from_arguments
set MSYSTEM=MSYS
set "xSH=%WD%bash -lc"
REM detecting number of processors and subtract 1.
set /a threads=%NUMBER_OF_PROCESSORS%-1
REM we must work in root of repo
cd ..
REM deleting old log files
del /S build_*.log >> nul
echo Receiving latest commit and cleaning up...
"%WD%bash" -lc "git pull && make clean" > build/build_git.log 2>&1
%xSH% "git pull && make clean" > build/build_git.log 2>&1
echo.
REM set to variable current commit hash
FOR /F "usebackq" %%a IN (`%WD%bash -lc 'git describe --tags'`) DO (
FOR /F "usebackq" %%a IN (`%xSH% 'git describe --tags'`) DO (
set tag=%%a
)
"%WD%bash" -lc "echo To use configs and certificates, move all files and certificates folder from contrib directory here. > README.txt" >> nul
%xSH% "echo To use configs and certificates, move all files and certificates folder from contrib directory here. > README.txt" >> nul
REM starting building
set MSYSTEM=MINGW32
@@ -55,12 +60,12 @@ exit /b 0
:BUILDING
echo Building i2pd %tag% for win%bitness%:
echo Build AVX+AESNI...
"%WD%bash" -lc "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1
%xSH% "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1
echo Build AVX...
"%WD%bash" -lc "make USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.log 2>&1
%xSH% "make USE_UPNP=yes USE_AVX=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx.log 2>&1
echo Build AESNI...
"%WD%bash" -lc "make USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.log 2>&1
%xSH% "make USE_UPNP=yes USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_aesni.log 2>&1
echo Build without extensions...
"%WD%bash" -lc "make USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1
%xSH% "make USE_UPNP=yes -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%.log 2>&1
:EOF

View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN
aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x
CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT
FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4
cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF
x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h
vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm
w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw
MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy
Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy
f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b
mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d
Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP
0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq
jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/
BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E
BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC
AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk
5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o
3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS
AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal
zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs
0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ
cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4
4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6
GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW
dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5
qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w==
-----END CERTIFICATE-----

View File

@@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFezCCA2OgAwIBAgIEb8xTzzANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxHjAcBgNVBAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEL
MAkGA1UEChMCWFgxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOcjRzYXNAbWFpbC5p
MnAwHhcNMTYwODExMjIyNDM2WhcNMjYwODExMjIyNDM2WjBuMQswCQYDVQQGEwJY
WDELMAkGA1UECBMCWFgxHjAcBgNVBAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEL
MAkGA1UEChMCWFgxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOcjRzYXNAbWFpbC5p
MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDjUMy/aYd0i6Oc3rdc
24V/fM2vhviH+cNhAOXsMSrwDSVbFQkuDPIfq4fo1A25rsyULR57vy7XKA51OstX
GvREPDhth4cMZjthq0f8AVzPq2vIk8Po65uvKR190yupPQ4FhvGeRkHkqp+SqoIJ
lClD8xZEHrUHSYZotm5TLWIgSwa4DuO1q3bMRI8oIWzqhv99FtlmHlC8fjVUN4mR
2czhABr0u6RMPOtJwTVxWgT1PKXiLWfmeHb63TcPYGgpJ39iMDOjtgY9jYueoO8J
uGJJtkGRIRjOuhDFE9NUlNnljUxUDWvMU7zCO4ozaKMZgoxr1WoIO6ubI/003I53
sZ0Q5h8yfz+QreEw3wzjxnQSkejG5c3NIvJSiu0ylOqDWmnj0v1Jv/P0qAMU4bt/
ZWj0GOrYfPn9STg0VxMOQwQ2o15GAcbr6PFI56U2IJhZAeER3hIe2kOl6591jQ67
zvOjPRRh2q05Ss8yo7nEpYUiB/FrE6RssJ5tVwX6e6Tq4Z1frINanIkUkToTkypP
Fn2T/KV2lak9rLuxzvhiDobu5iGCR323zFcFEpGq4Wsopx1uRT9+71G/ejw8pKTf
kQ7XiGaaxFyZuMuOz3bFkTuoTmAkUQTlRjGw2DmKZi/apcN+VQgpq9tQpS10pEUy
DCVdtw1AdlOnwb+Hf3X0Uz6OjwIDAQABoyEwHzAdBgNVHQ4EFgQUqLBlSlnqCo25
sIduMPm4iROMqkAwDQYJKoZIhvcNAQENBQADggIBAGWv8rDTzqhHkjqDOT+Ba2bs
gVddpCNa94RQoOn2DUSu4c+yuWJLSctjpX7gswB6qvWk5Ojfafop8jJW8zuozJrO
76b9345S/VnnbHVSoVfIpF9Fve1Xc8nvU4ylRcAMwhf8N3Md5Yc1kb+P7NtTTwMZ
TBR3xY3fVxv3qTpKApWQKkUiqM7yJKOfS8xcK/pjO/3oRUwfA9DHugCUpgSidlN+
JkZmgwAcA3/WMlDdNKmKnWLGB2Ea+W6kIx5TDFfjf11rbjuwXhDLyaOK88qlN0W2
hYa31UDSEYYQd3gMG1gjVc+9vZA/Vr0+SF5ULN9QLjB18CVIdPv92mBjJQRmJSVW
b1qwZI0jf/V+1fu9H9r7sE4CId3+WGOek3UNRNZLOVZCSiFq/b9cswcQZGjw6aE+
1FNjw1HW9CLoNcg74Kr98QouOoeRSofQYZiYqaM9Sz/MsinYMIRGRGw3Uq1uNRo0
WgoOngmZSKGaW5PFR19uuuNIVB4fCShqBVyrguW4xIskta1JVFoggFeOeTwk6/kH
S5roMzyB/kzv83A2IB0VxqbiDj8khgdm1Us6HCCmU+iTRVyG28gFklCJ8dQfxgGH
W2gpIwvxYLyNP14/7E1oF7/NfHmyjAVzYnR5Xw2wE4tvSHuIrHhj6Q26VB3vze6j
E/w1AJEepnw/KfHqS3bw
-----END CERTIFICATE-----

View File

@@ -23,7 +23,8 @@
# log = file
## Path to logfile (default - autodetect)
# logfile = /var/log/i2pd.log
## Log messages above this level (debug, *info, warn, error)
## Log messages above this level (debug, *info, warn, error, none)
## If you set it to none, logging will be disabled
# loglevel = info
## Path to storage of i2pd data (RI, keys, peer profiles, ...)

View File

@@ -1,7 +1,7 @@
%define build_timestamp %(date +"%Y%m%d")
Name: i2pd
Version: 2.15.0
Version: 2.17.0
Release: %{build_timestamp}git%{?dist}
Summary: I2P router written in C++
@@ -103,6 +103,35 @@ getent passwd i2pd >/dev/null || \
%changelog
* Mon Dec 04 2017 orignal <i2porignal@yandex.ru> - 2.17.0
- Added reseed through HTTP and SOCKS proxy
- Added show status of client services through web console
- Added change log level through web connsole
- Added transient keys for tunnels
- Added i2p.streaming.initialAckDelay parameter
- Added CRYPTO_TYPE for SAM destination
- Added signature and crypto type for newkeys BOB command
- Changed - correct publication of ECIES destinations
- Changed - disable RSA signatures completely
- Fixed CVE-2017-17066
- Fixed possible buffer overflow for RSA-4096
- Fixed shutdown from web console for Windows
- Fixed web console page layout
* Mon Nov 13 2017 orignal <i2porignal@yandex.ru> - 2.16.0
- Added https and "Connect" method for HTTP proxy
- Added outproxy for HTTP proxy
- Added initial support of ECIES crypto
- Added NTCP soft and hard descriptors limits
- Added support full timestamps in logs
- Changed faster implmentation of GOST R 34.11 hash
- Changed reject routers with RSA signtures
- Changed reload config and shudown from Windows GUI
- Changed update tunnels address(destination) without restart
- Fixed BOB crashes if destination is not set
- Fixed correct SAM tunnel name
- Fixed QT GUI issues
* Thu Aug 17 2017 orignal <i2porignal@yandex.ru> - 2.15.0
- Added QT GUI
- Added ability add and remove I2P tunnels without restart

View File

@@ -94,8 +94,12 @@ namespace i2p
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 */
if (logclftime)
i2p::log::Logger().SetTimeFormat ("[%d/%b/%Y:%H:%M:%S %z]");
if (isDaemon && (logs == "" || logs == "stdout"))
logs = "file";

View File

@@ -6,11 +6,11 @@
namespace i2p
{
namespace util
namespace util
{
class Daemon_Singleton_Private;
class Daemon_Singleton
{
class Daemon_Singleton_Private;
class Daemon_Singleton
{
public:
virtual bool init(int argc, char* argv[]);
virtual bool start();
@@ -29,40 +29,38 @@ namespace i2p
// d-pointer for httpServer, httpProxy, etc.
class Daemon_Singleton_Private;
Daemon_Singleton_Private &d;
};
};
#if defined(QT_GUI_LIB) // check if QT
#define Daemon i2p::util::DaemonQT::Instance()
// dummy, invoked from RunQT
class DaemonQT: public i2p::util::Daemon_Singleton
// dummy, invoked from RunQT
class DaemonQT: public i2p::util::Daemon_Singleton
{
public:
static DaemonQT& Instance()
{
static DaemonQT instance;
return instance;
}
};
};
#elif defined(ANDROID)
#define Daemon i2p::util::DaemonAndroid::Instance()
// dummy, invoked from android/jni/DaemonAndroid.*
class DaemonAndroid: public i2p::util::Daemon_Singleton
class DaemonAndroid: public i2p::util::Daemon_Singleton
{
public:
static DaemonAndroid& Instance()
{
static DaemonAndroid instance;
return instance;
}
};
};
#elif defined(_WIN32)
#define Daemon i2p::util::DaemonWin32::Instance()
class DaemonWin32 : public Daemon_Singleton
{
class DaemonWin32 : public Daemon_Singleton
{
public:
static DaemonWin32& Instance()
{
@@ -74,34 +72,36 @@ namespace i2p
bool start();
bool stop();
void run ();
};
bool isGraceful;
DaemonWin32 ():isGraceful(false) {}
};
#else
#define Daemon i2p::util::DaemonLinux::Instance()
class DaemonLinux : public Daemon_Singleton
{
public:
static DaemonLinux& Instance()
{
static DaemonLinux instance;
return instance;
}
class DaemonLinux : public Daemon_Singleton
{
public:
static DaemonLinux& Instance()
{
static DaemonLinux instance;
return instance;
}
bool start();
bool stop();
void run ();
bool start();
bool stop();
void run ();
private:
private:
std::string pidfile;
int pidFH;
std::string pidfile;
int pidFH;
public:
int gracefulShutdownInterval; // in seconds
};
public:
int gracefulShutdownInterval; // in seconds
};
#endif
}
}
}
#endif // DAEMON_H__

View File

@@ -51,8 +51,8 @@ namespace http {
const char *cssStyles =
"<style>\r\n"
" body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n"
" a { text-decoration: none; color: #894C84; }\r\n"
" a:hover { color: #FAFAFA; background: #894C84; }\r\n"
" a, .slide label { text-decoration: none; color: #894C84; }\r\n"
" a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n"
" .header { font-size: 2.5em; text-align: center; margin: 1.5em 0; color: #894C84; }\r\n"
" .wrapper { margin: 0 auto; padding: 1em; max-width: 60em; }\r\n"
" .left { float: left; position: absolute; }\r\n"
@@ -60,12 +60,13 @@ namespace http {
" .tunnel.established { color: #56B734; }\r\n"
" .tunnel.expiring { color: #D3AE3F; }\r\n"
" .tunnel.failed { color: #D33F3F; }\r\n"
" .tunnel.another { color: #434343; }\r\n"
" .tunnel.building { color: #434343; }\r\n"
" caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n"
" table { width: 100%; border-collapse: collapse; text-align: center; }\r\n"
" .private { background: black; color: black; } .private:hover { background: black; color: white } \r\n"
" .slide p, .slide [type='checkbox']{ display:none; } \r\n"
" .slide [type='checkbox']:checked ~ p { display:block; } \r\n"
" .slide p, .slide [type='checkbox']{ display:none; }\r\n"
" .slide [type='checkbox']:checked ~ p { display:block; margin-top: 0; padding: 0; }\r\n"
" .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n"
" .enabled:after { color: #56B734; content: \"Enabled\" }\r\n"
"</style>\r\n";
const char HTTP_PAGE_TUNNELS[] = "tunnels";
@@ -83,13 +84,14 @@ namespace http {
const char HTTP_COMMAND_DISABLE_TRANSIT[] = "disable_transit";
const char HTTP_COMMAND_SHUTDOWN_START[] = "shutdown_start";
const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel";
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test";
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
static void ShowUptime (std::stringstream& s, int seconds)
static void ShowUptime (std::stringstream& s, int seconds)
{
int num;
@@ -120,7 +122,7 @@ namespace http {
s << numKBytes / 1024 / 1024 << " GiB";
}
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, int bytes)
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
{
std::string state;
switch (eState) {
@@ -133,10 +135,21 @@ namespace http {
case i2p::tunnel::eTunnelStateEstablished : state = "established"; break;
default: state = "unknown"; break;
}
s << "<span class=\"tunnel " << state << "\"> " << state << "</span>, ";
s << "<span class=\"tunnel " << state << "\"> " << state << ((explr) ? " (exploratory)" : "") << "</span>, ";
s << " " << (int) (bytes / 1024) << "&nbsp;KiB<br>\r\n";
}
static void SetLogLevel (const std::string& level)
{
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
i2p::log::Logger().SetLogLevel(level);
else {
LogPrint(eLogError, "HTTPServer: unknown loglevel set attempted");
return;
}
i2p::log::Logger().Reopen ();
}
static void ShowPageHead (std::stringstream& s)
{
s <<
@@ -185,7 +198,7 @@ namespace http {
s << "<b>ERROR:</b>&nbsp;" << string << "<br>\r\n";
}
static void ShowStatus (std::stringstream& s)
void ShowStatus (std::stringstream& s, bool includeHiddenContent)
{
s << "<b>Uptime:</b> ";
ShowUptime(s, i2p::context.GetUptime ());
@@ -195,21 +208,21 @@ namespace http {
{
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Testing"; break;
case eRouterStatusFirewalled: s << "Firewalled"; break;
case eRouterStatusError:
{
s << "Error";
case eRouterStatusFirewalled: s << "Firewalled"; break;
case eRouterStatusError:
{
s << "Error";
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
s << "<br>Clock skew";
s << "<br>Clock skew";
break;
default: ;
}
default: ;
}
break;
}
}
default: s << "Unknown";
}
}
s << "<br>\r\n";
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
if (auto remains = Daemon.gracefulShutdownInterval) {
@@ -230,33 +243,35 @@ namespace http {
s << " (" << (double) i2p::transport::transports.GetOutBandwidth () / 1024 << " KiB/s)<br>\r\n";
s << "<b>Transit:</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n";
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " KiB/s)<br>\r\n";
s << "<b>Data path:</b> " << i2p::fs::GetDataDir() << "<br>\r\n";
s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
s << "<b>Our external address:</b>" << "<br>\r\n" ;
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
{
switch (address->transportStyle)
s << "<div class='slide'><label for='slide-info'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide-info'/>\r\n<p class='content'>\r\n";
if(includeHiddenContent) {
s << "<b>Router Ident:</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
s << "<b>Router Family:</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
s << "<b>Router Caps:</b> " << i2p::context.GetRouterInfo().GetProperty("caps") << "<br>\r\n";
s << "<b>Our external address:</b>" << "<br>\r\n" ;
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
{
case i2p::data::RouterInfo::eTransportNTCP:
if (address->host.is_v6 ())
s << "NTCP6&nbsp;&nbsp;";
else
s << "NTCP&nbsp;&nbsp;";
break;
case i2p::data::RouterInfo::eTransportSSU:
if (address->host.is_v6 ())
s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
else
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
break;
default:
s << "Unknown&nbsp;&nbsp;";
switch (address->transportStyle)
{
case i2p::data::RouterInfo::eTransportNTCP:
if (address->host.is_v6 ())
s << "NTCP6&nbsp;&nbsp;";
else
s << "NTCP&nbsp;&nbsp;";
break;
case i2p::data::RouterInfo::eTransportSSU:
if (address->host.is_v6 ())
s << "SSU6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
else
s << "SSU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
break;
default:
s << "Unknown&nbsp;&nbsp;";
}
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
}
s << address->host.to_string() << ":" << address->port << "<br>\r\n";
}
s << "</p>\r\n</div>\r\n";
s << "<b>Routers:</b> " << i2p::data::netdb.GetNumRouters () << " ";
@@ -268,32 +283,42 @@ namespace http {
size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels();
s << "<b>Client Tunnels:</b> " << std::to_string(clientTunnelCount) << " ";
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n";
s << "<b>Transit Tunnels:</b> " << std::to_string(transitTunnelCount) << "<br>\r\n<br>\r\n";
s << "<table><caption>Services</caption><tr><th>Service</th><th>State</th></tr>\r\n";
s << "<tr><td>" << "HTTP Proxy" << "</td><td><div class='" << ((i2p::client::context.GetHttpProxy ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "<tr><td>" << "SOCKS Proxy" << "</td><td><div class='" << ((i2p::client::context.GetSocksProxy ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "<tr><td>" << "BOB" << "</td><td><div class='" << ((i2p::client::context.GetBOBCommandChannel ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "<tr><td>" << "SAM" << "</td><td><div class='" << ((i2p::client::context.GetSAMBridge ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "<tr><td>" << "I2CP" << "</td><td><div class='" << ((i2p::client::context.GetI2CPServer ()) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
s << "<tr><td>" << "I2PControl" << "</td><td><div class='" << ((i2pcontrol) ? "enabled" : "disabled") << "'></div></td></tr>\r\n";
s << "</table>\r\n";
}
static void ShowLocalDestinations (std::stringstream& s)
void ShowLocalDestinations (std::stringstream& s)
{
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetDestinations ())
{
auto ident = it.second->GetIdentHash ();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
auto ident = it.second->GetIdentHash ();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
}
auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer)
if (i2cpServer && !(i2cpServer->GetSessions ().empty ()))
{
s << "<br><b>I2CP Local Destinations:</b><br>\r\n<br>\r\n";
for (auto& it: i2cpServer->GetSessions ())
{
auto dest = it.second->GetDestination ();
if (dest)
{
auto ident = dest->GetIdentHash ();
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">";
{
auto ident = dest->GetIdentHash ();
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">";
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
}
}
}
}
}
@@ -302,14 +327,14 @@ namespace http {
{
s << "<b>Base64:</b><br>\r\n<textarea readonly=\"readonly\" cols=\"64\" rows=\"11\" wrap=\"on\">";
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
s << "<b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets () << "</i><br>\r\n";
if(dest->GetNumRemoteLeaseSets())
{
s << "<div class='slide'\r\n><label for='slide1'>Hidden content. Press on text to see.</label>\r\n<input type='checkbox' id='slide1'/>\r\n<p class='content'>\r\n";
s << "<div class='slide'><label for='slide-lease'><b>LeaseSets:</b> <i>" << dest->GetNumRemoteLeaseSets () << "</i></label>\r\n<input type='checkbox' id='slide-lease'/>\r\n<p class='content'>\r\n";
for(auto& it: dest->GetLeaseSets ())
s << it.second->GetIdentHash ().ToBase32 () << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
}
} else
s << "<b>LeaseSets:</b> <i>0</i><br>\r\n";
auto pool = dest->GetTunnelPool ();
if (pool)
{
@@ -318,7 +343,7 @@ namespace http {
it->Print(s);
if(it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << "ms )";
ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ());
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
}
s << "<br>\r\n";
s << "<b>Outbound tunnels:</b><br>\r\n";
@@ -326,20 +351,22 @@ namespace http {
it->Print(s);
if(it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << "ms )";
ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
}
}
s << "<br>\r\n";
s << "<b>Tags</b><br>Incoming: " << dest->GetNumIncomingTags () << "<br>Outgoing:<br>" << std::endl;
for (const auto& it: dest->GetSessions ())
{
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " ";
s << it.second->GetNumOutgoingTags () << "<br>" << std::endl;
}
s << "<br>" << std::endl;
s << "<b>Tags</b><br>Incoming: <i>" << dest->GetNumIncomingTags () << "</i><br>";
if (!dest->GetSessions ().empty ()) {
s << "<div class='slide'><label for='slide-tags'>Outgoing:</label>\r\n<input type='checkbox' id='slide-tags'/>\r\n<p class='content'>\r\n";
for (const auto& it: dest->GetSessions ())
s << i2p::client::context.GetAddressBook ().ToAddress(it.first) << " " << it.second->GetNumOutgoingTags () << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
} else
s << "Outgoing: <i>0</i><br>\r\n";
s << "<br>\r\n";
}
static void ShowLocalDestination (std::stringstream& s, const std::string& b32)
void ShowLocalDestination (std::stringstream& s, const std::string& b32)
{
s << "<b>Local Destination:</b><br>\r\n<br>\r\n";
i2p::data::IdentHash ident;
@@ -347,9 +374,9 @@ namespace http {
auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest)
{
ShowLeaseSetDestination (s, dest);
ShowLeaseSetDestination (s, dest);
// show streams
s << "<br>\r\n<table><caption>Streams</caption><tr>";
s << "<table><caption>Streams</caption>\r\n<tr>";
s << "<th>StreamID</th>";
s << "<th>Destination</th>";
s << "<th>Sent</th>";
@@ -360,7 +387,7 @@ namespace http {
s << "<th>RTT</th>";
s << "<th>Window</th>";
s << "<th>Status</th>";
s << "</tr>";
s << "</tr>\r\n";
for (const auto& it: dest->GetAllStreams ())
{
@@ -375,35 +402,35 @@ namespace http {
s << "<td>" << it->GetRTT () << "</td>";
s << "<td>" << it->GetWindowSize () << "</td>";
s << "<td>" << (int)it->GetStatus () << "</td>";
s << "</tr><br>\r\n" << std::endl;
}
s << "</tr>\r\n";
}
s << "</table>";
}
}
static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
{
auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer)
{
s << "<b>I2CP Local Destination:</b><br>\r\n<br>\r\n";
auto it = i2cpServer->GetSessions ().find (std::stoi (id));
auto it = i2cpServer->GetSessions ().find (std::stoi (id));
if (it != i2cpServer->GetSessions ().end ())
ShowLeaseSetDestination (s, it->second->GetDestination ());
else
ShowError(s, "I2CP session not found");
ShowError(s, "I2CP session not found");
}
else
ShowError(s, "I2CP is not enabled");
}
static void ShowLeasesSets(std::stringstream& s)
void ShowLeasesSets(std::stringstream& s)
{
s << "<div id='leasesets'><b>LeaseSets (click on to show info):</b></div><br>\r\n";
s << "<b>LeaseSets:</b><br>\r\n<br>\r\n";
int counter = 1;
// for each lease set
i2p::data::netdb.VisitLeaseSets(
[&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet)
[&s, &counter](const i2p::data::IdentHash dest, std::shared_ptr<i2p::data::LeaseSet> leaseSet)
{
// create copy of lease set so we extract leases
i2p::data::LeaseSet ls(leaseSet->GetBuffer(), leaseSet->GetBufferLen());
@@ -430,16 +457,19 @@ namespace http {
// end for each lease set
}
static void ShowTunnels (std::stringstream& s)
void ShowTunnels (std::stringstream& s)
{
s << "<b>Tunnels:</b><br>\r\n<br>\r\n";
s << "<b>Queue size:</b> " << i2p::tunnel::tunnels.GetQueueSize () << "<br>\r\n";
auto ExplPool = i2p::tunnel::tunnels.GetExploratoryPool ();
s << "<b>Inbound tunnels:</b><br>\r\n";
for (auto & it : i2p::tunnel::tunnels.GetInboundTunnels ()) {
it->Print(s);
if(it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << "ms )";
ShowTunnelDetails(s, it->GetState (), it->GetNumReceivedBytes ());
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
}
s << "<br>\r\n";
s << "<b>Outbound tunnels:</b><br>\r\n";
@@ -447,7 +477,7 @@ namespace http {
it->Print(s);
if(it->LatencyIsKnown())
s << " ( " << it->GetMeanLatency() << "ms )";
ShowTunnelDetails(s, it->GetState (), it->GetNumSentBytes ());
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
}
s << "<br>\r\n";
}
@@ -455,7 +485,7 @@ namespace http {
static void ShowCommands (std::stringstream& s, uint32_t token)
{
/* commands */
s << "<b>Router Commands</b><br>\r\n";
s << "<b>Router Commands</b><br>\r\n<br>\r\n";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">Run peer test</a><br>\r\n";
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
if (i2p::context.AcceptsTunnels ())
@@ -463,18 +493,27 @@ namespace http {
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
if (Daemon.gracefulShutdownInterval)
if (Daemon.gracefulShutdownInterval)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
#endif
#ifdef WIN32_APP
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
#elif defined(WIN32_APP)
if (i2p::util::DaemonWin32::Instance().isGraceful)
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
else
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
#endif
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
s << "<br>\r\n<b>Logging level</b><br>\r\n";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
}
static void ShowTransitTunnels (std::stringstream& s)
void ShowTransitTunnels (std::stringstream& s)
{
s << "<b>Transit tunnels:</b><br>\r\n<br>\r\n";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
@@ -489,10 +528,10 @@ namespace http {
}
}
static void ShowTransports (std::stringstream& s)
void ShowTransports (std::stringstream& s)
{
s << "<b>Transports:</b><br>\r\n<br>\r\n";
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
auto ntcpServer = i2p::transport::transports.GetNTCPServer ();
if (ntcpServer)
{
auto sessions = ntcpServer->GetNTCPSessions ();
@@ -525,13 +564,13 @@ namespace http {
}
if (!tmp_s.str ().empty ())
{
s << "<b>NTCP</b> ( " << cnt << " )<br>\r\n";
s << tmp_s.str () << "<br>\r\n";
s << "<div class='slide'><label for='slide_ntcp'><b>NTCP</b> ( " << cnt << " )</label>\r\n<input type='checkbox' id='slide_ntcp'/>\r\n<p class='content'>";
s << tmp_s.str () << "</p>\r\n</div>\r\n";
}
if (!tmp_s6.str ().empty ())
{
s << "<b>NTCP6</b> ( " << cnt6 << " )<br>\r\n";
s << tmp_s6.str () << "<br>\r\n";
s << "<div class='slide'><label for='slide_ntcp6'><b>NTCP6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_ntcp6'/>\r\n<p class='content'>";
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
}
}
}
@@ -541,7 +580,7 @@ namespace http {
auto sessions = ssuServer->GetSessions ();
if (!sessions.empty ())
{
s << "<b>SSU</b> ( " << (int) sessions.size() << " )<br>\r\n";
s << "<div class='slide'><label for='slide_ssu'><b>SSU</b> ( " << (int) sessions.size() << " )</label>\r\n<input type='checkbox' id='slide_ssu'/>\r\n<p class='content'>";
for (const auto& it: sessions)
{
auto endpoint = it.second->GetRemoteEndpoint ();
@@ -553,12 +592,12 @@ namespace http {
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
}
auto sessions6 = ssuServer->GetSessionsV6 ();
if (!sessions6.empty ())
{
s << "<b>SSU6</b> ( " << (int) sessions6.size() << " )<br>\r\n";
s << "<div class='slide'><label for='slide_ssu6'><b>SSU6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssu6'/>\r\n<p class='content'>";
for (const auto& it: sessions6)
{
auto endpoint = it.second->GetRemoteEndpoint ();
@@ -570,12 +609,12 @@ namespace http {
s << " [itag:" << it.second->GetRelayTag () << "]";
s << "<br>\r\n" << std::endl;
}
s << "<br>\r\n";
s << "</p>\r\n</div>\r\n";
}
}
}
static void ShowSAMSessions (std::stringstream& s)
void ShowSAMSessions (std::stringstream& s)
{
auto sam = i2p::client::context.GetSAMBridge ();
if (!sam) {
@@ -585,8 +624,9 @@ namespace http {
s << "<b>SAM Sessions:</b><br>\r\n<br>\r\n";
for (auto& it: sam->GetSessions ())
{
auto& name = it.second->localDestination->GetNickname ();
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
s << it.first << "</a><br>\r\n" << std::endl;
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
}
}
@@ -622,13 +662,13 @@ namespace http {
}
}
static void ShowI2PTunnels (std::stringstream& s)
void ShowI2PTunnels (std::stringstream& s)
{
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@@ -637,29 +677,32 @@ namespace http {
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP Proxy" << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
}
}
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS Proxy" << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
}
s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: i2p::client::context.GetServerTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8658; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort ();
s << "</a><br>\r\n"<< std::endl;
}
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
if (!serverTunnels.empty ()) {
s << "<br>\r\n<b>Server Tunnels:</b><br>\r\n<br>\r\n";
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8658; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << ":" << it.second->GetLocalPort ();
s << "</a><br>\r\n"<< std::endl;
}
}
auto& clientForwards = i2p::client::context.GetClientForwards ();
if (!clientForwards.empty ())
@@ -668,7 +711,7 @@ namespace http {
for (auto& it: clientForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@@ -681,7 +724,7 @@ namespace http {
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "<br>\r\n"<< std::endl;
@@ -690,7 +733,7 @@ namespace http {
}
HTTPConnection::HTTPConnection (std::shared_ptr<boost::asio::ip::tcp::socket> socket):
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0)
{
/* cache options */
i2p::config::GetOption("http.auth", needAuth);
@@ -751,10 +794,10 @@ namespace http {
}
/* method #2: 'Authorization' header sent */
auto provided = req.GetHeader ("Authorization");
if (provided.length () > 0)
{
if (provided.length () > 0)
{
bool result = false;
std::string expected = user + ":" + pass;
size_t b64_sz = i2p::data::Base64EncodingBufferSize(expected.length()) + 1;
char * b64_creds = new char[b64_sz];
@@ -797,7 +840,7 @@ namespace http {
} else if (req.uri.find("cmd=") != std::string::npos) {
HandleCommand (req, res, s);
} else {
ShowStatus (s);
ShowStatus (s, true);
res.add_header("Refresh", "10");
}
ShowPageTail (s);
@@ -809,7 +852,7 @@ namespace http {
std::map<uint32_t, uint32_t> HTTPConnection::m_Tokens;
void HTTPConnection::HandlePage (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{
{
std::map<std::string, std::string> params;
std::string page("");
URL url;
@@ -835,13 +878,13 @@ namespace http {
else
++it;
}
m_Tokens[token] = ts;
m_Tokens[token] = ts;
ShowCommands (s, token);
}
else if (page == HTTP_PAGE_TRANSIT_TUNNELS)
ShowTransitTunnels (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATIONS)
ShowLocalDestinations (s);
ShowLocalDestinations (s);
else if (page == HTTP_PAGE_LOCAL_DESTINATION)
ShowLocalDestination (s, params["b32"]);
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
@@ -859,7 +902,7 @@ namespace http {
ShowError(s, "Unknown page: " + page);
return;
}
}
}
void HTTPConnection::HandleCommand (const HTTPReq& req, HTTPRes& res, std::stringstream& s)
{
@@ -876,7 +919,7 @@ namespace http {
return;
}
std::string cmd = params["cmd"];
std::string cmd = params["cmd"];
if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
i2p::transport::transports.PeerTest ();
else if (cmd == HTTP_COMMAND_RELOAD_CONFIG)
@@ -889,17 +932,25 @@ namespace http {
i2p::context.SetAcceptsTunnels (false);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 10*60;
#endif
#ifdef WIN32_APP
#elif defined(WIN32_APP)
i2p::win32::GracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL) {
i2p::context.SetAcceptsTunnels (true);
#if (!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID))
Daemon.gracefulShutdownInterval = 0;
#elif defined(WIN32_APP)
i2p::win32::StopGracefulShutdown ();
#endif
} else if (cmd == HTTP_COMMAND_SHUTDOWN_NOW) {
#ifndef WIN32_APP
Daemon.running = false;
#else
i2p::win32::StopWin32App ();
#endif
} else if (cmd == HTTP_COMMAND_LOGLEVEL){
std::string level = params["level"];
SetLogLevel (level);
} else {
res.code = 400;
ShowError(s, "Unknown command: " + cmd);
@@ -942,8 +993,8 @@ namespace http {
if (needAuth && pass == "") {
uint8_t random[16];
char alnum[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
pass.resize(sizeof(random));
RAND_bytes(random, sizeof(random));
for (size_t i = 0; i < sizeof(random); i++) {
@@ -963,7 +1014,7 @@ namespace http {
m_IsRunning = false;
m_Acceptor.close();
m_Service.stop ();
if (m_Thread)
if (m_Thread)
{
m_Thread->join ();
m_Thread = nullptr;
@@ -981,7 +1032,7 @@ namespace http {
catch (std::exception& ex)
{
LogPrint (eLogError, "HTTPServer: runtime exception: ", ex.what ());
}
}
}
}
@@ -992,7 +1043,7 @@ namespace http {
boost::asio::placeholders::error, newSocket));
}
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
{
if (ecode)
@@ -1000,7 +1051,7 @@ namespace http {
if(newSocket) newSocket->close();
LogPrint(eLogError, "HTTP Server: error handling accept ", ecode.message());
if(ecode != boost::asio::error::operation_aborted)
Accept();
Accept();
return;
}
CreateConnection(newSocket);

View File

@@ -7,6 +7,7 @@
#include <map>
#include <thread>
#include <boost/asio.hpp>
#include <sstream>
#include "HTTP.h"
namespace i2p
@@ -75,6 +76,17 @@ namespace http
boost::asio::io_service::work m_Work;
boost::asio::ip::tcp::acceptor m_Acceptor;
};
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
void ShowStatus (std::stringstream& s, bool includeHiddenContent);
void ShowLocalDestinations (std::stringstream& s);
void ShowLeasesSets(std::stringstream& s);
void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32);
} // http
} // i2p

View File

@@ -512,10 +512,10 @@ namespace client
{
for (auto it = params.begin (); it != params.end (); it++)
{
if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
auto it1 = m_NetworkSettingHandlers.find (it->first);
if (it1 != m_NetworkSettingHandlers.end ()) {
if (it != params.begin ()) results << ",";
(this->*(it1->second))(it->second.data (), results);
} else
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);

View File

@@ -79,11 +79,14 @@ namespace transport
void UPnP::Discover ()
{
int nerror = 0;
#if MINIUPNPC_API_VERSION >= 14
int nerror = 0;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror);
#else
#elif ( MINIUPNPC_API_VERSION >= 8 || defined(UPNPDISCOVER_SUCCESS) )
int nerror = 0;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
#else
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0);
#endif
{
// notify satrting thread
@@ -155,7 +158,11 @@ namespace transport
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int r;
std::string strDesc; i2p::config::GetOption("upnp.name", strDesc);
#ifdef UPNPDISCOVER_SUCCESS
r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0");
#else
r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0);
#endif
if (r!=UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r);

12
debian/changelog vendored
View File

@@ -1,3 +1,15 @@
i2pd (2.17.0-1) unstable; urgency=low
* updated to version 2.17.0/0.9.32
-- orignal <orignal@i2pmail.org> Mon, 4 Dec 2017 18:00:00 +0000
i2pd (2.16.0-1) unstable; urgency=low
* updated to version 2.16.0/0.9.32
-- orignal <orignal@i2pmail.org> Mon, 13 Nov 2017 18:00:00 +0000
i2pd (2.15.0-1) unstable; urgency=low
* updated to version 2.15.0/0.9.31

4
debian/control vendored
View File

@@ -2,7 +2,7 @@ Source: i2pd
Section: net
Priority: optional
Maintainer: R4SAS <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor
Standards-Version: 3.9.6
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
@@ -12,7 +12,7 @@ Package: i2pd
Architecture: any
Pre-Depends: adduser
Depends: ${shlibs:Depends}, ${misc:Depends}
Suggests: tor, privoxy
Suggests: tor, privoxy, apparmor
Description: A full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants

1
debian/i2pd.install vendored
View File

@@ -3,3 +3,4 @@ contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/
contrib/subscriptions.txt etc/i2pd/
contrib/certificates/ usr/share/i2pd/
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d

1
debian/rules vendored
View File

@@ -12,6 +12,7 @@ PREFIX=/usr
%:
dh $@ --parallel
dh_apparmor --profile-name=usr.sbin.i2pd -pi2pd
override_dh_strip:
dh_strip --dbg-package=i2pd-dbg

View File

@@ -38,6 +38,7 @@ namespace config {
("log", value<std::string>()->default_value(""), "Logs destination: stdout, file, syslog (stdout if not set)")
("logfile", value<std::string>()->default_value(""), "Path to logfile (stdout if not set, autodetect if daemon)")
("loglevel", value<std::string>()->default_value("info"), "Set the minimal level of log messages (debug, info, warn, error)")
("logclftime", value<bool>()->default_value(false), "Write full CLF-formatted date and time to log (default: write only time)")
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
@@ -70,6 +71,8 @@ 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 probabalistic 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)")
;
options_description httpserver("HTTP Server options");
@@ -176,6 +179,7 @@ namespace config {
("reseed.floodfill", value<std::string>()->default_value(""), "Path to router info of floodfill to reseed from")
("reseed.file", value<std::string>()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from")
("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from")
("reseed.proxy", value<std::string>()->default_value(""), "url for reseed proxy, supports http/socks")
("reseed.urls", value<std::string>()->default_value(
"https://reseed.i2p-projekt.de/,"
"https://i2p.mooo.com/netDb/,"
@@ -189,7 +193,8 @@ namespace config {
"https://reseed.memcpy.io/,"
"https://reseed.onion.im/,"
"https://itoopie.atomike.ninja/,"
"https://i2pseed.creativecowpat.net:8443/"
"https://i2pseed.creativecowpat.net:8443/,"
"https://i2p.novg.net/"
), "Reseed URLs, separated by comma")
;

View File

@@ -14,20 +14,20 @@
namespace i2p
{
namespace crypto
{
{
const uint8_t elgp_[256]=
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
@@ -36,7 +36,7 @@ namespace crypto
};
const int elgg_ = 2;
const uint8_t dsap_[128]=
{
0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c,
@@ -45,7 +45,7 @@ namespace crypto
0x76, 0x55, 0xc4, 0x96, 0x4a, 0xfa, 0xa2, 0xb3, 0x37, 0xe9, 0x6a, 0xd3, 0x16, 0xb9, 0xfb, 0x1c,
0xc5, 0x64, 0xb5, 0xae, 0xc5, 0xb6, 0x9a, 0x9f, 0xf6, 0xc3, 0xe4, 0x54, 0x87, 0x07, 0xfe, 0xf8,
0x50, 0x3d, 0x91, 0xdd, 0x86, 0x02, 0xe8, 0x67, 0xe6, 0xd3, 0x5d, 0x22, 0x35, 0xc1, 0x86, 0x9c,
0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11,
0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11,
0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93
};
@@ -63,27 +63,27 @@ namespace crypto
0x3c, 0x43, 0x1f, 0x46, 0x98, 0x59, 0x9d, 0xda, 0x02, 0x45, 0x18, 0x24, 0xff, 0x36, 0x97, 0x52,
0x59, 0x36, 0x47, 0xcc, 0x3d, 0xdc, 0x19, 0x7d, 0xe9, 0x85, 0xe4, 0x3d, 0x13, 0x6c, 0xdc, 0xfc,
0x6b, 0xd5, 0x40, 0x9c, 0xd2, 0xf4, 0x50, 0x82, 0x11, 0x42, 0xa5, 0xe6, 0xf8, 0xeb, 0x1c, 0x3a,
0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c,
0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82
0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c,
0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82
};
const int rsae_ = 65537;
const int rsae_ = 65537;
struct CryptoConstants
{
// DH/ElGamal
BIGNUM * elgp;
BIGNUM * elgg;
BIGNUM * elgg;
// DSA
BIGNUM * dsap;
BIGNUM * dsap;
BIGNUM * dsaq;
BIGNUM * dsag;
// RSA
BIGNUM * rsae;
CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_,
CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_,
const uint8_t * dsaq_, const uint8_t * dsag_, int rsae_)
{
elgp = BN_new ();
@@ -99,18 +99,18 @@ namespace crypto
rsae = BN_new ();
BN_set_word (rsae, rsae_);
}
~CryptoConstants ()
{
BN_free (elgp); BN_free (elgg); BN_free (dsap); BN_free (dsaq); BN_free (dsag); BN_free (rsae);
}
};
}
};
static const CryptoConstants& GetCryptoConstants ()
{
static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_);
static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_);
return cryptoConstants;
}
}
bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len)
{
@@ -119,34 +119,34 @@ namespace crypto
BN_bn2bin (bn, buf + offset);
memset (buf, 0, offset);
return true;
}
}
// RSA
#define rsae GetCryptoConstants ().rsae
#define rsae GetCryptoConstants ().rsae
const BIGNUM * GetRSAE ()
{
return rsae;
}
}
// DSA
#define dsap GetCryptoConstants ().dsap
#define dsap GetCryptoConstants ().dsap
#define dsaq GetCryptoConstants ().dsaq
#define dsag GetCryptoConstants ().dsag
#define dsag GetCryptoConstants ().dsag
DSA * CreateDSA ()
{
DSA * dsa = DSA_new ();
DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag));
DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag));
DSA_set0_key (dsa, NULL, NULL);
return dsa;
}
// DH/ElGamal
// DH/ElGamal
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;
#define elgp GetCryptoConstants ().elgp
#define elgg GetCryptoConstants ().elgg
@@ -156,14 +156,14 @@ namespace crypto
if (len <= 0) return;
BN_CTX * ctx = BN_CTX_new ();
g_MontCtx = BN_MONT_CTX_new ();
BN_MONT_CTX_set (g_MontCtx, elgp, ctx);
BN_MONT_CTX_set (g_MontCtx, elgp, ctx);
auto montCtx = BN_MONT_CTX_new ();
BN_MONT_CTX_copy (montCtx, g_MontCtx);
for (int i = 0; i < len; i++)
{
table[i][0] = BN_new ();
if (!i)
BN_to_montgomery (table[0][0], elgg, montCtx, ctx);
if (!i)
BN_to_montgomery (table[0][0], elgg, montCtx, ctx);
else
BN_mod_mul_montgomery (table[i][0], table[i-1][254], table[i-1][0], montCtx, ctx);
for (int j = 1; j < 255; j++)
@@ -174,7 +174,7 @@ namespace crypto
}
BN_MONT_CTX_free (montCtx);
BN_CTX_free (ctx);
}
}
static void DestroyElggTable (BIGNUM * table[][255], int len)
{
@@ -186,9 +186,9 @@ namespace crypto
}
BN_MONT_CTX_free (g_MontCtx);
}
static BIGNUM * ElggPow (const uint8_t * exp, int len, BIGNUM * table[][255], BN_CTX * ctx)
// exp is in Big Endian
// exp is in Big Endian
{
if (len <= 0) return nullptr;
auto montCtx = BN_MONT_CTX_new ();
@@ -200,15 +200,15 @@ namespace crypto
{
if (exp[i])
BN_mod_mul_montgomery (res, res, table[len-1-i][exp[i]-1], montCtx, ctx);
}
else if (exp[i])
}
else if (exp[i])
res = BN_dup (table[len-i-1][exp[i]-1]);
}
}
if (res)
BN_from_montgomery (res, res, montCtx, ctx);
BN_MONT_CTX_free (montCtx);
return res;
}
}
static BIGNUM * ElggPow (const BIGNUM * exp, BIGNUM * table[][255], BN_CTX * ctx)
{
@@ -218,64 +218,64 @@ namespace crypto
auto ret = ElggPow (buf, len, table, ctx);
delete[] buf;
return ret;
}
}
static BIGNUM * (* g_ElggTable)[255] = nullptr;
static BIGNUM * (* g_ElggTable)[255] = nullptr;
// DH
DHKeys::DHKeys ()
{
m_DH = DH_new ();
DH_set0_pqg (m_DH, BN_dup (elgp), NULL, BN_dup (elgg));
DH_set0_key (m_DH, NULL, NULL);
}
DHKeys::~DHKeys ()
{
DH_free (m_DH);
}
}
void DHKeys::GenerateKeys ()
{
BIGNUM * priv_key = NULL, * pub_key = NULL;
#if !defined(__x86_64__) // use short exponent for non x64
BIGNUM * priv_key = NULL, * pub_key = NULL;
#if !defined(__x86_64__) // use short exponent for non x64
priv_key = BN_new ();
BN_rand (priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1);
#endif
#endif
if (g_ElggTable)
{
{
#if defined(__x86_64__)
priv_key = BN_new ();
BN_rand (priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1);
#endif
#endif
auto ctx = BN_CTX_new ();
pub_key = ElggPow (priv_key, g_ElggTable, ctx);
DH_set0_key (m_DH, pub_key, priv_key);
BN_CTX_free (ctx);
}
}
else
{
DH_set0_key (m_DH, NULL, priv_key);
DH_generate_key (m_DH);
DH_get0_key (m_DH, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key);
}
}
bn2buf (pub_key, m_PublicKey, 256);
}
}
void DHKeys::Agree (const uint8_t * pub, uint8_t * shared)
{
BIGNUM * pk = BN_bin2bn (pub, 256, NULL);
DH_compute_key (shared, pk, m_DH);
BN_free (pk);
}
}
// ElGamal
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
{
BN_CTX_start (ctx);
// everything, but a, because a might come from table
// everything, but a, because a might come from table
BIGNUM * k = BN_CTX_get (ctx);
BIGNUM * y = BN_CTX_get (ctx);
BIGNUM * b1 = BN_CTX_get (ctx);
@@ -285,13 +285,13 @@ namespace crypto
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
#else
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
#endif
#endif
// calculate a
BIGNUM * a;
BIGNUM * a;
if (g_ElggTable)
a = ElggPow (k, g_ElggTable, ctx);
else
{
{
a = BN_new ();
BN_mod_exp (a, elgg, k, elgp, ctx);
}
@@ -315,17 +315,17 @@ namespace crypto
bn2buf (a, encrypted + 1, 256);
encrypted[257] = 0;
bn2buf (b, encrypted + 258, 256);
}
}
else
{
bn2buf (a, encrypted, 256);
bn2buf (b, encrypted + 256, 256);
}
}
BN_free (a);
BN_CTX_end (ctx);
}
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted,
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted,
uint8_t * data, BN_CTX * ctx, bool zeroPadding)
{
BN_CTX_start (ctx);
@@ -334,11 +334,11 @@ namespace crypto
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);
// m = b*(a^x mod p) mod p
// m = b*(a^x mod p) mod p
BN_mod_exp (x, a, x, elgp, ctx);
BN_mod_mul (b, b, x, elgp, ctx);
BN_mod_mul (b, b, x, elgp, ctx);
uint8_t m[255];
bn2buf (b, m, 255);
bn2buf (b, m, 255);
BN_CTX_end (ctx);
uint8_t hash[32];
SHA256 (m + 33, 222, hash);
@@ -346,14 +346,14 @@ namespace crypto
{
LogPrint (eLogError, "ElGamal decrypt hash doesn't match");
return false;
}
}
memcpy (data, m + 33, 222);
return true;
}
}
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
{
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
RAND_bytes (priv, 256);
#else
// lower 226 bits (28 bytes and 2 bits) only. short exponent
@@ -364,27 +364,130 @@ namespace crypto
priv[numZeroBytes] &= 0x03;
#endif
BN_CTX * ctx = BN_CTX_new ();
BIGNUM * p = BN_new ();
BIGNUM * p = BN_new ();
BN_bin2bn (priv, 256, p);
BN_mod_exp (p, elgg, p, elgp, ctx);
bn2buf (p, pub, 256);
bn2buf (p, pub, 256);
BN_free (p);
BN_CTX_free (ctx);
}
// ECIES
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
{
BN_CTX_start (ctx);
BIGNUM * q = BN_CTX_get (ctx);
EC_GROUP_get_order(curve, q, ctx);
int len = BN_num_bytes (q);
BIGNUM * k = BN_CTX_get (ctx);
BN_rand_range (k, q); // 0 < k < q
// point for shared secret
auto p = EC_POINT_new (curve);
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);
encrypted[0] = 0;
bn2buf (x, encrypted + 1, len);
bn2buf (y, encrypted + 1 + len, len);
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
// ecryption key and iv
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
uint8_t keyBuf[64], iv[64], shared[32];
bn2buf (x, keyBuf, len);
bn2buf (y, iv, len);
SHA256 (keyBuf, len, shared);
// create buffer
uint8_t m[256];
m[0] = 0xFF; m[255] = 0xFF;
memcpy (m+33, data, 222);
SHA256 (m+33, 222, m+1);
// encrypt
encrypted[257] = 0;
CBCEncryption encryption;
encryption.SetKey (shared);
encryption.SetIV (iv);
encryption.Encrypt (m, 256, encrypted + 258);
EC_POINT_free (p);
BN_CTX_end (ctx);
}
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
{
bool ret = true;
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);
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))
{
auto s = EC_POINT_new (curve);
EC_POINT_mul (curve, s, nullptr, p, key, ctx);
EC_POINT_get_affine_coordinates_GFp (curve, s, x, y, nullptr);
EC_POINT_free (s);
uint8_t keyBuf[64], iv[64], shared[32];
bn2buf (x, keyBuf, len);
bn2buf (y, iv, len);
SHA256 (keyBuf, len, shared);
// decrypt
uint8_t m[256];
CBCDecryption decryption;
decryption.SetKey (shared);
decryption.SetIV (iv);
decryption.Decrypt (encrypted + 258, 256, m);
// verify and copy
uint8_t hash[32];
SHA256 (m + 33, 222, hash);
if (!memcmp (m + 1, hash, 32))
memcpy (data, m + 33, 222);
else
{
LogPrint (eLogError, "ECIES decrypt hash doesn't match");
ret = false;
}
}
else
{
LogPrint (eLogError, "ECIES decrypt point is invalid");
ret = false;
}
EC_POINT_free (p);
BN_CTX_end (ctx);
return ret;
}
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub)
{
BN_CTX * ctx = BN_CTX_new ();
BIGNUM * q = BN_new ();
EC_GROUP_get_order(curve, q, ctx);
priv = BN_new ();
BN_rand_range (priv, q);
pub = EC_POINT_new (curve);
EC_POINT_mul (curve, pub, priv, nullptr, nullptr, ctx);
BN_free (q);
BN_CTX_free (ctx);
}
// HMAC
const uint64_t IPAD = 0x3636363636363636;
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
#if defined(__AVX__)
#if defined(__AVX__)
static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD };
static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD };
#endif
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
// key is 32 bytes
// digest is 16 bytes
// block size is 64 bytes
// block size is 64 bytes
{
uint64_t buf[256];
uint64_t hash[12]; // 96 bytes
@@ -395,53 +498,53 @@ namespace crypto
"vmovups %[ipad], %%ymm1 \n"
"vmovups %%ymm1, 32(%[buf]) \n"
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
"vmovups %%ymm1, (%[buf]) \n"
"vmovups %%ymm1, (%[buf]) \n"
"vmovups %[opad], %%ymm1 \n"
"vmovups %%ymm1, 32(%[hash]) \n"
"vmovups %%ymm1, 32(%[hash]) \n"
"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
"vmovups %%ymm1, (%[hash]) \n"
"vzeroall \n" // end of AVX
"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
:
"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
:
: [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads),
[buf]"r"(buf), [hash]"r"(hash)
[buf]"r"(buf), [hash]"r"(hash)
: "memory", "%xmm0" // TODO: change to %ymm0 later
);
#else
// ikeypad
buf[0] = key.GetLL ()[0] ^ IPAD;
buf[1] = key.GetLL ()[1] ^ IPAD;
buf[2] = key.GetLL ()[2] ^ IPAD;
buf[3] = key.GetLL ()[3] ^ IPAD;
buf[0] = key.GetLL ()[0] ^ IPAD;
buf[1] = key.GetLL ()[1] ^ IPAD;
buf[2] = key.GetLL ()[2] ^ IPAD;
buf[3] = key.GetLL ()[3] ^ IPAD;
buf[4] = IPAD;
buf[5] = IPAD;
buf[6] = IPAD;
buf[7] = IPAD;
// okeypad
hash[0] = key.GetLL ()[0] ^ OPAD;
hash[1] = key.GetLL ()[1] ^ OPAD;
hash[2] = key.GetLL ()[2] ^ OPAD;
hash[3] = key.GetLL ()[3] ^ OPAD;
// okeypad
hash[0] = key.GetLL ()[0] ^ OPAD;
hash[1] = key.GetLL ()[1] ^ OPAD;
hash[2] = key.GetLL ()[2] ^ OPAD;
hash[3] = key.GetLL ()[3] ^ OPAD;
hash[4] = OPAD;
hash[5] = OPAD;
hash[6] = OPAD;
hash[7] = OPAD;
// fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
memset (hash + 10, 0, 16);
memset (hash + 10, 0, 16);
#endif
// concatenate with msg
memcpy (buf + 8, msg, len);
// calculate first hash
MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes
MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes
// calculate digest
MD5((uint8_t *)hash, 96, digest);
}
// AES
#ifdef AESNI
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
"movaps %%xmm1, %%xmm4 \n" \
@@ -463,7 +566,7 @@ namespace crypto
"pslldq $4, %%xmm4 \n" \
"pxor %%xmm4, %%xmm3 \n" \
"pxor %%xmm2, %%xmm3 \n" \
"movaps %%xmm3, "#round1"(%[sched]) \n"
"movaps %%xmm3, "#round1"(%[sched]) \n"
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{
@@ -488,7 +591,7 @@ namespace crypto
"aeskeygenassist $64, %%xmm3, %%xmm2 \n"
// key expansion final
"pshufd $0xff, %%xmm2, %%xmm2 \n"
"movaps %%xmm1, %%xmm4 \n"
"movaps %%xmm1, %%xmm4 \n"
"pslldq $4, %%xmm4 \n"
"pxor %%xmm4, %%xmm1 \n"
"pslldq $4, %%xmm4 \n"
@@ -519,17 +622,17 @@ namespace crypto
"aesenc 192(%["#sched"]), %%xmm0 \n" \
"aesenc 208(%["#sched"]), %%xmm0 \n" \
"aesenclast 224(%["#sched"]), %%xmm0 \n"
void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
}
}
#define DecryptAES256(sched) \
"pxor 224(%["#sched"]), %%xmm0 \n" \
@@ -547,22 +650,22 @@ namespace crypto
"aesdec 32(%["#sched"]), %%xmm0 \n" \
"aesdec 16(%["#sched"]), %%xmm0 \n" \
"aesdeclast (%["#sched"]), %%xmm0 \n"
void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
);
}
#define CallAESIMC(offset) \
"movaps "#offset"(%[shed]), %%xmm0 \n" \
"aesimc %%xmm0, %%xmm0 \n" \
"movaps %%xmm0, "#offset"(%[shed]) \n"
"movaps %%xmm0, "#offset"(%[shed]) \n"
void ECBDecryptionAESNI::SetKey (const AESKey& key)
{
@@ -587,7 +690,7 @@ namespace crypto
);
}
#endif
#endif
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
@@ -595,31 +698,31 @@ namespace crypto
#ifdef AESNI
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
#else
);
#else
for (int i = 0; i < numBlocks; i++)
{
*m_LastBlock.GetChipherBlock () ^= in[i];
m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
out[i] = *m_LastBlock.GetChipherBlock ();
}
#endif
#endif
}
void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
@@ -627,7 +730,7 @@ namespace crypto
// len/16
int numBlocks = len >> 4;
if (numBlocks > 0)
Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
}
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
@@ -637,17 +740,17 @@ namespace crypto
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
);
#else
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
#endif
}
@@ -657,23 +760,23 @@ namespace crypto
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
);
#else
for (int i = 0; i < numBlocks; i++)
{
@@ -689,7 +792,7 @@ namespace crypto
{
int numBlocks = len >> 4;
if (numBlocks > 0)
Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
}
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
@@ -698,18 +801,18 @@ namespace crypto
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
#else
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
#endif
}
@@ -718,7 +821,7 @@ namespace crypto
#ifdef AESNI
__asm__
(
// encrypt IV
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
@@ -728,16 +831,16 @@ namespace crypto
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()),
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
@@ -754,7 +857,7 @@ namespace crypto
#ifdef AESNI
__asm__
(
// decrypt IV
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
@@ -764,27 +867,27 @@ namespace crypto
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
#else
m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
m_LayerDecryption.SetIV (out);
m_LayerDecryption.SetIV (out);
m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
#endif
}
}
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
static void OpensslLockingCallback(int mode, int type, const char * file, int line)
@@ -795,45 +898,44 @@ namespace crypto
m_OpenSSLMutexes[type]->lock ();
else
m_OpenSSLMutexes[type]->unlock ();
}
}
}*/
void InitCrypto (bool precomputation)
{
SSL_library_init ();
/* auto numLocks = CRYPTO_num_locks();
for (int i = 0; i < numLocks; i++)
m_OpenSSLMutexes.emplace_back (new std::mutex);
m_OpenSSLMutexes.emplace_back (new std::mutex);
CRYPTO_set_locking_callback (OpensslLockingCallback);*/
if (precomputation)
{
{
#if defined(__x86_64__)
g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
#else
#else
g_ElggTable = new BIGNUM * [ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255];
PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES);
#endif
}
#endif
}
}
void TerminateCrypto ()
{
if (g_ElggTable)
{
{
DestroyElggTable (g_ElggTable,
#if defined(__x86_64__)
#if defined(__x86_64__)
ELGAMAL_FULL_EXPONENT_NUM_BYTES
#else
ELGAMAL_SHORT_EXPONENT_NUM_BYTES
#endif
);
ELGAMAL_SHORT_EXPONENT_NUM_BYTES
#endif
);
delete[] g_ElggTable; g_ElggTable = nullptr;
}
}
/* CRYPTO_set_locking_callback (nullptr);
m_OpenSSLMutexes.clear ();*/
}
}
}
}

View File

@@ -52,6 +52,11 @@ namespace crypto
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
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); // 222 bytes data, 514 bytes encrypted
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
// HMAC
typedef i2p::data::Tag<32> MACKey;
void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest);

151
libi2pd/CryptoKey.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include <string.h>
#include "Log.h"
#include "Gost.h"
#include "CryptoKey.h"
namespace i2p
{
namespace crypto
{
ElGamalEncryptor::ElGamalEncryptor (const uint8_t * pub)
{
memcpy (m_PublicKey, pub, 256);
}
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
{
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, true);
}
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
{
memcpy (m_PrivateKey, priv, 256);
}
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
{
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, true);
}
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
{
m_Curve = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
m_PublicKey = EC_POINT_new (m_Curve);
BIGNUM * x = BN_bin2bn (pub, 32, nullptr);
BIGNUM * y = BN_bin2bn (pub + 32, 32, nullptr);
if (!EC_POINT_set_affine_coordinates_GFp (m_Curve, m_PublicKey, x, y, nullptr))
LogPrint (eLogError, "ECICS P256 invalid public key");
BN_free (x); BN_free (y);
}
ECIESP256Encryptor::~ECIESP256Encryptor ()
{
if (m_Curve) EC_GROUP_free (m_Curve);
if (m_PublicKey) EC_POINT_free (m_PublicKey);
}
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
{
if (m_Curve && m_PublicKey)
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx);
}
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
{
m_Curve = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
m_PrivateKey = BN_bin2bn (priv, 32, nullptr);
}
ECIESP256Decryptor::~ECIESP256Decryptor ()
{
if (m_Curve) EC_GROUP_free (m_Curve);
if (m_PrivateKey) BN_free (m_PrivateKey);
}
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
{
if (m_Curve && m_PrivateKey)
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx);
return false;
}
void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub)
{
EC_GROUP * curve = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
EC_POINT * p = nullptr;
BIGNUM * key = nullptr;
GenerateECIESKeyPair (curve, key, p);
bn2buf (key, priv, 32);
RAND_bytes (priv + 32, 224);
BN_free (key);
BIGNUM * x = BN_new (), * y = BN_new ();
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, NULL);
bn2buf (x, pub, 32);
bn2buf (y, pub + 32, 32);
RAND_bytes (pub + 64, 192);
EC_POINT_free (p);
BN_free (x); BN_free (y);
EC_GROUP_free (curve);
}
ECIESGOSTR3410Encryptor::ECIESGOSTR3410Encryptor (const uint8_t * pub)
{
auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA);
m_PublicKey = EC_POINT_new (curve->GetGroup ());
BIGNUM * x = BN_bin2bn (pub, 32, nullptr);
BIGNUM * y = BN_bin2bn (pub + 32, 32, nullptr);
if (!EC_POINT_set_affine_coordinates_GFp (curve->GetGroup (), m_PublicKey, x, y, nullptr))
LogPrint (eLogError, "ECICS GOST R 34.10 invalid public key");
BN_free (x); BN_free (y);
}
ECIESGOSTR3410Encryptor::~ECIESGOSTR3410Encryptor ()
{
if (m_PublicKey) EC_POINT_free (m_PublicKey);
}
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
{
if (m_PublicKey)
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx);
}
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
{
m_PrivateKey = BN_bin2bn (priv, 32, nullptr);
}
ECIESGOSTR3410Decryptor::~ECIESGOSTR3410Decryptor ()
{
if (m_PrivateKey) BN_free (m_PrivateKey);
}
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
{
if (m_PrivateKey)
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx);
return false;
}
void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub)
{
auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA);
EC_POINT * p = nullptr;
BIGNUM * key = nullptr;
GenerateECIESKeyPair (curve->GetGroup (), key, p);
bn2buf (key, priv, 32);
RAND_bytes (priv + 32, 224);
BN_free (key);
BIGNUM * x = BN_new (), * y = BN_new ();
EC_POINT_get_affine_coordinates_GFp (curve->GetGroup (), p, x, y, NULL);
bn2buf (x, pub, 32);
bn2buf (y, pub + 32, 32);
RAND_bytes (pub + 64, 192);
EC_POINT_free (p);
BN_free (x); BN_free (y);
}
}
}

119
libi2pd/CryptoKey.h Normal file
View File

@@ -0,0 +1,119 @@
#ifndef CRYPTO_KEY_H__
#define CRYPTO_KEY_H__
#include <inttypes.h>
#include "Crypto.h"
namespace i2p
{
namespace crypto
{
class CryptoKeyEncryptor
{
public:
virtual ~CryptoKeyEncryptor () {};
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted
};
class CryptoKeyDecryptor
{
public:
virtual ~CryptoKeyDecryptor () {};
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) = 0; // 512 bytes encrypted, 222 bytes data
};
// ElGamal
class ElGamalEncryptor: public CryptoKeyEncryptor // for destination
{
public:
ElGamalEncryptor (const uint8_t * pub);
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
private:
uint8_t m_PublicKey[256];
};
class ElGamalDecryptor: public CryptoKeyDecryptor // for destination
{
public:
ElGamalDecryptor (const uint8_t * priv);
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
private:
uint8_t m_PrivateKey[256];
};
// ECIES P256
class ECIESP256Encryptor: public CryptoKeyEncryptor
{
public:
ECIESP256Encryptor (const uint8_t * pub);
~ECIESP256Encryptor ();
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
private:
EC_GROUP * m_Curve;
EC_POINT * m_PublicKey;
};
class ECIESP256Decryptor: public CryptoKeyDecryptor
{
public:
ECIESP256Decryptor (const uint8_t * priv);
~ECIESP256Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
private:
EC_GROUP * m_Curve;
BIGNUM * m_PrivateKey;
};
void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub);
// ECIES GOST R 34.10
class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor
{
public:
ECIESGOSTR3410Encryptor (const uint8_t * pub);
~ECIESGOSTR3410Encryptor ();
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
private:
EC_POINT * m_PublicKey;
};
class ECIESGOSTR3410Decryptor: public CryptoKeyDecryptor
{
public:
ECIESGOSTR3410Decryptor (const uint8_t * priv);
~ECIESGOSTR3410Decryptor ();
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
private:
BIGNUM * m_PrivateKey;
};
void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub);
}
}
#endif

View File

@@ -1,5 +1,6 @@
#include <algorithm>
#include <cassert>
#include <string>
#include "Crypto.h"
#include "Log.h"
#include "FS.h"
@@ -13,8 +14,8 @@ namespace i2p
namespace client
{
LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params):
m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service)
{
int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
@@ -23,8 +24,10 @@ namespace client
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
int numTags = DEFAULT_TAGS_TO_SEND;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
try {
if (params) {
try
{
if (params)
{
auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH);
if (it != params->end ())
inLen = std::stoi(it->second);
@@ -55,8 +58,12 @@ namespace client
LogPrint (eLogInfo, "Destination: Added to explicit peers list: ", b64);
}
}
it = params->find (I2CP_PARAM_INBOUND_NICKNAME);
if (it != params->end ()) m_Nickname = it->second; // otherwise we set deafult nickname in Start when we know local address
}
} catch (std::exception & ex) {
}
catch (std::exception & ex)
{
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
}
SetNumTags (numTags);
@@ -83,77 +90,79 @@ namespace client
LeaseSetDestination::~LeaseSetDestination ()
{
if (m_IsRunning)
if (m_IsRunning)
Stop ();
if (m_Pool)
i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool);
for (auto& it: m_LeaseSetRequests)
it.second->Complete (nullptr);
}
}
void LeaseSetDestination::Run ()
{
while (m_IsRunning)
{
try
{
{
m_Service.run ();
}
catch (std::exception& ex)
{
LogPrint (eLogError, "Destination: runtime exception: ", ex.what ());
}
}
}
}
}
}
bool LeaseSetDestination::Start ()
{
{
if (!m_IsRunning)
{
{
if (m_Nickname.empty ())
m_Nickname = i2p::data::GetIdentHashAbbreviation (GetIdentHash ()); // set default nickname
LoadTags ();
m_IsRunning = true;
m_Pool->SetLocalDestination (shared_from_this ());
m_Pool->SetActive (true);
m_Pool->SetActive (true);
m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT));
m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
shared_from_this (), std::placeholders::_1));
shared_from_this (), std::placeholders::_1));
m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ()));
return true;
}
}
else
return false;
}
bool LeaseSetDestination::Stop ()
{
{
if (m_IsRunning)
{
{
m_CleanupTimer.cancel ();
m_PublishConfirmationTimer.cancel ();
m_PublishVerificationTimer.cancel ();
m_PublishVerificationTimer.cancel ();
m_IsRunning = false;
if (m_Pool)
{
{
m_Pool->SetLocalDestination (nullptr);
i2p::tunnel::tunnels.StopTunnelPool (m_Pool);
}
}
m_Service.stop ();
if (m_Thread)
{
m_Thread->join ();
{
m_Thread->join ();
delete m_Thread;
m_Thread = 0;
}
}
SaveTags ();
CleanUp (); // GarlicDestination
return true;
}
}
else
return false;
}
}
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
{
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
@@ -164,7 +173,7 @@ namespace client
remoteLS = it->second;
}
if (remoteLS)
if (remoteLS)
{
if (!remoteLS->IsExpired ())
{
@@ -193,9 +202,9 @@ namespace client
m_RemoteLeaseSets.erase (ident);
return nullptr;
}
}
}
else
{
{
auto ls = i2p::data::netdb.FindLeaseSet (ident);
if (ls && !ls->IsExpired ())
{
@@ -203,7 +212,7 @@ namespace client
std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ident] = ls;
return ls;
}
}
}
return nullptr;
}
@@ -215,11 +224,11 @@ namespace client
UpdateLeaseSet ();
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
return m_LeaseSet;
}
}
void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet)
{
{
{
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
m_LeaseSet.reset (newLeaseSet);
}
@@ -229,21 +238,21 @@ namespace client
m_PublishVerificationTimer.cancel ();
Publish ();
}
}
}
void LeaseSetDestination::UpdateLeaseSet ()
{
int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum
int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels
if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum
CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels));
}
}
bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag)
{
struct
{
uint8_t k[32], t[32];
} data;
} data;
memcpy (data.k, key, 32);
memcpy (data.t, tag, 32);
auto s = shared_from_this ();
@@ -256,42 +265,42 @@ namespace client
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
}
void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
{
m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg));
}
void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET];
switch (typeID)
{
{
case eI2NPData:
HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break;
case eI2NPDeliveryStatus:
// we assume tunnel tests non-encrypted
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
break;
HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
break;
case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break;
case eI2NPDatabaseSearchReply:
HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET));
break;
break;
default:
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
}
}
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
}
}
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
{
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
size_t offset = DATABASE_STORE_HEADER_SIZE;
if (replyToken)
if (replyToken)
{
LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore");
offset += 36;
@@ -307,8 +316,8 @@ namespace client
{
leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
{
leaseSet->Update (buf + offset, len - offset);
{
leaseSet->Update (buf + offset, len - offset);
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
else
@@ -322,7 +331,7 @@ namespace client
LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
}
else
{
{
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset);
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
{
@@ -339,18 +348,18 @@ namespace client
LogPrint (eLogError, "Destination: New remote LeaseSet failed");
leaseSet = nullptr;
}
}
}
}
}
else
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ())
{
it1->second->requestTimeoutTimer.cancel ();
if (it1->second) it1->second->Complete (leaseSet);
m_LeaseSetRequests.erase (it1);
}
}
}
void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len)
@@ -364,7 +373,7 @@ namespace client
auto request = it->second;
bool found = false;
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
{
{
for (int i = 0; i < num; i++)
{
i2p::data::IdentHash peerHash (buf + 33 + i*32);
@@ -372,28 +381,28 @@ namespace client
{
LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message
i2p::data::netdb.RequestDestination (peerHash);
}
}
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
if (floodfill)
{
LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
if (SendLeaseSetRequest (key, floodfill, request))
found = true;
}
}
}
}
if (!found)
{
{
LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
request->Complete (nullptr);
m_LeaseSetRequests.erase (key);
}
}
else
}
}
else
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
}
}
void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
{
uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET);
@@ -405,20 +414,20 @@ namespace client
// schedule verification
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1));
shared_from_this (), std::placeholders::_1));
}
else
i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg);
}
}
void LeaseSetDestination::SetLeaseSetUpdated ()
{
{
UpdateLeaseSet ();
}
void LeaseSetDestination::Publish ()
{
if (!m_LeaseSet || !m_Pool)
{
if (!m_LeaseSet || !m_Pool)
{
LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet");
return;
@@ -435,9 +444,9 @@ namespace client
m_PublishDelayTimer.cancel ();
m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL));
m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer,
shared_from_this (), std::placeholders::_1));
shared_from_this (), std::placeholders::_1));
return;
}
}
auto outbound = m_Pool->GetNextOutboundTunnel ();
if (!outbound)
{
@@ -450,33 +459,46 @@ namespace client
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
return;
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
if (!floodfill)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
m_ExcludedFloodfills.clear ();
return;
}
}
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound));
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound));
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
m_LastSubmissionTime = ts;
}
void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
{
{
if (m_PublishReplyToken)
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
m_PublishReplyToken = 0;
Publish ();
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
Publish ();
}
else
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
// Java floodfill never sends confirmantion back for unknown crypto type
// assume it successive and try to verify
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer,
shared_from_this (), std::placeholders::_1));
}
}
}
}
@@ -484,25 +506,25 @@ namespace client
void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
{
{
auto s = shared_from_this ();
RequestLeaseSet (GetIdentHash (),
RequestLeaseSet (GetIdentHash (),
// "this" added due to bug in gcc 4.7-4.8
[s,this](std::shared_ptr<i2p::data::LeaseSet> leaseSet)
{
if (leaseSet)
if (leaseSet)
{
if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet)
{
// we got latest LeasetSet
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", 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));
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
return;
}
}
else
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32());
}
}
else
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32());
// we have to publish again
@@ -515,16 +537,16 @@ namespace client
{
if (ecode != boost::asio::error::operation_aborted)
Publish ();
}
}
bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
{
if (!m_Pool || !IsReady ())
{
if (requestComplete)
if (!m_Pool || !IsReady ())
{
if (requestComplete)
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
return false;
}
}
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
return true;
}
@@ -536,14 +558,14 @@ namespace client
{
auto it = s->m_LeaseSetRequests.find (dest);
if (it != s->m_LeaseSetRequests.end ())
{
auto requestComplete = it->second;
{
auto requestComplete = it->second;
s->m_LeaseSetRequests.erase (it);
if (notify && requestComplete) requestComplete->Complete (nullptr);
}
});
}
});
}
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
{
std::set<i2p::data::IdentHash> excluded;
@@ -564,28 +586,28 @@ namespace client
m_LeaseSetRequests.erase (ret.first);
if (requestComplete) requestComplete (nullptr);
}
}
}
else // duplicate
{
LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already");
if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT)
{
{
// something went wrong
m_LeaseSetRequests.erase (ret.first);
if (requestComplete) requestComplete (nullptr);
}
else if (requestComplete)
ret.first->second->requestComplete.push_back (requestComplete);
}
}
}
}
else
{
{
LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found");
if (requestComplete) requestComplete (nullptr);
}
}
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
}
}
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
{
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
@@ -594,36 +616,36 @@ namespace client
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
if (request->replyTunnel && request->outboundTunnel)
{
{
request->excluded.insert (nextFloodfill->GetIdentHash ());
request->requestTimeoutTimer.cancel ();
uint8_t replyKey[32], replyTag[32];
RAND_bytes (replyKey, 32); // random session key
RAND_bytes (replyKey, 32); // random session key
RAND_bytes (replyTag, 32); // random session tag
AddSessionKey (replyKey, replyTag);
auto msg = WrapMessage (nextFloodfill,
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded,
request->replyTunnel, replyKey, replyTag));
request->outboundTunnel->SendTunnelDataMsg (
{
i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeRouter,
nextFloodfill->GetIdentHash (), 0, msg
}
});
});
request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT));
request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer,
shared_from_this (), std::placeholders::_1, dest));
}
}
else
return false;
return true;
}
}
void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest)
{
@@ -641,26 +663,26 @@ namespace client
{
// reset tunnels, because one them might fail
it->second->outboundTunnel = nullptr;
it->second->replyTunnel = nullptr;
it->second->replyTunnel = nullptr;
done = !SendLeaseSetRequest (dest, floodfill, it->second);
}
else
done = true;
}
else
{
{
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
done = true;
}
if (done)
{
auto requestComplete = it->second;
auto requestComplete = it->second;
m_LeaseSetRequests.erase (it);
if (requestComplete) requestComplete->Complete (nullptr);
}
}
}
}
}
}
}
void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode)
@@ -674,7 +696,7 @@ namespace client
m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer,
shared_from_this (), std::placeholders::_1));
}
}
}
void LeaseSetDestination::CleanupRemoteLeaseSets ()
{
@@ -686,43 +708,53 @@ namespace client
{
LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired");
it = m_RemoteLeaseSets.erase (it);
}
else
}
else
++it;
}
}
}
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (isPublic, params),
m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0),
LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(GetService())
{
if (isPublic)
if (isPublic)
PersistTemporaryKeys ();
else
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (),
m_EncryptionPrivateKey, m_EncryptionPublicKey);
m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey);
if (isPublic)
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
}
ClientDestination::~ClientDestination ()
// extract streaming params
if (params)
{
auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY);
if (it != params->end ())
m_StreamingAckDelay = std::stoi(it->second);
}
}
ClientDestination::~ClientDestination ()
{
}
}
bool ClientDestination::Start ()
{
if (LeaseSetDestination::Start ())
{
{
m_StreamingDestination = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis ()); // TODO:
m_StreamingDestination->Start ();
m_StreamingDestination->Start ();
for (auto& it: m_StreamingDestinationsByPorts)
it.second->Start ();
return true;
}
}
else
return false;
}
}
bool ClientDestination::Stop ()
{
if (LeaseSetDestination::Stop ())
@@ -732,21 +764,21 @@ namespace client
//m_StreamingDestination->SetOwner (nullptr);
m_StreamingDestination = nullptr;
for (auto& it: m_StreamingDestinationsByPorts)
{
{
it.second->Stop ();
//it.second->SetOwner (nullptr);
}
m_StreamingDestinationsByPorts.clear ();
if (m_DatagramDestination)
{
{
delete m_DatagramDestination;
m_DatagramDestination = nullptr;
}
}
return true;
}
else
return false;
}
}
#ifdef I2LUA
void ClientDestination::Ready(ReadyPromise & p)
@@ -773,14 +805,14 @@ namespace client
ScheduleCheckForReady(p);
}
#endif
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
{
uint32_t length = bufbe32toh (buf);
buf += 4;
// we assume I2CP payload
uint16_t fromPort = bufbe16toh (buf + 4), // source
toPort = bufbe16toh (buf + 6); // destination
toPort = bufbe16toh (buf + 6); // destination
switch (buf[9])
{
case PROTOCOL_TYPE_STREAMING:
@@ -804,14 +836,14 @@ namespace client
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
{
if (!streamRequestComplete)
if (!streamRequestComplete)
{
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
return;
}
}
auto leaseSet = FindLeaseSet (dest);
if (leaseSet)
streamRequestComplete(CreateStream (leaseSet, port));
@@ -837,18 +869,18 @@ namespace client
return nullptr;
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
{
if (port)
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
{
if (port)
{
auto it = m_StreamingDestinationsByPorts.find (port);
if (it != m_StreamingDestinationsByPorts.end ())
return it->second;
}
}
// if port is zero or not found, use default destination
return m_StreamingDestination;
return m_StreamingDestination;
}
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
{
if (m_StreamingDestination)
@@ -860,35 +892,35 @@ namespace client
if (m_StreamingDestination)
m_StreamingDestination->ResetAcceptor ();
}
bool ClientDestination::IsAcceptingStreams () const
{
if (m_StreamingDestination)
return m_StreamingDestination->IsAcceptorSet ();
return false;
}
}
void ClientDestination::AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor)
{
if (m_StreamingDestination)
m_StreamingDestination->AcceptOnce (acceptor);
}
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
{
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
if (port)
m_StreamingDestinationsByPorts[port] = dest;
else // update default
else // update default
m_StreamingDestination = dest;
return dest;
}
}
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination ()
{
if (m_DatagramDestination == nullptr)
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ());
return m_DatagramDestination;
return m_DatagramDestination;
}
std::vector<std::shared_ptr<const i2p::stream::Stream> > ClientDestination::GetAllStreams () const
@@ -898,12 +930,12 @@ namespace client
{
for (auto& it: m_StreamingDestination->GetStreams ())
ret.push_back (it.second);
}
}
for (auto& it: m_StreamingDestinationsByPorts)
for (auto& it1: it.second->GetStreams ())
ret.push_back (it1.second);
return ret;
}
}
void ClientDestination::PersistTemporaryKeys ()
{
@@ -918,7 +950,8 @@ namespace client
}
LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p");
i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey);
i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (),
m_EncryptionPrivateKey, m_EncryptionPublicKey);
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
if (f1) {
@@ -927,7 +960,7 @@ namespace client
return;
}
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
}
}
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
{
@@ -935,12 +968,20 @@ namespace client
// sign
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO
SetLeaseSet (leaseSet);
}
}
void ClientDestination::CleanupDestination ()
{
if (m_DatagramDestination) m_DatagramDestination->CleanUp ();
}
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
{
if (m_Decryptor)
return m_Decryptor->Decrypt (encrypted, data, ctx);
else
LogPrint (eLogError, "Destinations: decryptor is not set");
return false;
}
}
}

View File

@@ -50,6 +50,7 @@ namespace client
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
const int DEFAULT_TAGS_TO_SEND = 40;
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
// latency
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
@@ -57,6 +58,10 @@ namespace client
const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max";
const int DEFAULT_MAX_TUNNEL_LATENCY = 0;
// streaming
const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay";
const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds
typedef std::function<void (std::shared_ptr<i2p::stream::Stream> stream)> StreamRequestComplete;
class LeaseSetDestination: public i2p::garlic::GarlicDestination,
@@ -86,6 +91,7 @@ namespace client
LeaseSetDestination (bool isPublic, const std::map<std::string, std::string> * params = nullptr);
~LeaseSetDestination ();
const std::string& GetNickname () const { return m_Nickname; };
virtual bool Start ();
virtual bool Stop ();
@@ -153,6 +159,7 @@ namespace client
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer;
std::string m_Nickname;
public:
@@ -196,13 +203,14 @@ namespace client
void StopAcceptingStreams ();
bool IsAcceptingStreams () const;
void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor);
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
// datagram
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
i2p::datagram::DatagramDestination * CreateDatagramDestination ();
// implements LocalDestination
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
protected:
@@ -225,7 +233,9 @@ namespace client
i2p::data::PrivateKeys m_Keys;
uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256];
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
int m_StreamingAckDelay;
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
i2p::datagram::DatagramDestination * m_DatagramDestination;

View File

@@ -189,7 +189,7 @@ namespace garlic
uint8_t iv[32]; // IV is first 16 bytes
SHA256(elGamal.preIV, 32, iv);
BN_CTX * ctx = BN_CTX_new ();
i2p::crypto::ElGamalEncrypt (m_Destination->GetEncryptionPublicKey (), (uint8_t *)&elGamal, buf, ctx, true);
m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx);
BN_CTX_free (ctx);
m_Encryption.SetIV (iv);
buf += 514;
@@ -454,7 +454,7 @@ namespace garlic
{
// tag not found. Use ElGamal
ElGamalBlock elGamal;
if (length >= 514 && i2p::crypto::ElGamalDecrypt (GetEncryptionPrivateKey (), buf, (uint8_t *)&elGamal, m_Ctx, true))
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx))
{
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
uint8_t iv[32]; // IV is first 16 bytes
@@ -512,12 +512,17 @@ namespace garlic
void GarlicDestination::HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
const uint8_t * buf1 = buf;
if (len < 1)
{
LogPrint (eLogError, "Garlic: payload is too short");
return;
}
int numCloves = buf[0];
LogPrint (eLogDebug, "Garlic: ", numCloves," cloves");
buf++;
buf++; len--;
for (int i = 0; i < numCloves; i++)
{
const uint8_t * buf1 = buf;
// delivery instructions
uint8_t flag = buf[0];
buf++; // flag
@@ -527,17 +532,29 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: clove encrypted");
buf += 32;
}
ptrdiff_t offset = buf - buf1;
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
switch (deliveryType)
{
case eGarlicDeliveryTypeLocal:
LogPrint (eLogDebug, "Garlic: type local");
HandleI2NPMessage (buf, len, from);
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
break;
}
HandleI2NPMessage (buf, len - offset, from);
break;
case eGarlicDeliveryTypeDestination:
LogPrint (eLogDebug, "Garlic: type destination");
buf += 32; // destination. check it later or for multiple destinations
HandleI2NPMessage (buf, len, from);
offset = buf1 - buf;
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
break;
}
HandleI2NPMessage (buf, len - offset, from);
break;
case eGarlicDeliveryTypeTunnel:
{
@@ -545,9 +562,15 @@ namespace garlic
// gwHash and gwTunnel sequence is reverted
uint8_t * gwHash = buf;
buf += 32;
offset = buf1 - buf;
if (offset + 4 > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
break;
}
uint32_t gwTunnel = bufbe32toh (buf);
buf += 4;
auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from);
buf += 4; offset += 4;
auto msg = CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset), from);
if (from) // received through an inbound tunnel
{
std::shared_ptr<i2p::tunnel::OutboundTunnel> tunnel;
@@ -568,9 +591,17 @@ namespace garlic
{
uint8_t * ident = buf;
buf += 32;
offset = buf1 - buf;
if (!from) // received directly
{
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
break;
}
i2p::transport::transports.SendMessage (ident,
CreateI2NPMessage (buf, GetI2NPMessageLength (buf)));
CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
}
else
LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported");
break;
@@ -578,15 +609,22 @@ namespace garlic
default:
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
}
buf += GetI2NPMessageLength (buf); // I2NP
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: message is too short");
break;
}
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
buf += 4; // CloveID
buf += 8; // Date
buf += 3; // Certificate
if (buf - buf1 > (int)len)
offset = buf1 - buf;
if (offset > (int)len)
{
LogPrint (eLogError, "Garlic: clove is too long");
break;
}
len -= offset;
}
}

View File

@@ -179,121 +179,595 @@ namespace crypto
// ГОСТ 34.11-2012
static const uint8_t sbox_[256] =
static const uint64_t T0[256] =
{
0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D,
0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1,
0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F,
0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F,
0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC,
0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87,
0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1,
0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57,
0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03,
0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A,
0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41,
0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B,
0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89,
0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61,
0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52,
0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6
0xE6F87E5C5B711FD0, 0x258377800924FA16, 0xC849E07E852EA4A8, 0x5B4686A18F06C16A,
0x0B32E9A2D77B416E, 0xABDA37A467815C66, 0xF61796A81A686676, 0xF5DC0B706391954B,
0x4862F38DB7E64BF1, 0xFF5C629A68BD85C5, 0xCB827DA6FCD75795, 0x66D36DAF69B9F089,
0x356C9F74483D83B0, 0x7CBCECB1238C99A1, 0x36A702AC31C4708D, 0x9EB6A8D02FBCDFD6,
0x8B19FA51E5B3AE37, 0x9CCFB5408A127D0B, 0xBC0C78B508208F5A, 0xE533E3842288ECED,
0xCEC2C7D377C15FD2, 0xEC7817B6505D0F5E, 0xB94CC2C08336871D, 0x8C205DB4CB0B04AD,
0x763C855B28A0892F, 0x588D1B79F6FF3257, 0x3FECF69E4311933E, 0x0FC0D39F803A18C9,
0xEE010A26F5F3AD83, 0x10EFE8F4411979A6, 0x5DCDA10C7DE93A10, 0x4A1BEE1D1248E92C,
0x53BFF2DB21847339, 0xB4F50CCFA6A23D09, 0x5FB4BC9CD84798CD, 0xE88A2D8B071C56F9,
0x7F7771695A756A9C, 0xC5F02E71A0BA1EBC, 0xA663F9AB4215E672, 0x2EB19E22DE5FBB78,
0x0DB9CE0F2594BA14, 0x82520E6397664D84, 0x2F031E6A0208EA98, 0x5C7F2144A1BE6BF0,
0x7A37CB1CD16362DB, 0x83E08E2B4B311C64, 0xCF70479BAB960E32, 0x856BA986B9DEE71E,
0xB5478C877AF56CE9, 0xB8FE42885F61D6FD, 0x1BDD0156966238C8, 0x622157923EF8A92E,
0xFC97FF42114476F8, 0x9D7D350856452CEB, 0x4C90C9B0E0A71256, 0x2308502DFBCB016C,
0x2D7A03FAA7A64845, 0xF46E8B38BFC6C4AB, 0xBDBEF8FDD477DEBA, 0x3AAC4CEBC8079B79,
0xF09CB105E8879D0C, 0x27FA6A10AC8A58CB, 0x8960E7C1401D0CEA, 0x1A6F811E4A356928,
0x90C4FB0773D196FF, 0x43501A2F609D0A9F, 0xF7A516E0C63F3796, 0x1CE4A6B3B8DA9252,
0x1324752C38E08A9B, 0xA5A864733BEC154F, 0x2BF124575549B33F, 0xD766DB15440DC5C7,
0xA7D179E39E42B792, 0xDADF151A61997FD3, 0x86A0345EC0271423, 0x38D5517B6DA939A4,
0x6518F077104003B4, 0x02791D90A5AEA2DD, 0x88D267899C4A5D0A, 0x930F66DF0A2865C2,
0x4EE9D4204509B08B, 0x325538916685292A, 0x412907BFC533A842, 0xB27E2B62544DC673,
0x6C5304456295E007, 0x5AF406E95351908A, 0x1F2F3B6BC123616F, 0xC37B09DC5255E5C6,
0x3967D133B1FE6844, 0x298839C7F0E711E2, 0x409B87F71964F9A2, 0xE938ADC3DB4B0719,
0x0C0B4E47F9C3EBF4, 0x5534D576D36B8843, 0x4610A05AEB8B02D8, 0x20C3CDF58232F251,
0x6DE1840DBEC2B1E7, 0xA0E8DE06B0FA1D08, 0x7B854B540D34333B, 0x42E29A67BCCA5B7F,
0xD8A6088AC437DD0E, 0xC63BB3A9D943ED81, 0x21714DBD5E65A3B1, 0x6761EDE7B5EEA169,
0x2431F7C8D573ABF6, 0xD51FC685E1A3671A, 0x5E063CD40410C92D, 0x283AB98F2CB04002,
0x8FEBC06CB2F2F790, 0x17D64F116FA1D33C, 0xE07359F1A99EE4AA, 0x784ED68C74CDC006,
0x6E2A19D5C73B42DA, 0x8712B4161C7045C3, 0x371582E4ED93216D, 0xACE390414939F6FC,
0x7EC5F12186223B7C, 0xC0B094042BAC16FB, 0xF9D745379A527EBF, 0x737C3F2EA3B68168,
0x33E7B8D9BAD278CA, 0xA9A32A34C22FFEBB, 0xE48163CCFEDFBD0D, 0x8E5940246EA5A670,
0x51C6EF4B842AD1E4, 0x22BAD065279C508C, 0xD91488C218608CEE, 0x319EA5491F7CDA17,
0xD394E128134C9C60, 0x094BF43272D5E3B3, 0x9BF612A5A4AAD791, 0xCCBBDA43D26FFD0F,
0x34DE1F3C946AD250, 0x4F5B5468995EE16B, 0xDF9FAF6FEA8F7794, 0x2648EA5870DD092B,
0xBFC7E56D71D97C67, 0xDDE6B2FF4F21D549, 0x3C276B463AE86003, 0x91767B4FAF86C71F,
0x68A13E7835D4B9A0, 0xB68C115F030C9FD4, 0x141DD2C916582001, 0x983D8F7DDD5324AC,
0x64AA703FCC175254, 0xC2C989948E02B426, 0x3E5E76D69F46C2DE, 0x50746F03587D8004,
0x45DB3D829272F1E5, 0x60584A029B560BF3, 0xFBAE58A73FFCDC62, 0xA15A5E4E6CAD4CE8,
0x4BA96E55CE1FB8CC, 0x08F9747AAE82B253, 0xC102144CF7FB471B, 0x9F042898F3EB8E36,
0x068B27ADF2EFFB7A, 0xEDCA97FE8C0A5EBE, 0x778E0513F4F7D8CF, 0x302C2501C32B8BF7,
0x8D92DDFC175C554D, 0xF865C57F46052F5F, 0xEAF3301BA2B2F424, 0xAA68B7ECBBD60D86,
0x998F0F350104754C, 0x0000000000000000, 0xF12E314D34D0CCEC, 0x710522BE061823B5,
0xAF280D9930C005C1, 0x97FD5CE25D693C65, 0x19A41CC633CC9A15, 0x95844172F8C79EB8,
0xDC5432B7937684A9, 0x9436C13A2490CF58, 0x802B13F332C8EF59, 0xC442AE397CED4F5C,
0xFA1CD8EFE3AB8D82, 0xF2E5AC954D293FD1, 0x6AD823E8907A1B7D, 0x4D2249F83CF043B6,
0x03CB9DD879F9F33D, 0xDE2D2F2736D82674, 0x2A43A41F891EE2DF, 0x6F98999D1B6C133A,
0xD4AD46CD3DF436FA, 0xBB35DF50269825C0, 0x964FDCAA813E6D85, 0xEB41B0537EE5A5C4,
0x0540BA758B160847, 0xA41AE43BE7BB44AF, 0xE3B8C429D0671797, 0x819993BBEE9FBEB9,
0xAE9A8DD1EC975421, 0xF3572CDD917E6E31, 0x6393D7DAE2AFF8CE, 0x47A2201237DC5338,
0xA32343DEC903EE35, 0x79FC56C4A89A91E6, 0x01B28048DC5751E0, 0x1296F564E4B7DB7B,
0x75F7188351597A12, 0xDB6D9552BDCE2E33, 0x1E9DBB231D74308F, 0x520D7293FDD322D9,
0xE20A44610C304677, 0xFEEEE2D2B4EAD425, 0xCA30FDEE20800675, 0x61EACA4A47015A13,
0xE74AFE1487264E30, 0x2CC883B27BF119A5, 0x1664CF59B3F682DC, 0xA811AA7C1E78AF5B,
0x1D5626FB648DC3B2, 0xB73E9117DF5BCE34, 0xD05F7CF06AB56F5D, 0xFD257F0ACD132718,
0x574DC8E676C52A9E, 0x0739A7E52EB8AA9A, 0x5486553E0F3CD9A3, 0x56FF48AEAA927B7E,
0xBE756525AD8E2D87, 0x7D0E6CF9FFDBC841, 0x3B1ECCA31450CA99, 0x6913BE30E983E840,
0xAD511009956EA71C, 0xB1B5B6BA2DB4354E, 0x4469BDCA4E25A005, 0x15AF5281CA0F71E1,
0x744598CB8D0E2BF2, 0x593F9B312AA863B7, 0xEFB38A6E29A4FC63, 0x6B6AA3A04C2D4A9D,
0x3D95EB0EE6BF31E3, 0xA291C3961554BFD5, 0x18169C8EEF9BCBF5, 0x115D68BC9D4E2846,
0xBA875F18FACF7420, 0xD1EDFCB8B6E23EBD, 0xB00736F2F1E364AE, 0x84D929CE6589B6FE,
0x70B7A2F6DA4F7255, 0x0E7253D75C6D4929, 0x04F23A3D574159A7, 0x0A8069EA0B2C108E,
0x49D073C56BB11A11, 0x8AAB7A1939E4FFD7, 0xCD095A0B0E38ACEF, 0xC9FB60365979F548,
0x92BDE697D67F3422, 0xC78933E10514BC61, 0xE1C1D9B975C9B54A, 0xD2266160CF1BCD80,
0x9A4492ED78FD8671, 0xB3CCAB2A881A9793, 0x72CEBF667FE1D088, 0xD6D45B5D985A9427
};
static const uint64_t T1[256] =
{
0xC811A8058C3F55DE, 0x65F5B43196B50619, 0xF74F96B1D6706E43, 0x859D1E8BCB43D336,
0x5AAB8A85CCFA3D84, 0xF9C7BF99C295FCFD, 0xA21FD5A1DE4B630F, 0xCDB3EF763B8B456D,
0x803F59F87CF7C385, 0xB27C73BE5F31913C, 0x98E3AC6633B04821, 0xBF61674C26B8F818,
0x0FFBC995C4C130C8, 0xAAA0862010761A98, 0x6057F342210116AA, 0xF63C760C0654CC35,
0x2DDB45CC667D9042, 0xBCF45A964BD40382, 0x68E8A0C3EF3C6F3D, 0xA7BD92D269FF73BC,
0x290AE20201ED2287, 0xB7DE34CDE885818F, 0xD901EEA7DD61059B, 0xD6FA273219A03553,
0xD56F1AE874CCCEC9, 0xEA31245C2E83F554, 0x7034555DA07BE499, 0xCE26D2AC56E7BEF7,
0xFD161857A5054E38, 0x6A0E7DA4527436D1, 0x5BD86A381CDE9FF2, 0xCAF7756231770C32,
0xB09AAED9E279C8D0, 0x5DEF1091C60674DB, 0x111046A2515E5045, 0x23536CE4729802FC,
0xC50CBCF7F5B63CFA, 0x73A16887CD171F03, 0x7D2941AFD9F28DBD, 0x3F5E3EB45A4F3B9D,
0x84EEFE361B677140, 0x3DB8E3D3E7076271, 0x1A3A28F9F20FD248, 0x7EBC7C75B49E7627,
0x74E5F293C7EB565C, 0x18DCF59E4F478BA4, 0x0C6EF44FA9ADCB52, 0xC699812D98DAC760,
0x788B06DC6E469D0E, 0xFC65F8EA7521EC4E, 0x30A5F7219E8E0B55, 0x2BEC3F65BCA57B6B,
0xDDD04969BAF1B75E, 0x99904CDBE394EA57, 0x14B201D1E6EA40F6, 0xBBB0C08241284ADD,
0x50F20463BF8F1DFF, 0xE8D7F93B93CBACB8, 0x4D8CB68E477C86E8, 0xC1DD1B3992268E3F,
0x7C5AA11209D62FCB, 0x2F3D98ABDB35C9AE, 0x671369562BFD5FF5, 0x15C1E16C36CEE280,
0x1D7EB2EDF8F39B17, 0xDA94D37DB00DFE01, 0x877BC3EC760B8ADA, 0xCB8495DFE153AE44,
0x05A24773B7B410B3, 0x12857B783C32ABDF, 0x8EB770D06812513B, 0x536739B9D2E3E665,
0x584D57E271B26468, 0xD789C78FC9849725, 0xA935BBFA7D1AE102, 0x8B1537A3DFA64188,
0xD0CD5D9BC378DE7A, 0x4AC82C9A4D80CFB7, 0x42777F1B83BDB620, 0x72D2883A1D33BD75,
0x5E7A2D4BAB6A8F41, 0xF4DAAB6BBB1C95D9, 0x905CFFE7FD8D31B6, 0x83AA6422119B381F,
0xC0AEFB8442022C49, 0xA0F908C663033AE3, 0xA428AF0804938826, 0xADE41C341A8A53C7,
0xAE7121EE77E6A85D, 0xC47F5C4A25929E8C, 0xB538E9AA55CDD863, 0x06377AA9DAD8EB29,
0xA18AE87BB3279895, 0x6EDFDA6A35E48414, 0x6B7D9D19825094A7, 0xD41CFA55A4E86CBF,
0xE5CAEDC9EA42C59C, 0xA36C351C0E6FC179, 0x5181E4DE6FABBF89, 0xFFF0C530184D17D4,
0x9D41EB1584045892, 0x1C0D525028D73961, 0xF178EC180CA8856A, 0x9A0571018EF811CD,
0x4091A27C3EF5EFCC, 0x19AF15239F6329D2, 0x347450EFF91EB990, 0xE11B4A078DD27759,
0xB9561DE5FC601331, 0x912F1F5A2DA993C0, 0x1654DCB65BA2191A, 0x3E2DDE098A6B99EB,
0x8A66D71E0F82E3FE, 0x8C51ADB7D55A08D7, 0x4533E50F8941FF7F, 0x02E6DD67BD4859EC,
0xE068AABA5DF6D52F, 0xC24826E3FF4A75A5, 0x6C39070D88ACDDF8, 0x6486548C4691A46F,
0xD1BEBD26135C7C0C, 0xB30F93038F15334A, 0x82D9849FC1BF9A69, 0x9C320BA85420FAE4,
0xFA528243AFF90767, 0x9ED4D6CFE968A308, 0xB825FD582C44B147, 0x9B7691BC5EDCB3BB,
0xC7EA619048FE6516, 0x1063A61F817AF233, 0x47D538683409A693, 0x63C2CE984C6DED30,
0x2A9FDFD86C81D91D, 0x7B1E3B06032A6694, 0x666089EBFBD9FD83, 0x0A598EE67375207B,
0x07449A140AFC495F, 0x2CA8A571B6593234, 0x1F986F8A45BBC2FB, 0x381AA4A050B372C2,
0x5423A3ADD81FAF3A, 0x17273C0B8B86BB6C, 0xFE83258DC869B5A2, 0x287902BFD1C980F1,
0xF5A94BD66B3837AF, 0x88800A79B2CABA12, 0x55504310083B0D4C, 0xDF36940E07B9EEB2,
0x04D1A7CE6790B2C5, 0x612413FFF125B4DC, 0x26F12B97C52C124F, 0x86082351A62F28AC,
0xEF93632F9937E5E7, 0x3507B052293A1BE6, 0xE72C30AE570A9C70, 0xD3586041AE1425E0,
0xDE4574B3D79D4CC4, 0x92BA228040C5685A, 0xF00B0CA5DC8C271C, 0xBE1287F1F69C5A6E,
0xF39E317FB1E0DC86, 0x495D114020EC342D, 0x699B407E3F18CD4B, 0xDCA3A9D46AD51528,
0x0D1D14F279896924, 0x0000000000000000, 0x593EB75FA196C61E, 0x2E4E78160B116BD8,
0x6D4AE7B058887F8E, 0xE65FD013872E3E06, 0x7A6DDBBBD30EC4E2, 0xAC97FC89CAAEF1B1,
0x09CCB33C1E19DBE1, 0x89F3EAC462EE1864, 0x7770CF49AA87ADC6, 0x56C57ECA6557F6D6,
0x03953DDA6D6CFB9A, 0x36928D884456E07C, 0x1EEB8F37959F608D, 0x31D6179C4EAAA923,
0x6FAC3AD7E5C02662, 0x43049FA653991456, 0xABD3669DC052B8EE, 0xAF02C153A7C20A2B,
0x3CCB036E3723C007, 0x93C9C23D90E1CA2C, 0xC33BC65E2F6ED7D3, 0x4CFF56339758249E,
0xB1E94E64325D6AA6, 0x37E16D359472420A, 0x79F8E661BE623F78, 0x5214D90402C74413,
0x482EF1FDF0C8965B, 0x13F69BC5EC1609A9, 0x0E88292814E592BE, 0x4E198B542A107D72,
0xCCC00FCBEBAFE71B, 0x1B49C844222B703E, 0x2564164DA840E9D5, 0x20C6513E1FF4F966,
0xBAC3203F910CE8AB, 0xF2EDD1C261C47EF0, 0x814CB945ACD361F3, 0x95FEB8944A392105,
0x5C9CF02C1622D6AD, 0x971865F3F77178E9, 0xBD87BA2B9BF0A1F4, 0x444005B259655D09,
0xED75BE48247FBC0B, 0x7596122E17CFF42A, 0xB44B091785E97A15, 0x966B854E2755DA9F,
0xEEE0839249134791, 0x32432A4623C652B9, 0xA8465B47AD3E4374, 0xF8B45F2412B15E8B,
0x2417F6F078644BA3, 0xFB2162FE7FDDA511, 0x4BBBCC279DA46DC1, 0x0173E0BDD024A276,
0x22208C59A2BCA08A, 0x8FC4906DB836F34D, 0xE4B90D743A6667EA, 0x7147B5E0705F46EF,
0x2782CB2A1508B039, 0xEC065EF5F45B1E7D, 0x21B5B183CFD05B10, 0xDBE733C060295C77,
0x9FA73672394C017E, 0xCF55321186C31C81, 0xD8720E1A0D45A7ED, 0x3B8F997A3DDF8958,
0x3AFC79C7EDFB2B2E, 0xE9A4198643EF0ECE, 0x5F09CDF67B4E2D37, 0x4F6A6BE9FA34DF04,
0xB6ADD47038A123F9, 0x8D224D0A057EAAA1, 0xC96248B85C1BF7A8, 0xE3FD9760309A2EB5,
0x0B2A6E5BA351820D, 0xEB42C4E1FEA75722, 0x948D58299A1D8373, 0x7FCF9CC864BAD451,
0xA55B4FB5D4B72A50, 0x08BF5381CE3D7997, 0x46A6D8D5E42D04E5, 0xD22B80FC7E308796,
0x57B69E77B57354A0, 0x3969441D8097D0B4, 0x3330CAFBF3E2F0CF, 0xE28E77DDE0BE8CC3,
0x62B12E259C494F46, 0xA6CE726FB9DBD1CA, 0x41E242C1EED14DBA, 0x76032FF47AA30FB0
};
static const uint64_t T2[256] =
{
0x45B268A93ACDE4CC, 0xAF7F0BE884549D08, 0x048354B3C1468263, 0x925435C2C80EFED2,
0xEE4E37F27FDFFBA7, 0x167A33920C60F14D, 0xFB123B52EA03E584, 0x4A0CAB53FDBB9007,
0x9DEAF6380F788A19, 0xCB48EC558F0CB32A, 0xB59DC4B2D6FEF7E0, 0xDCDBCA22F4F3ECB6,
0x11DF5813549A9C40, 0xE33FDEDF568ACED3, 0xA0C1C8124322E9C3, 0x07A56B8158FA6D0D,
0x77279579B1E1F3DD, 0xD9B18B74422AC004, 0xB8EC2D9FFFABC294, 0xF4ACF8A82D75914F,
0x7BBF69B1EF2B6878, 0xC4F62FAF487AC7E1, 0x76CE809CC67E5D0C, 0x6711D88F92E4C14C,
0x627B99D9243DEDFE, 0x234AA5C3DFB68B51, 0x909B1F15262DBF6D, 0x4F66EA054B62BCB5,
0x1AE2CF5A52AA6AE8, 0xBEA053FBD0CE0148, 0xED6808C0E66314C9, 0x43FE16CD15A82710,
0xCD049231A06970F6, 0xE7BC8A6C97CC4CB0, 0x337CE835FCB3B9C0, 0x65DEF2587CC780F3,
0x52214EDE4132BB50, 0x95F15E4390F493DF, 0x870839625DD2E0F1, 0x41313C1AFB8B66AF,
0x91720AF051B211BC, 0x477D427ED4EEA573, 0x2E3B4CEEF6E3BE25, 0x82627834EB0BCC43,
0x9C03E3DD78E724C8, 0x2877328AD9867DF9, 0x14B51945E243B0F2, 0x574B0F88F7EB97E2,
0x88B6FA989AA4943A, 0x19C4F068CB168586, 0x50EE6409AF11FAEF, 0x7DF317D5C04EABA4,
0x7A567C5498B4C6A9, 0xB6BBFB804F42188E, 0x3CC22BCF3BC5CD0B, 0xD04336EAAA397713,
0xF02FAC1BEC33132C, 0x2506DBA7F0D3488D, 0xD7E65D6BF2C31A1E, 0x5EB9B2161FF820F5,
0x842E0650C46E0F9F, 0x716BEB1D9E843001, 0xA933758CAB315ED4, 0x3FE414FDA2792265,
0x27C9F1701EF00932, 0x73A4C1CA70A771BE, 0x94184BA6E76B3D0E, 0x40D829FF8C14C87E,
0x0FBEC3FAC77674CB, 0x3616A9634A6A9572, 0x8F139119C25EF937, 0xF545ED4D5AEA3F9E,
0xE802499650BA387B, 0x6437E7BD0B582E22, 0xE6559F89E053E261, 0x80AD52E305288DFC,
0x6DC55A23E34B9935, 0xDE14E0F51AD0AD09, 0xC6390578A659865E, 0x96D7617109487CB1,
0xE2D6CB3A21156002, 0x01E915E5779FAED1, 0xADB0213F6A77DCB7, 0x9880B76EB9A1A6AB,
0x5D9F8D248644CF9B, 0xFD5E4536C5662658, 0xF1C6B9FE9BACBDFD, 0xEACD6341BE9979C4,
0xEFA7221708405576, 0x510771ECD88E543E, 0xC2BA51CB671F043D, 0x0AD482AC71AF5879,
0xFE787A045CDAC936, 0xB238AF338E049AED, 0xBD866CC94972EE26, 0x615DA6EBBD810290,
0x3295FDD08B2C1711, 0xF834046073BF0AEA, 0xF3099329758FFC42, 0x1CAEB13E7DCFA934,
0xBA2307481188832B, 0x24EFCE42874CE65C, 0x0E57D61FB0E9DA1A, 0xB3D1BAD6F99B343C,
0xC0757B1C893C4582, 0x2B510DB8403A9297, 0x5C7698C1F1DB614A, 0x3E0D0118D5E68CB4,
0xD60F488E855CB4CF, 0xAE961E0DF3CB33D9, 0x3A8E55AB14A00ED7, 0x42170328623789C1,
0x838B6DD19C946292, 0x895FEF7DED3B3AEB, 0xCFCBB8E64E4A3149, 0x064C7E642F65C3DC,
0x3D2B3E2A4C5A63DA, 0x5BD3F340A9210C47, 0xB474D157A1615931, 0xAC5934DA1DE87266,
0x6EE365117AF7765B, 0xC86ED36716B05C44, 0x9BA6885C201D49C5, 0xB905387A88346C45,
0x131072C4BAB9DDFF, 0xBF49461EA751AF99, 0xD52977BC1CE05BA1, 0xB0F785E46027DB52,
0x546D30BA6E57788C, 0x305AD707650F56AE, 0xC987C682612FF295, 0xA5AB8944F5FBC571,
0x7ED528E759F244CA, 0x8DDCBBCE2C7DB888, 0xAA154ABE328DB1BA, 0x1E619BE993ECE88B,
0x09F2BD9EE813B717, 0x7401AA4B285D1CB3, 0x21858F143195CAEE, 0x48C381841398D1B8,
0xFCB750D3B2F98889, 0x39A86A998D1CE1B9, 0x1F888E0CE473465A, 0x7899568376978716,
0x02CF2AD7EE2341BF, 0x85C713B5B3F1A14E, 0xFF916FE12B4567E7, 0x7C1A0230B7D10575,
0x0C98FCC85ECA9BA5, 0xA3E7F720DA9E06AD, 0x6A6031A2BBB1F438, 0x973E74947ED7D260,
0x2CF4663918C0FF9A, 0x5F50A7F368678E24, 0x34D983B4A449D4CD, 0x68AF1B755592B587,
0x7F3C3D022E6DEA1B, 0xABFC5F5B45121F6B, 0x0D71E92D29553574, 0xDFFDF5106D4F03D8,
0x081BA87B9F8C19C6, 0xDB7EA1A3AC0981BB, 0xBBCA12AD66172DFA, 0x79704366010829C7,
0x179326777BFF5F9C, 0x0000000000000000, 0xEB2476A4C906D715, 0x724DD42F0738DF6F,
0xB752EE6538DDB65F, 0x37FFBC863DF53BA3, 0x8EFA84FCB5C157E6, 0xE9EB5C73272596AA,
0x1B0BDABF2535C439, 0x86E12C872A4D4E20, 0x9969A28BCE3E087A, 0xFAFB2EB79D9C4B55,
0x056A4156B6D92CB2, 0x5A3AE6A5DEBEA296, 0x22A3B026A8292580, 0x53C85B3B36AD1581,
0xB11E900117B87583, 0xC51F3A4A3FE56930, 0xE019E1EDCF3621BD, 0xEC811D2591FCBA18,
0x445B7D4C4D524A1D, 0xA8DA6069DCAEF005, 0x58F5CC72309DE329, 0xD4C062596B7FF570,
0xCE22AD0339D59F98, 0x591CD99747024DF8, 0x8B90C5AA03187B54, 0xF663D27FC356D0F0,
0xD8589E9135B56ED5, 0x35309651D3D67A1C, 0x12F96721CD26732E, 0xD28C1C3D441A36AC,
0x492A946164077F69, 0x2D1D73DC6F5F514B, 0x6F0A70F40D68D88A, 0x60B4B30ECA1EAC41,
0xD36509D83385987D, 0x0B3D97490630F6A8, 0x9ECCC90A96C46577, 0xA20EE2C5AD01A87C,
0xE49AB55E0E70A3DE, 0xA4429CA182646BA0, 0xDA97B446DB962F6A, 0xCCED87D4D7F6DE27,
0x2AB8185D37A53C46, 0x9F25DCEFE15BCBA6, 0xC19C6EF9FEA3EB53, 0xA764A3931BD884CE,
0x2FD2590B817C10F4, 0x56A21A6D80743933, 0xE573A0BB79EF0D0F, 0x155C0CA095DC1E23,
0x6C2C4FC694D437E4, 0x10364DF623053291, 0xDD32DFC7836C4267, 0x03263F3299BCEF6E,
0x66F8CD6AE57B6F9D, 0x8C35AE2B5BE21659, 0x31B3C2E21290F87F, 0x93BD2027BF915003,
0x69460E90220D1B56, 0x299E276FAE19D328, 0x63928C3C53A2432F, 0x7082FEF8E91B9ED0,
0xBC6F792C3EED40F7, 0x4C40D537D2DE53DB, 0x75E8BFAE5FC2B262, 0x4DA9C0D2A541FD0A,
0x4E8FFFE03CFD1264, 0x2620E495696FA7E3, 0xE1F0F408B8A98F6C, 0xD1AA230FDDA6D9C2,
0xC7D0109DD1C6288F, 0x8A79D04F7487D585, 0x4694579BA3710BA2, 0x38417F7CFA834F68,
0x1D47A4DB0A5007E5, 0x206C9AF1460A643F, 0xA128DDF734BD4712, 0x8144470672B7232D,
0xF2E086CC02105293, 0x182DE58DBC892B57, 0xCAA1F9B0F8931DFB, 0x6B892447CC2E5AE9,
0xF9DD11850420A43B, 0x4BE5BEB68A243ED6, 0x5584255F19C8D65D, 0x3B67404E633FA006,
0xA68DB6766C472A1F, 0xF78AC79AB4C97E21, 0xC353442E1080AAEC, 0x9A4F9DB95782E714
};
static const uint64_t T3[256] =
{
0x05BA7BC82C9B3220, 0x31A54665F8B65E4F, 0xB1B651F77547F4D4, 0x8BFA0D857BA46682,
0x85A96C5AA16A98BB, 0x990FAEF908EB79C9, 0xA15E37A247F4A62D, 0x76857DCD5D27741E,
0xF8C50B800A1820BC, 0xBE65DCB201F7A2B4, 0x666D1B986F9426E7, 0x4CC921BF53C4E648,
0x95410A0F93D9CA42, 0x20CDCCAA647BA4EF, 0x429A4060890A1871, 0x0C4EA4F69B32B38B,
0xCCDA362DDE354CD3, 0x96DC23BC7C5B2FA9, 0xC309BB68AA851AB3, 0xD26131A73648E013,
0x021DC52941FC4DB2, 0xCD5ADAB7704BE48A, 0xA77965D984ED71E6, 0x32386FD61734BBA4,
0xE82D6DD538AB7245, 0x5C2147EA6177B4B1, 0x5DA1AB70CF091CE8, 0xAC907FCE72B8BDFF,
0x57C85DFD972278A8, 0xA4E44C6A6B6F940D, 0x3851995B4F1FDFE4, 0x62578CCAED71BC9E,
0xD9882BB0C01D2C0A, 0x917B9D5D113C503B, 0xA2C31E11A87643C6, 0xE463C923A399C1CE,
0xF71686C57EA876DC, 0x87B4A973E096D509, 0xAF0D567D9D3A5814, 0xB40C2A3F59DCC6F4,
0x3602F88495D121DD, 0xD3E1DD3D9836484A, 0xF945E71AA46688E5, 0x7518547EB2A591F5,
0x9366587450C01D89, 0x9EA81018658C065B, 0x4F54080CBC4603A3, 0x2D0384C65137BF3D,
0xDC325078EC861E2A, 0xEA30A8FC79573FF7, 0x214D2030CA050CB6, 0x65F0322B8016C30C,
0x69BE96DD1B247087, 0xDB95EE9981E161B8, 0xD1FC1814D9CA05F8, 0x820ED2BBCC0DE729,
0x63D76050430F14C7, 0x3BCCB0E8A09D3A0F, 0x8E40764D573F54A2, 0x39D175C1E16177BD,
0x12F5A37C734F1F4B, 0xAB37C12F1FDFC26D, 0x5648B167395CD0F1, 0x6C04ED1537BF42A7,
0xED97161D14304065, 0x7D6C67DAAB72B807, 0xEC17FA87BA4EE83C, 0xDFAF79CB0304FBC1,
0x733F060571BC463E, 0x78D61C1287E98A27, 0xD07CF48E77B4ADA1, 0xB9C262536C90DD26,
0xE2449B5860801605, 0x8FC09AD7F941FCFB, 0xFAD8CEA94BE46D0E, 0xA343F28B0608EB9F,
0x9B126BD04917347B, 0x9A92874AE7699C22, 0x1B017C42C4E69EE0, 0x3A4C5C720EE39256,
0x4B6E9F5E3EA399DA, 0x6BA353F45AD83D35, 0xE7FEE0904C1B2425, 0x22D009832587E95D,
0x842980C00F1430E2, 0xC6B3C0A0861E2893, 0x087433A419D729F2, 0x341F3DADD42D6C6F,
0xEE0A3FAEFBB2A58E, 0x4AEE73C490DD3183, 0xAAB72DB5B1A16A34, 0xA92A04065E238FDF,
0x7B4B35A1686B6FCC, 0x6A23BF6EF4A6956C, 0x191CB96B851AD352, 0x55D598D4D6DE351A,
0xC9604DE5F2AE7EF3, 0x1CA6C2A3A981E172, 0xDE2F9551AD7A5398, 0x3025AAFF56C8F616,
0x15521D9D1E2860D9, 0x506FE31CFA45073A, 0x189C55F12B647B0B, 0x0180EC9AAE7EA859,
0x7CEC8B40050C105E, 0x2350E5198BF94104, 0xEF8AD33455CC0DD7, 0x07A7BEE16D677F92,
0xE5E325B90DE76997, 0x5A061591A26E637A, 0xB611EF1618208B46, 0x09F4DF3EB7A981AB,
0x1EBB078AE87DACC0, 0xB791038CB65E231F, 0x0FD38D4574B05660, 0x67EDF702C1EA8EBE,
0xBA5F4BE0831238CD, 0xE3C477C2CEFEBE5C, 0x0DCE486C354C1BD2, 0x8C5DB36416C31910,
0x26EA9ED1A7627324, 0x039D29B3EF82E5EB, 0x9F28FC82CBF2AE02, 0xA8AAE89CF05D2786,
0x431AACFA2774B028, 0xCF471F9E31B7A938, 0x581BD0B8E3922EC8, 0xBC78199B400BEF06,
0x90FB71C7BF42F862, 0x1F3BEB1046030499, 0x683E7A47B55AD8DE, 0x988F4263A695D190,
0xD808C72A6E638453, 0x0627527BC319D7CB, 0xEBB04466D72997AE, 0xE67E0C0AE2658C7C,
0x14D2F107B056C880, 0x7122C32C30400B8C, 0x8A7AE11FD5DACEDB, 0xA0DEDB38E98A0E74,
0xAD109354DCC615A6, 0x0BE91A17F655CC19, 0x8DDD5FFEB8BDB149, 0xBFE53028AF890AED,
0xD65BA6F5B4AD7A6A, 0x7956F0882997227E, 0x10E8665532B352F9, 0x0E5361DFDACEFE39,
0xCEC7F3049FC90161, 0xFF62B561677F5F2E, 0x975CCF26D22587F0, 0x51EF0F86543BAF63,
0x2F1E41EF10CBF28F, 0x52722635BBB94A88, 0xAE8DBAE73344F04D, 0x410769D36688FD9A,
0xB3AB94DE34BBB966, 0x801317928DF1AA9B, 0xA564A0F0C5113C54, 0xF131D4BEBDB1A117,
0x7F71A2F3EA8EF5B5, 0x40878549C8F655C3, 0x7EF14E6944F05DEC, 0xD44663DCF55137D8,
0xF2ACFD0D523344FC, 0x0000000000000000, 0x5FBC6E598EF5515A, 0x16CF342EF1AA8532,
0xB036BD6DDB395C8D, 0x13754FE6DD31B712, 0xBBDFA77A2D6C9094, 0x89E7C8AC3A582B30,
0x3C6B0E09CDFA459D, 0xC4AE0589C7E26521, 0x49735A777F5FD468, 0xCAFD64561D2C9B18,
0xDA1502032F9FC9E1, 0x8867243694268369, 0x3782141E3BAF8984, 0x9CB5D53124704BE9,
0xD7DB4A6F1AD3D233, 0xA6F989432A93D9BF, 0x9D3539AB8A0EE3B0, 0x53F2CAAF15C7E2D1,
0x6E19283C76430F15, 0x3DEBE2936384EDC4, 0x5E3C82C3208BF903, 0x33B8834CB94A13FD,
0x6470DEB12E686B55, 0x359FD1377A53C436, 0x61CAA57902F35975, 0x043A975282E59A79,
0xFD7F70482683129C, 0xC52EE913699CCD78, 0x28B9FF0E7DAC8D1D, 0x5455744E78A09D43,
0xCB7D88CCB3523341, 0x44BD121B4A13CFBA, 0x4D49CD25FDBA4E11, 0x3E76CB208C06082F,
0x3FF627BA2278A076, 0xC28957F204FBB2EA, 0x453DFE81E46D67E3, 0x94C1E6953DA7621B,
0x2C83685CFF491764, 0xF32C1197FC4DECA5, 0x2B24D6BD922E68F6, 0xB22B78449AC5113F,
0x48F3B6EDD1217C31, 0x2E9EAD75BEB55AD6, 0x174FD8B45FD42D6B, 0x4ED4E4961238ABFA,
0x92E6B4EEFEBEB5D0, 0x46A0D7320BEF8208, 0x47203BA8A5912A51, 0x24F75BF8E69E3E96,
0xF0B1382413CF094E, 0xFEE259FBC901F777, 0x276A724B091CDB7D, 0xBDF8F501EE75475F,
0x599B3C224DEC8691, 0x6D84018F99C1EAFE, 0x7498B8E41CDB39AC, 0xE0595E71217C5BB7,
0x2AA43A273C50C0AF, 0xF50B43EC3F543B6E, 0x838E3E2162734F70, 0xC09492DB4507FF58,
0x72BFEA9FDFC2EE67, 0x11688ACF9CCDFAA0, 0x1A8190D86A9836B9, 0x7ACBD93BC615C795,
0xC7332C3A286080CA, 0x863445E94EE87D50, 0xF6966A5FD0D6DE85, 0xE9AD814F96D5DA1C,
0x70A22FB69E3EA3D5, 0x0A69F68D582B6440, 0xB8428EC9C2EE757F, 0x604A49E3AC8DF12C,
0x5B86F90B0C10CB23, 0xE1D9B2EB8F02F3EE, 0x29391394D3D22544, 0xC8E0A17F5CD0D6AA,
0xB58CC6A5F7A26EAD, 0x8193FB08238F02C2, 0xD5C68F465B2F9F81, 0xFCFF9CD288FDBAC5,
0x77059157F359DC47, 0x1D262E3907FF492B, 0xFB582233E59AC557, 0xDDB2BCE242F8B673,
0x2577B76248E096CF, 0x6F99C4A6D83DA74C, 0xC1147E41EB795701, 0xF48BAF76912A9337
};
static const uint64_t T4[256] =
{
0x3EF29D249B2C0A19, 0xE9E16322B6F8622F, 0x5536994047757F7A, 0x9F4D56D5A47B0B33,
0x822567466AA1174C, 0xB8F5057DEB082FB2, 0xCC48C10BF4475F53, 0x373088D4275DEC3A,
0x968F4325180AED10, 0x173D232CF7016151, 0xAE4ED09F946FCC13, 0xFD4B4741C4539873,
0x1B5B3F0DD9933765, 0x2FFCB0967B644052, 0xE02376D20A89840C, 0xA3AE3A70329B18D7,
0x419CBD2335DE8526, 0xFAFEBF115B7C3199, 0x0397074F85AA9B0D, 0xC58AD4FB4836B970,
0xBEC60BE3FC4104A8, 0x1EFF36DC4B708772, 0x131FDC33ED8453B6, 0x0844E33E341764D3,
0x0FF11B6EAB38CD39, 0x64351F0A7761B85A, 0x3B5694F509CFBA0E, 0x30857084B87245D0,
0x47AFB3BD2297AE3C, 0xF2BA5C2F6F6B554A, 0x74BDC4761F4F70E1, 0xCFDFC64471EDC45E,
0xE610784C1DC0AF16, 0x7ACA29D63C113F28, 0x2DED411776A859AF, 0xAC5F211E99A3D5EE,
0xD484F949A87EF33B, 0x3CE36CA596E013E4, 0xD120F0983A9D432C, 0x6BC40464DC597563,
0x69D5F5E5D1956C9E, 0x9AE95F043698BB24, 0xC9ECC8DA66A4EF44, 0xD69508C8A5B2EAC6,
0xC40C2235C0503B80, 0x38C193BA8C652103, 0x1CEEC75D46BC9E8F, 0xD331011937515AD1,
0xD8E2E56886ECA50F, 0xB137108D5779C991, 0x709F3B6905CA4206, 0x4FEB50831680CAEF,
0xEC456AF3241BD238, 0x58D673AFE181ABBE, 0x242F54E7CAD9BF8C, 0x0211F1810DCC19FD,
0x90BC4DBB0F43C60A, 0x9518446A9DA0761D, 0xA1BFCBF13F57012A, 0x2BDE4F8961E172B5,
0x27B853A84F732481, 0xB0B1E643DF1F4B61, 0x18CC38425C39AC68, 0xD2B7F7D7BF37D821,
0x3103864A3014C720, 0x14AA246372ABFA5C, 0x6E600DB54EBAC574, 0x394765740403A3F3,
0x09C215F0BC71E623, 0x2A58B947E987F045, 0x7B4CDF18B477BDD8, 0x9709B5EB906C6FE0,
0x73083C268060D90B, 0xFEDC400E41F9037E, 0x284948C6E44BE9B8, 0x728ECAE808065BFB,
0x06330E9E17492B1A, 0x5950856169E7294E, 0xBAE4F4FCE6C4364F, 0xCA7BCF95E30E7449,
0x7D7FD186A33E96C2, 0x52836110D85AD690, 0x4DFAA1021B4CD312, 0x913ABB75872544FA,
0xDD46ECB9140F1518, 0x3D659A6B1E869114, 0xC23F2CABD719109A, 0xD713FE062DD46836,
0xD0A60656B2FBC1DC, 0x221C5A79DD909496, 0xEFD26DBCA1B14935, 0x0E77EDA0235E4FC9,
0xCBFD395B6B68F6B9, 0x0DE0EAEFA6F4D4C4, 0x0422FF1F1A8532E7, 0xF969B85EDED6AA94,
0x7F6E2007AEF28F3F, 0x3AD0623B81A938FE, 0x6624EE8B7AADA1A7, 0xB682E8DDC856607B,
0xA78CC56F281E2A30, 0xC79B257A45FAA08D, 0x5B4174E0642B30B3, 0x5F638BFF7EAE0254,
0x4BC9AF9C0C05F808, 0xCE59308AF98B46AE, 0x8FC58DA9CC55C388, 0x803496C7676D0EB1,
0xF33CAAE1E70DD7BA, 0xBB6202326EA2B4BF, 0xD5020F87201871CB, 0x9D5CA754A9B712CE,
0x841669D87DE83C56, 0x8A6184785EB6739F, 0x420BBA6CB0741E2B, 0xF12D5B60EAC1CE47,
0x76AC35F71283691C, 0x2C6BB7D9FECEDB5F, 0xFCCDB18F4C351A83, 0x1F79C012C3160582,
0xF0ABADAE62A74CB7, 0xE1A5801C82EF06FC, 0x67A21845F2CB2357, 0x5114665F5DF04D9D,
0xBF40FD2D74278658, 0xA0393D3FB73183DA, 0x05A409D192E3B017, 0xA9FB28CF0B4065F9,
0x25A9A22942BF3D7C, 0xDB75E22703463E02, 0xB326E10C5AB5D06C, 0xE7968E8295A62DE6,
0xB973F3B3636EAD42, 0xDF571D3819C30CE5, 0xEE549B7229D7CBC5, 0x12992AFD65E2D146,
0xF8EF4E9056B02864, 0xB7041E134030E28B, 0xC02EDD2ADAD50967, 0x932B4AF48AE95D07,
0x6FE6FB7BC6DC4784, 0x239AACB755F61666, 0x401A4BEDBDB807D6, 0x485EA8D389AF6305,
0xA41BC220ADB4B13D, 0x753B32B89729F211, 0x997E584BB3322029, 0x1D683193CEDA1C7F,
0xFF5AB6C0C99F818E, 0x16BBD5E27F67E3A1, 0xA59D34EE25D233CD, 0x98F8AE853B54A2D9,
0x6DF70AFACB105E79, 0x795D2E99B9BBA425, 0x8E437B6744334178, 0x0186F6CE886682F0,
0xEBF092A3BB347BD2, 0xBCD7FA62F18D1D55, 0xADD9D7D011C5571E, 0x0BD3E471B1BDFFDE,
0xAA6C2F808EEAFEF4, 0x5EE57D31F6C880A4, 0xF50FA47FF044FCA0, 0x1ADDC9C351F5B595,
0xEA76646D3352F922, 0x0000000000000000, 0x85909F16F58EBEA6, 0x46294573AAF12CCC,
0x0A5512BF39DB7D2E, 0x78DBD85731DD26D5, 0x29CFBE086C2D6B48, 0x218B5D36583A0F9B,
0x152CD2ADFACD78AC, 0x83A39188E2C795BC, 0xC3B9DA655F7F926A, 0x9ECBA01B2C1D89C3,
0x07B5F8509F2FA9EA, 0x7EE8D6C926940DCF, 0x36B67E1AAF3B6ECA, 0x86079859702425AB,
0xFB7849DFD31AB369, 0x4C7C57CC932A51E2, 0xD96413A60E8A27FF, 0x263EA566C715A671,
0x6C71FC344376DC89, 0x4A4F595284637AF8, 0xDAF314E98B20BCF2, 0x572768C14AB96687,
0x1088DB7C682EC8BB, 0x887075F9537A6A62, 0x2E7A4658F302C2A2, 0x619116DBE582084D,
0xA87DDE018326E709, 0xDCC01A779C6997E8, 0xEDC39C3DAC7D50C8, 0xA60A33A1A078A8C0,
0xC1A82BE452B38B97, 0x3F746BEA134A88E9, 0xA228CCBEBAFD9A27, 0xABEAD94E068C7C04,
0xF48952B178227E50, 0x5CF48CB0FB049959, 0x6017E0156DE48ABD, 0x4438B4F2A73D3531,
0x8C528AE649FF5885, 0xB515EF924DFCFB76, 0x0C661C212E925634, 0xB493195CC59A7986,
0x9CDA519A21D1903E, 0x32948105B5BE5C2D, 0x194ACE8CD45F2E98, 0x438D4CA238129CDB,
0x9B6FA9CABEFE39D4, 0x81B26009EF0B8C41, 0xDED1EBF691A58E15, 0x4E6DA64D9EE6481F,
0x54B06F8ECF13FD8A, 0x49D85E1D01C9E1F5, 0xAFC826511C094EE3, 0xF698A33075EE67AD,
0x5AC7822EEC4DB243, 0x8DD47C28C199DA75, 0x89F68337DB1CE892, 0xCDCE37C57C21DDA3,
0x530597DE503C5460, 0x6A42F2AA543FF793, 0x5D727A7E73621BA9, 0xE232875307459DF1,
0x56A19E0FC2DFE477, 0xC61DD3B4CD9C227D, 0xE5877F03986A341B, 0x949EB2A415C6F4ED,
0x6206119460289340, 0x6380E75AE84E11B0, 0x8BE772B6D6D0F16F, 0x50929091D596CF6D,
0xE86795EC3E9EE0DF, 0x7CF927482B581432, 0xC86A3E14EEC26DB4, 0x7119CDA78DACC0F6,
0xE40189CD100CB6EB, 0x92ADBC3A028FDFF7, 0xB2A017C2D2D3529C, 0x200DABF8D05C8D6B,
0x34A78F9BA2F77737, 0xE3B4719D8F231F01, 0x45BE423C2F5BB7C1, 0xF71E55FEFD88E55D,
0x6853032B59F3EE6E, 0x65B3E9C4FF073AAA, 0x772AC3399AE5EBEC, 0x87816E97F842A75B,
0x110E2DB2E0484A4B, 0x331277CB3DD8DEDD, 0xBD510CAC79EB9FA5, 0x352179552A91F5C7
};
static const uint64_t T5[256] =
{
0x8AB0A96846E06A6D, 0x43C7E80B4BF0B33A, 0x08C9B3546B161EE5, 0x39F1C235EBA990BE,
0xC1BEF2376606C7B2, 0x2C209233614569AA, 0xEB01523B6FC3289A, 0x946953AB935ACEDD,
0x272838F63E13340E, 0x8B0455ECA12BA052, 0x77A1B2C4978FF8A2, 0xA55122CA13E54086,
0x2276135862D3F1CD, 0xDB8DDFDE08B76CFE, 0x5D1E12C89E4A178A, 0x0E56816B03969867,
0xEE5F79953303ED59, 0xAFED748BAB78D71D, 0x6D929F2DF93E53EE, 0xF5D8A8F8BA798C2A,
0xF619B1698E39CF6B, 0x95DDAF2F749104E2, 0xEC2A9C80E0886427, 0xCE5C8FD8825B95EA,
0xC4E0D9993AC60271, 0x4699C3A5173076F9, 0x3D1B151F50A29F42, 0x9ED505EA2BC75946,
0x34665ACFDC7F4B98, 0x61B1FB53292342F7, 0xC721C0080E864130, 0x8693CD1696FD7B74,
0x872731927136B14B, 0xD3446C8A63A1721B, 0x669A35E8A6680E4A, 0xCAB658F239509A16,
0xA4E5DE4EF42E8AB9, 0x37A7435EE83F08D9, 0x134E6239E26C7F96, 0x82791A3C2DF67488,
0x3F6EF00A8329163C, 0x8E5A7E42FDEB6591, 0x5CAAEE4C7981DDB5, 0x19F234785AF1E80D,
0x255DDDE3ED98BD70, 0x50898A32A99CCCAC, 0x28CA4519DA4E6656, 0xAE59880F4CB31D22,
0x0D9798FA37D6DB26, 0x32F968F0B4FFCD1A, 0xA00F09644F258545, 0xFA3AD5175E24DE72,
0xF46C547C5DB24615, 0x713E80FBFF0F7E20, 0x7843CF2B73D2AAFA, 0xBD17EA36AEDF62B4,
0xFD111BACD16F92CF, 0x4ABAA7DBC72D67E0, 0xB3416B5DAD49FAD3, 0xBCA316B24914A88B,
0x15D150068AECF914, 0xE27C1DEBE31EFC40, 0x4FE48C759BEDA223, 0x7EDCFD141B522C78,
0x4E5070F17C26681C, 0xE696CAC15815F3BC, 0x35D2A64B3BB481A7, 0x800CFF29FE7DFDF6,
0x1ED9FAC3D5BAA4B0, 0x6C2663A91EF599D1, 0x03C1199134404341, 0xF7AD4DED69F20554,
0xCD9D9649B61BD6AB, 0xC8C3BDE7EADB1368, 0xD131899FB02AFB65, 0x1D18E352E1FAE7F1,
0xDA39235AEF7CA6C1, 0xA1BBF5E0A8EE4F7A, 0x91377805CF9A0B1E, 0x3138716180BF8E5B,
0xD9F83ACBDB3CE580, 0x0275E515D38B897E, 0x472D3F21F0FBBCC6, 0x2D946EB7868EA395,
0xBA3C248D21942E09, 0xE7223645BFDE3983, 0xFF64FEB902E41BB1, 0xC97741630D10D957,
0xC3CB1722B58D4ECC, 0xA27AEC719CAE0C3B, 0x99FECB51A48C15FB, 0x1465AC826D27332B,
0xE1BD047AD75EBF01, 0x79F733AF941960C5, 0x672EC96C41A3C475, 0xC27FEBA6524684F3,
0x64EFD0FD75E38734, 0xED9E60040743AE18, 0xFB8E2993B9EF144D, 0x38453EB10C625A81,
0x6978480742355C12, 0x48CF42CE14A6EE9E, 0x1CAC1FD606312DCE, 0x7B82D6BA4792E9BB,
0x9D141C7B1F871A07, 0x5616B80DC11C4A2E, 0xB849C198F21FA777, 0x7CA91801C8D9A506,
0xB1348E487EC273AD, 0x41B20D1E987B3A44, 0x7460AB55A3CFBBE3, 0x84E628034576F20A,
0x1B87D16D897A6173, 0x0FE27DEFE45D5258, 0x83CDE6B8CA3DBEB7, 0x0C23647ED01D1119,
0x7A362A3EA0592384, 0xB61F40F3F1893F10, 0x75D457D1440471DC, 0x4558DA34237035B8,
0xDCA6116587FC2043, 0x8D9B67D3C9AB26D0, 0x2B0B5C88EE0E2517, 0x6FE77A382AB5DA90,
0x269CC472D9D8FE31, 0x63C41E46FAA8CB89, 0xB7ABBC771642F52F, 0x7D1DE4852F126F39,
0xA8C6BA3024339BA0, 0x600507D7CEE888C8, 0x8FEE82C61A20AFAE, 0x57A2448926D78011,
0xFCA5E72836A458F0, 0x072BCEBB8F4B4CBD, 0x497BBE4AF36D24A1, 0x3CAFE99BB769557D,
0x12FA9EBD05A7B5A9, 0xE8C04BAA5B836BDB, 0x4273148FAC3B7905, 0x908384812851C121,
0xE557D3506C55B0FD, 0x72FF996ACB4F3D61, 0x3EDA0C8E64E2DC03, 0xF0868356E6B949E9,
0x04EAD72ABB0B0FFC, 0x17A4B5135967706A, 0xE3C8E16F04D5367F, 0xF84F30028DAF570C,
0x1846C8FCBD3A2232, 0x5B8120F7F6CA9108, 0xD46FA231ECEA3EA6, 0x334D947453340725,
0x58403966C28AD249, 0xBED6F3A79A9F21F5, 0x68CCB483A5FE962D, 0xD085751B57E1315A,
0xFED0023DE52FD18E, 0x4B0E5B5F20E6ADDF, 0x1A332DE96EB1AB4C, 0xA3CE10F57B65C604,
0x108F7BA8D62C3CD7, 0xAB07A3A11073D8E1, 0x6B0DAD1291BED56C, 0xF2F366433532C097,
0x2E557726B2CEE0D4, 0x0000000000000000, 0xCB02A476DE9B5029, 0xE4E32FD48B9E7AC2,
0x734B65EE2C84F75E, 0x6E5386BCCD7E10AF, 0x01B4FC84E7CBCA3F, 0xCFE8735C65905FD5,
0x3613BFDA0FF4C2E6, 0x113B872C31E7F6E8, 0x2FE18BA255052AEB, 0xE974B72EBC48A1E4,
0x0ABC5641B89D979B, 0xB46AA5E62202B66E, 0x44EC26B0C4BBFF87, 0xA6903B5B27A503C7,
0x7F680190FC99E647, 0x97A84A3AA71A8D9C, 0xDD12EDE16037EA7C, 0xC554251DDD0DC84E,
0x88C54C7D956BE313, 0x4D91696048662B5D, 0xB08072CC9909B992, 0xB5DE5962C5C97C51,
0x81B803AD19B637C9, 0xB2F597D94A8230EC, 0x0B08AAC55F565DA4, 0xF1327FD2017283D6,
0xAD98919E78F35E63, 0x6AB9519676751F53, 0x24E921670A53774F, 0xB9FD3D1C15D46D48,
0x92F66194FBDA485F, 0x5A35DC7311015B37, 0xDED3F4705477A93D, 0xC00A0EB381CD0D8D,
0xBB88D809C65FE436, 0x16104997BEACBA55, 0x21B70AC95693B28C, 0x59F4C5E225411876,
0xD5DB5EB50B21F499, 0x55D7A19CF55C096F, 0xA97246B4C3F8519F, 0x8552D487A2BD3835,
0x54635D181297C350, 0x23C2EFDC85183BF2, 0x9F61F96ECC0C9379, 0x534893A39DDC8FED,
0x5EDF0B59AA0A54CB, 0xAC2C6D1A9F38945C, 0xD7AEBBA0D8AA7DE7, 0x2ABFA00C09C5EF28,
0xD84CC64F3CF72FBF, 0x2003F64DB15878B3, 0xA724C7DFC06EC9F8, 0x069F323F68808682,
0xCC296ACD51D01C94, 0x055E2BAE5CC0C5C3, 0x6270E2C21D6301B6, 0x3B842720382219C0,
0xD2F0900E846AB824, 0x52FC6F277A1745D2, 0xC6953C8CE94D8B0F, 0xE009F8FE3095753E,
0x655B2C7992284D0B, 0x984A37D54347DFC4, 0xEAB5AEBF8808E2A5, 0x9A3FD2C090CC56BA,
0x9CA0E0FFF84CD038, 0x4C2595E4AFADE162, 0xDF6708F4B3BC6302, 0xBF620F237D54EBCA,
0x93429D101C118260, 0x097D4FD08CDDD4DA, 0x8C2F9B572E60ECEF, 0x708A7C7F18C4B41F,
0x3A30DBA4DFE9D3FF, 0x4006F19A7FB0F07B, 0x5F6BF7DD4DC19EF4, 0x1F6D064732716E8F,
0xF9FBCC866A649D33, 0x308C8DE567744464, 0x8971B0F972A0292C, 0xD61A47243F61B7D8,
0xEFEB8511D4C82766, 0x961CB6BE40D147A3, 0xAAB35F25F7B812DE, 0x76154E407044329D,
0x513D76B64E570693, 0xF3479AC7D2F90AA8, 0x9B8B2E4477079C85, 0x297EB99D3D85AC69
};
static const uint64_t T6[256] =
{
0x7E37E62DFC7D40C3, 0x776F25A4EE939E5B, 0xE045C850DD8FB5AD, 0x86ED5BA711FF1952,
0xE91D0BD9CF616B35, 0x37E0AB256E408FFB, 0x9607F6C031025A7A, 0x0B02F5E116D23C9D,
0xF3D8486BFB50650C, 0x621CFF27C40875F5, 0x7D40CB71FA5FD34A, 0x6DAA6616DAA29062,
0x9F5F354923EC84E2, 0xEC847C3DC507C3B3, 0x025A3668043CE205, 0xA8BF9E6C4DAC0B19,
0xFA808BE2E9BEBB94, 0xB5B99C5277C74FA3, 0x78D9BC95F0397BCC, 0xE332E50CDBAD2624,
0xC74FCE129332797E, 0x1729ECEB2EA709AB, 0xC2D6B9F69954D1F8, 0x5D898CBFBAB8551A,
0x859A76FB17DD8ADB, 0x1BE85886362F7FB5, 0xF6413F8FF136CD8A, 0xD3110FA5BBB7E35C,
0x0A2FEED514CC4D11, 0xE83010EDCD7F1AB9, 0xA1E75DE55F42D581, 0xEEDE4A55C13B21B6,
0xF2F5535FF94E1480, 0x0CC1B46D1888761E, 0xBCE15FDB6529913B, 0x2D25E8975A7181C2,
0x71817F1CE2D7A554, 0x2E52C5CB5C53124B, 0xF9F7A6BEEF9C281D, 0x9E722E7D21F2F56E,
0xCE170D9B81DCA7E6, 0x0E9B82051CB4941B, 0x1E712F623C49D733, 0x21E45CFA42F9F7DC,
0xCB8E7A7F8BBA0F60, 0x8E98831A010FB646, 0x474CCF0D8E895B23, 0xA99285584FB27A95,
0x8CC2B57205335443, 0x42D5B8E984EFF3A5, 0x012D1B34021E718C, 0x57A6626AAE74180B,
0xFF19FC06E3D81312, 0x35BA9D4D6A7C6DFE, 0xC9D44C178F86ED65, 0x506523E6A02E5288,
0x03772D5C06229389, 0x8B01F4FE0B691EC0, 0xF8DABD8AED825991, 0x4C4E3AEC985B67BE,
0xB10DF0827FBF96A9, 0x6A69279AD4F8DAE1, 0xE78689DCD3D5FF2E, 0x812E1A2B1FA553D1,
0xFBAD90D6EBA0CA18, 0x1AC543B234310E39, 0x1604F7DF2CB97827, 0xA6241C6951189F02,
0x753513CCEAAF7C5E, 0x64F2A59FC84C4EFA, 0x247D2B1E489F5F5A, 0xDB64D718AB474C48,
0x79F4A7A1F2270A40, 0x1573DA832A9BEBAE, 0x3497867968621C72, 0x514838D2A2302304,
0xF0AF6537FD72F685, 0x1D06023E3A6B44BA, 0x678588C3CE6EDD73, 0x66A893F7CC70ACFF,
0xD4D24E29B5EDA9DF, 0x3856321470EA6A6C, 0x07C3418C0E5A4A83, 0x2BCBB22F5635BACD,
0x04B46CD00878D90A, 0x06EE5AB80C443B0F, 0x3B211F4876C8F9E5, 0x0958C38912EEDE98,
0xD14B39CDBF8B0159, 0x397B292072F41BE0, 0x87C0409313E168DE, 0xAD26E98847CAA39F,
0x4E140C849C6785BB, 0xD5FF551DB7F3D853, 0xA0CA46D15D5CA40D, 0xCD6020C787FE346F,
0x84B76DCF15C3FB57, 0xDEFDA0FCA121E4CE, 0x4B8D7B6096012D3D, 0x9AC642AD298A2C64,
0x0875D8BD10F0AF14, 0xB357C6EA7B8374AC, 0x4D6321D89A451632, 0xEDA96709C719B23F,
0xF76C24BBF328BC06, 0xC662D526912C08F2, 0x3CE25EC47892B366, 0xB978283F6F4F39BD,
0xC08C8F9E9D6833FD, 0x4F3917B09E79F437, 0x593DE06FB2C08C10, 0xD6887841B1D14BDA,
0x19B26EEE32139DB0, 0xB494876675D93E2F, 0x825937771987C058, 0x90E9AC783D466175,
0xF1827E03FF6C8709, 0x945DC0A8353EB87F, 0x4516F9658AB5B926, 0x3F9573987EB020EF,
0xB855330B6D514831, 0x2AE6A91B542BCB41, 0x6331E413C6160479, 0x408F8E8180D311A0,
0xEFF35161C325503A, 0xD06622F9BD9570D5, 0x8876D9A20D4B8D49, 0xA5533135573A0C8B,
0xE168D364DF91C421, 0xF41B09E7F50A2F8F, 0x12B09B0F24C1A12D, 0xDA49CC2CA9593DC4,
0x1F5C34563E57A6BF, 0x54D14F36A8568B82, 0xAF7CDFE043F6419A, 0xEA6A2685C943F8BC,
0xE5DCBFB4D7E91D2B, 0xB27ADDDE799D0520, 0x6B443CAED6E6AB6D, 0x7BAE91C9F61BE845,
0x3EB868AC7CAE5163, 0x11C7B65322E332A4, 0xD23C1491B9A992D0, 0x8FB5982E0311C7CA,
0x70AC6428E0C9D4D8, 0x895BC2960F55FCC5, 0x76423E90EC8DEFD7, 0x6FF0507EDE9E7267,
0x3DCF45F07A8CC2EA, 0x4AA06054941F5CB1, 0x5810FB5BB0DEFD9C, 0x5EFEA1E3BC9AC693,
0x6EDD4B4ADC8003EB, 0x741808F8E8B10DD2, 0x145EC1B728859A22, 0x28BC9F7350172944,
0x270A06424EBDCCD3, 0x972AEDF4331C2BF6, 0x059977E40A66A886, 0x2550302A4A812ED6,
0xDD8A8DA0A7037747, 0xC515F87A970E9B7B, 0x3023EAA9601AC578, 0xB7E3AA3A73FBADA6,
0x0FB699311EAAE597, 0x0000000000000000, 0x310EF19D6204B4F4, 0x229371A644DB6455,
0x0DECAF591A960792, 0x5CA4978BB8A62496, 0x1C2B190A38753536, 0x41A295B582CD602C,
0x3279DCC16426277D, 0xC1A194AA9F764271, 0x139D803B26DFD0A1, 0xAE51C4D441E83016,
0xD813FA44AD65DFC1, 0xAC0BF2BC45D4D213, 0x23BE6A9246C515D9, 0x49D74D08923DCF38,
0x9D05032127D066E7, 0x2F7FDEFF5E4D63C7, 0xA47E2A0155247D07, 0x99B16FF12FA8BFED,
0x4661D4398C972AAF, 0xDFD0BBC8A33F9542, 0xDCA79694A51D06CB, 0xB020EBB67DA1E725,
0xBA0F0563696DAA34, 0xE4F1A480D5F76CA7, 0xC438E34E9510EAF7, 0x939E81243B64F2FC,
0x8DEFAE46072D25CF, 0x2C08F3A3586FF04E, 0xD7A56375B3CF3A56, 0x20C947CE40E78650,
0x43F8A3DD86F18229, 0x568B795EAC6A6987, 0x8003011F1DBB225D, 0xF53612D3F7145E03,
0x189F75DA300DEC3C, 0x9570DB9C3720C9F3, 0xBB221E576B73DBB8, 0x72F65240E4F536DD,
0x443BE25188ABC8AA, 0xE21FFE38D9B357A8, 0xFD43CA6EE7E4F117, 0xCAA3614B89A47EEC,
0xFE34E732E1C6629E, 0x83742C431B99B1D4, 0xCF3A16AF83C2D66A, 0xAAE5A8044990E91C,
0x26271D764CA3BD5F, 0x91C4B74C3F5810F9, 0x7C6DD045F841A2C6, 0x7F1AFD19FE63314F,
0xC8F957238D989CE9, 0xA709075D5306EE8E, 0x55FC5402AA48FA0E, 0x48FA563C9023BEB4,
0x65DFBEABCA523F76, 0x6C877D22D8BCE1EE, 0xCC4D3BF385E045E3, 0xBEBB69B36115733E,
0x10EAAD6720FD4328, 0xB6CEB10E71E5DC2A, 0xBDCC44EF6737E0B7, 0x523F158EA412B08D,
0x989C74C52DB6CE61, 0x9BEB59992B945DE8, 0x8A2CEFCA09776F4C, 0xA3BD6B8D5B7E3784,
0xEB473DB1CB5D8930, 0xC3FBA2C29B4AA074, 0x9C28181525CE176B, 0x683311F2D0C438E4,
0x5FD3BAD7BE84B71F, 0xFC6ED15AE5FA809B, 0x36CDB0116C5EFE77, 0x29918447520958C8,
0xA29070B959604608, 0x53120EBAA60CC101, 0x3A0C047C74D68869, 0x691E0AC6D2DA4968,
0x73DB4974E6EB4751, 0x7A838AFDF40599C9, 0x5A4ACD33B4E21F99, 0x6046C94FC03497F0,
0xE6AB92E8D1CB8EA2, 0x3354C7F5663856F1, 0xD93EE170AF7BAE4D, 0x616BD27BC22AE67C,
0x92B39A10397A8370, 0xABC8B3304B8E9890, 0xBF967287630B02B2, 0x5B67D607B6FC6E15
};
static uint64_t T7[256] =
{
0xD031C397CE553FE6, 0x16BA5B01B006B525, 0xA89BADE6296E70C8, 0x6A1F525D77D3435B,
0x6E103570573DFA0B, 0x660EFB2A17FC95AB, 0x76327A9E97634BF6, 0x4BAD9D6462458BF5,
0xF1830CAEDBC3F748, 0xC5C8F542669131FF, 0x95044A1CDC48B0CB, 0x892962DF3CF8B866,
0xB0B9E208E930C135, 0xA14FB3F0611A767C, 0x8D2605F21C160136, 0xD6B71922FECC549E,
0x37089438A5907D8B, 0x0B5DA38E5803D49C, 0x5A5BCC9CEA6F3CBC, 0xEDAE246D3B73FFE5,
0xD2B87E0FDE22EDCE, 0x5E54ABB1CA8185EC, 0x1DE7F88FE80561B9, 0xAD5E1A870135A08C,
0x2F2ADBD665CECC76, 0x5780B5A782F58358, 0x3EDC8A2EEDE47B3F, 0xC9D95C3506BEE70F,
0x83BE111D6C4E05EE, 0xA603B90959367410, 0x103C81B4809FDE5D, 0x2C69B6027D0C774A,
0x399080D7D5C87953, 0x09D41E16487406B4, 0xCDD63B1826505E5F, 0xF99DC2F49B0298E8,
0x9CD0540A943CB67F, 0xBCA84B7F891F17C5, 0x723D1DB3B78DF2A6, 0x78AA6E71E73B4F2E,
0x1433E699A071670D, 0x84F21BE454620782, 0x98DF3327B4D20F2F, 0xF049DCE2D3769E5C,
0xDB6C60199656EB7A, 0x648746B2078B4783, 0x32CD23598DCBADCF, 0x1EA4955BF0C7DA85,
0xE9A143401B9D46B5, 0xFD92A5D9BBEC21B8, 0xC8138C790E0B8E1B, 0x2EE00B9A6D7BA562,
0xF85712B893B7F1FC, 0xEB28FED80BEA949D, 0x564A65EB8A40EA4C, 0x6C9988E8474A2823,
0x4535898B121D8F2D, 0xABD8C03231ACCBF4, 0xBA2E91CAB9867CBD, 0x7960BE3DEF8E263A,
0x0C11A977602FD6F0, 0xCB50E1AD16C93527, 0xEAE22E94035FFD89, 0x2866D12F5DE2CE1A,
0xFF1B1841AB9BF390, 0x9F9339DE8CFE0D43, 0x964727C8C48A0BF7, 0x524502C6AAAE531C,
0x9B9C5EF3AC10B413, 0x4FA2FA4942AB32A5, 0x3F165A62E551122B, 0xC74148DA76E6E3D7,
0x924840E5E464B2A7, 0xD372AE43D69784DA, 0x233B72A105E11A86, 0xA48A04914941A638,
0xB4B68525C9DE7865, 0xDDEABAACA6CF8002, 0x0A9773C250B6BD88, 0xC284FFBB5EBD3393,
0x8BA0DF472C8F6A4E, 0x2AEF6CB74D951C32, 0x427983722A318D41, 0x73F7CDFFBF389BB2,
0x074C0AF9382C026C, 0x8A6A0F0B243A035A, 0x6FDAE53C5F88931F, 0xC68B98967E538AC3,
0x44FF59C71AA8E639, 0xE2FCE0CE439E9229, 0xA20CDE2479D8CD40, 0x19E89FA2C8EBD8E9,
0xF446BBCFF398270C, 0x43B3533E2284E455, 0xD82F0DCD8E945046, 0x51066F12B26CE820,
0xE73957AF6BC5426D, 0x081ECE5A40C16FA0, 0x3B193D4FC5BFAB7B, 0x7FE66488DF174D42,
0x0E9814EF705804D8, 0x8137AC857C39D7C6, 0xB1733244E185A821, 0x695C3F896F11F867,
0xF6CF0657E3EFF524, 0x1AABF276D02963D5, 0x2DA3664E75B91E5E, 0x0289BD981077D228,
0x90C1FD7DF413608F, 0x3C5537B6FD93A917, 0xAA12107E3919A2E0, 0x0686DAB530996B78,
0xDAA6B0559EE3826E, 0xC34E2FF756085A87, 0x6D5358A44FFF4137, 0xFC587595B35948AC,
0x7CA5095CC7D5F67E, 0xFB147F6C8B754AC0, 0xBFEB26AB91DDACF9, 0x6896EFC567A49173,
0xCA9A31E11E7C5C33, 0xBBE44186B13315A9, 0x0DDB793B689ABFE4, 0x70B4A02BA7FA208E,
0xE47A3A7B7307F951, 0x8CECD5BE14A36822, 0xEEED49B923B144D9, 0x17708B4DB8B3DC31,
0x6088219F2765FED3, 0xB3FA8FDCF1F27A09, 0x910B2D31FCA6099B, 0x0F52C4A378ED6DCC,
0x50CCBF5EBAD98134, 0x6BD582117F662A4F, 0x94CE9A50D4FDD9DF, 0x2B25BCFB45207526,
0x67C42B661F49FCBF, 0x492420FC723259DD, 0x03436DD418C2BB3C, 0x1F6E4517F872B391,
0xA08563BC69AF1F68, 0xD43EA4BAEEBB86B6, 0x01CAD04C08B56914, 0xAC94CACB0980C998,
0x54C3D8739A373864, 0x26FEC5C02DBACAC2, 0xDEA9D778BE0D3B3E, 0x040F672D20EEB950,
0xE5B0EA377BB29045, 0xF30AB136CBB42560, 0x62019C0737122CFB, 0xE86B930C13282FA1,
0xCC1CEB542EE5374B, 0x538FD28AA21B3A08, 0x1B61223AD89C0AC1, 0x36C24474AD25149F,
0x7A23D3E9F74C9D06, 0xBE21F6E79968C5ED, 0xCF5F868036278C77, 0xF705D61BEB5A9C30,
0x4D2B47D152DCE08D, 0x5F9E7BFDC234ECF8, 0x247778583DCD18EA, 0x867BA67C4415D5AA,
0x4CE1979D5A698999, 0x0000000000000000, 0xEC64F42133C696F1, 0xB57C5569C16B1171,
0xC1C7926F467F88AF, 0x654D96FE0F3E2E97, 0x15F936D5A8C40E19, 0xB8A72C52A9F1AE95,
0xA9517DAA21DB19DC, 0x58D27104FA18EE94, 0x5918A148F2AD8780, 0x5CDD1629DAF657C4,
0x8274C15164FB6CFA, 0xD1FB13DBC6E056F2, 0x7D6FD910CF609F6A, 0xB63F38BDD9A9AA4D,
0x3D9FE7FAF526C003, 0x74BBC706871499DE, 0xDF630734B6B8522A, 0x3AD3ED03CD0AC26F,
0xFADEAF2083C023D4, 0xC00D42234ECAE1BB, 0x8538CBA85CD76E96, 0xC402250E6E2458EB,
0x47BC3413026A5D05, 0xAFD7A71F114272A4, 0x978DF784CC3F62E3, 0xB96DFC1EA144C781,
0x21B2CF391596C8AE, 0x318E4E8D950916F3, 0xCE9556CC3E92E563, 0x385A509BDD7D1047,
0x358129A0B5E7AFA3, 0xE6F387E363702B79, 0xE0755D5653E94001, 0x7BE903A5FFF9F412,
0x12B53C2C90E80C75, 0x3307F315857EC4DB, 0x8FAFB86A0C61D31E, 0xD9E5DD8186213952,
0x77F8AAD29FD622E2, 0x25BDA814357871FE, 0x7571174A8FA1F0CA, 0x137FEC60985D6561,
0x30449EC19DBC7FE7, 0xA540D4DD41F4CF2C, 0xDC206AE0AE7AE916, 0x5B911CD0E2DA55A8,
0xB2305F90F947131D, 0x344BF9ECBD52C6B7, 0x5D17C665D2433ED0, 0x18224FEEC05EB1FD,
0x9E59E992844B6457, 0x9A568EBFA4A5DD07, 0xA3C60E68716DA454, 0x7E2CB4C4D7A22456,
0x87B176304CA0BCBE, 0x413AEEA632F3367D, 0x9915E36BBC67663B, 0x40F03EEA3A465F69,
0x1C2D28C3E0B008AD, 0x4E682A054A1E5BB1, 0x05C5B761285BD044, 0xE1BF8D1A5B5C2915,
0xF2C0617AC3014C74, 0xB7F5E8F1D11CC359, 0x63CB4C4B3FA745EF, 0x9D1A84469C89DF6B,
0xE33630824B2BFB3D, 0xD5F474F6E60EEFA2, 0xF58C6B83FB2D4E18, 0x4676E45F0ADF3411,
0x20781F751D23A1BA, 0xBD629B3381AA7ED1, 0xAE1D775319F71BB0, 0xFED1C80DA32E9A84,
0x5509083F92825170, 0x29AC01635557A70E, 0xA7C9694551831D04, 0x8E65682604D4BA0A,
0x11F651F8882AB749, 0xD77DC96EF6793D8A, 0xEF2799F52B042DCD, 0x48EEF0B07A8730C9,
0x22F1A2ED0D547392, 0x6142F1D32FD097C7, 0x4A674D286AF0E2E1, 0x80FD7CC9748CBED2,
0x717E7067AF4F499A, 0x938290A9ECD1DBB3, 0x88E3B293344DD172, 0x2734158C250FA3D6
};
static const uint64_t A_[64] =
{
0x8e20faa72ba0b470, 0x47107ddd9b505a38, 0xad08b0e0c3282d1c, 0xd8045870ef14980e,
0x6c022c38f90a4c07, 0x3601161cf205268d, 0x1b8e0b0e798c13c8, 0x83478b07b2468764,
0xa011d380818e8f40, 0x5086e740ce47c920, 0x2843fd2067adea10, 0x14aff010bdd87508,
0x0ad97808d06cb404, 0x05e23c0468365a02, 0x8c711e02341b2d01, 0x46b60f011a83988e,
0x90dab52a387ae76f, 0x486dd4151c3dfdb9, 0x24b86a840e90f0d2, 0x125c354207487869,
0x092e94218d243cba, 0x8a174a9ec8121e5d, 0x4585254f64090fa0, 0xaccc9ca9328a8950,
0x9d4df05d5f661451, 0xc0a878a0a1330aa6, 0x60543c50de970553, 0x302a1e286fc58ca7,
0x18150f14b9ec46dd, 0x0c84890ad27623e0, 0x0642ca05693b9f70, 0x0321658cba93c138,
0x86275df09ce8aaa8, 0x439da0784e745554, 0xafc0503c273aa42a, 0xd960281e9d1d5215,
0xe230140fc0802984, 0x71180a8960409a42, 0xb60c05ca30204d21, 0x5b068c651810a89e,
0x456c34887a3805b9, 0xac361a443d1c8cd2, 0x561b0d22900e4669, 0x2b838811480723ba,
0x9bcf4486248d9f5d, 0xc3e9224312c8c1a0, 0xeffa11af0964ee50, 0xf97d86d98a327728,
0xe4fa2054a80b329c, 0x727d102a548b194e, 0x39b008152acb8227, 0x9258048415eb419d,
0x492c024284fbaec0, 0xaa16012142f35760, 0x550b8e9e21f7a530, 0xa48b474f9ef5dc18,
0x70a6a56e2440598e, 0x3853dc371220a247, 0x1ca76e95091051ad, 0x0edd37c48a08a6d8,
0x07e095624504536c, 0x8d70c431ac02a736, 0xc83862965601dd1b, 0x641c314b2b8ee083
};
static const uint8_t C_[12][64] =
static const uint64_t C_[12][8] =
{
{
0xb1,0x08,0x5b,0xda,0x1e,0xca,0xda,0xe9,0xeb,0xcb,0x2f,0x81,0xc0,0x65,0x7c,0x1f,
0x2f,0x6a,0x76,0x43,0x2e,0x45,0xd0,0x16,0x71,0x4e,0xb8,0x8d,0x75,0x85,0xc4,0xfc,
0x4b,0x7c,0xe0,0x91,0x92,0x67,0x69,0x01,0xa2,0x42,0x2a,0x08,0xa4,0x60,0xd3,0x15,
0x05,0x76,0x74,0x36,0xcc,0x74,0x4d,0x23,0xdd,0x80,0x65,0x59,0xf2,0xa6,0x45,0x07
},
0xe9daca1eda5b08b1, 0x1f7c65c0812fcbeb, 0x16d0452e43766a2f, 0xfcc485758db84e71,
0x0169679291e07c4b, 0x15d360a4082a42a2, 0x234d74cc36747605, 0x0745a6f2596580dd
},
{
0x6f,0xa3,0xb5,0x8a,0xa9,0x9d,0x2f,0x1a,0x4f,0xe3,0x9d,0x46,0x0f,0x70,0xb5,0xd7,
0xf3,0xfe,0xea,0x72,0x0a,0x23,0x2b,0x98,0x61,0xd5,0x5e,0x0f,0x16,0xb5,0x01,0x31,
0x9a,0xb5,0x17,0x6b,0x12,0xd6,0x99,0x58,0x5c,0xb5,0x61,0xc2,0xdb,0x0a,0xa7,0xca,
0x55,0xdd,0xa2,0x1b,0xd7,0xcb,0xcd,0x56,0xe6,0x79,0x04,0x70,0x21,0xb1,0x9b,0xb7
},
0x1a2f9da98ab5a36f, 0xd7b5700f469de34f, 0x982b230a72eafef3, 0x3101b5160f5ed561,
0x5899d6126b17b59a, 0xcaa70adbc261b55c, 0x56cdcbd71ba2dd55, 0xb79bb121700479e6
},
{
0xf5,0x74,0xdc,0xac,0x2b,0xce,0x2f,0xc7,0x0a,0x39,0xfc,0x28,0x6a,0x3d,0x84,0x35,
0x06,0xf1,0x5e,0x5f,0x52,0x9c,0x1f,0x8b,0xf2,0xea,0x75,0x14,0xb1,0x29,0x7b,0x7b,
0xd3,0xe2,0x0f,0xe4,0x90,0x35,0x9e,0xb1,0xc1,0xc9,0x3a,0x37,0x60,0x62,0xdb,0x09,
0xc2,0xb6,0xf4,0x43,0x86,0x7a,0xdb,0x31,0x99,0x1e,0x96,0xf5,0x0a,0xba,0x0a,0xb2
},
0xc72fce2bacdc74f5, 0x35843d6a28fc390a, 0x8b1f9c525f5ef106, 0x7b7b29b11475eaf2,
0xb19e3590e40fe2d3, 0x09db6260373ac9c1, 0x31db7a8643f4b6c2, 0xb20aba0af5961e99
},
{
0xef,0x1f,0xdf,0xb3,0xe8,0x15,0x66,0xd2,0xf9,0x48,0xe1,0xa0,0x5d,0x71,0xe4,0xdd,
0x48,0x8e,0x85,0x7e,0x33,0x5c,0x3c,0x7d,0x9d,0x72,0x1c,0xad,0x68,0x5e,0x35,0x3f,
0xa9,0xd7,0x2c,0x82,0xed,0x03,0xd6,0x75,0xd8,0xb7,0x13,0x33,0x93,0x52,0x03,0xbe,
0x34,0x53,0xea,0xa1,0x93,0xe8,0x37,0xf1,0x22,0x0c,0xbe,0xbc,0x84,0xe3,0xd1,0x2e
},
0xd26615e8b3df1fef, 0xdde4715da0e148f9, 0x7d3c5c337e858e48, 0x3f355e68ad1c729d,
0x75d603ed822cd7a9, 0xbe0352933313b7d8, 0xf137e893a1ea5334, 0x2ed1e384bcbe0c22
},
{
0x4b,0xea,0x6b,0xac,0xad,0x47,0x47,0x99,0x9a,0x3f,0x41,0x0c,0x6c,0xa9,0x23,0x63,
0x7f,0x15,0x1c,0x1f,0x16,0x86,0x10,0x4a,0x35,0x9e,0x35,0xd7,0x80,0x0f,0xff,0xbd,
0xbf,0xcd,0x17,0x47,0x25,0x3a,0xf5,0xa3,0xdf,0xff,0x00,0xb7,0x23,0x27,0x1a,0x16,
0x7a,0x56,0xa2,0x7e,0xa9,0xea,0x63,0xf5,0x60,0x17,0x58,0xfd,0x7c,0x6c,0xfe,0x57
},
0x994747adac6bea4b, 0x6323a96c0c413f9a, 0x4a1086161f1c157f, 0xbdff0f80d7359e35,
0xa3f53a254717cdbf, 0x161a2723b700ffdf, 0xf563eaa97ea2567a, 0x57fe6c7cfd581760
},
{
0xae,0x4f,0xae,0xae,0x1d,0x3a,0xd3,0xd9,0x6f,0xa4,0xc3,0x3b,0x7a,0x30,0x39,0xc0,
0x2d,0x66,0xc4,0xf9,0x51,0x42,0xa4,0x6c,0x18,0x7f,0x9a,0xb4,0x9a,0xf0,0x8e,0xc6,
0xcf,0xfa,0xa6,0xb7,0x1c,0x9a,0xb7,0xb4,0x0a,0xf2,0x1f,0x66,0xc2,0xbe,0xc6,0xb6,
0xbf,0x71,0xc5,0x72,0x36,0x90,0x4f,0x35,0xfa,0x68,0x40,0x7a,0x46,0x64,0x7d,0x6e
},
0xd9d33a1daeae4fae, 0xc039307a3bc3a46f, 0x6ca44251f9c4662d, 0xc68ef09ab49a7f18,
0xb4b79a1cb7a6facf, 0xb6c6bec2661ff20a, 0x354f903672c571bf, 0x6e7d64467a4068fa
},
{
0xf4,0xc7,0x0e,0x16,0xee,0xaa,0xc5,0xec,0x51,0xac,0x86,0xfe,0xbf,0x24,0x09,0x54,
0x39,0x9e,0xc6,0xc7,0xe6,0xbf,0x87,0xc9,0xd3,0x47,0x3e,0x33,0x19,0x7a,0x93,0xc9,
0x09,0x92,0xab,0xc5,0x2d,0x82,0x2c,0x37,0x06,0x47,0x69,0x83,0x28,0x4a,0x05,0x04,
0x35,0x17,0x45,0x4c,0xa2,0x3c,0x4a,0xf3,0x88,0x86,0x56,0x4d,0x3a,0x14,0xd4,0x93
},
0xecc5aaee160ec7f4, 0x540924bffe86ac51, 0xc987bfe6c7c69e39, 0xc9937a19333e47d3,
0x372c822dc5ab9209, 0x04054a2883694706, 0xf34a3ca24c451735, 0x93d4143a4d568688
},
{
0x9b,0x1f,0x5b,0x42,0x4d,0x93,0xc9,0xa7,0x03,0xe7,0xaa,0x02,0x0c,0x6e,0x41,0x41,
0x4e,0xb7,0xf8,0x71,0x9c,0x36,0xde,0x1e,0x89,0xb4,0x44,0x3b,0x4d,0xdb,0xc4,0x9a,
0xf4,0x89,0x2b,0xcb,0x92,0x9b,0x06,0x90,0x69,0xd1,0x8d,0x2b,0xd1,0xa5,0xc4,0x2f,
0x36,0xac,0xc2,0x35,0x59,0x51,0xa8,0xd9,0xa4,0x7f,0x0d,0xd4,0xbf,0x02,0xe7,0x1e
},
0xa7c9934d425b1f9b, 0x41416e0c02aae703, 0x1ede369c71f8b74e, 0x9ac4db4d3b44b489,
0x90069b92cb2b89f4, 0x2fc4a5d12b8dd169, 0xd9a8515935c2ac36, 0x1ee702bfd40d7fa4
},
{
0x37,0x8f,0x5a,0x54,0x16,0x31,0x22,0x9b,0x94,0x4c,0x9a,0xd8,0xec,0x16,0x5f,0xde,
0x3a,0x7d,0x3a,0x1b,0x25,0x89,0x42,0x24,0x3c,0xd9,0x55,0xb7,0xe0,0x0d,0x09,0x84,
0x80,0x0a,0x44,0x0b,0xdb,0xb2,0xce,0xb1,0x7b,0x2b,0x8a,0x9a,0xa6,0x07,0x9c,0x54,
0x0e,0x38,0xdc,0x92,0xcb,0x1f,0x2a,0x60,0x72,0x61,0x44,0x51,0x83,0x23,0x5a,0xdb
},
0x9b223116545a8f37, 0xde5f16ecd89a4c94, 0x244289251b3a7d3a, 0x84090de0b755d93c,
0xb1ceb2db0b440a80, 0x549c07a69a8a2b7b, 0x602a1fcb92dc380e, 0xdb5a238351446172
},
{
0xab,0xbe,0xde,0xa6,0x80,0x05,0x6f,0x52,0x38,0x2a,0xe5,0x48,0xb2,0xe4,0xf3,0xf3,
0x89,0x41,0xe7,0x1c,0xff,0x8a,0x78,0xdb,0x1f,0xff,0xe1,0x8a,0x1b,0x33,0x61,0x03,
0x9f,0xe7,0x67,0x02,0xaf,0x69,0x33,0x4b,0x7a,0x1e,0x6c,0x30,0x3b,0x76,0x52,0xf4,
0x36,0x98,0xfa,0xd1,0x15,0x3b,0xb6,0xc3,0x74,0xb4,0xc7,0xfb,0x98,0x45,0x9c,0xed
},
0x526f0580a6debeab, 0xf3f3e4b248e52a38, 0xdb788aff1ce74189, 0x0361331b8ae1ff1f,
0x4b3369af0267e79f, 0xf452763b306c1e7a, 0xc3b63b15d1fa9836, 0xed9c4598fbc7b474
},
{
0x7b,0xcd,0x9e,0xd0,0xef,0xc8,0x89,0xfb,0x30,0x02,0xc6,0xcd,0x63,0x5a,0xfe,0x94,
0xd8,0xfa,0x6b,0xbb,0xeb,0xab,0x07,0x61,0x20,0x01,0x80,0x21,0x14,0x84,0x66,0x79,
0x8a,0x1d,0x71,0xef,0xea,0x48,0xb9,0xca,0xef,0xba,0xcd,0x1d,0x7d,0x47,0x6e,0x98,
0xde,0xa2,0x59,0x4a,0xc0,0x6f,0xd8,0x5d,0x6b,0xca,0xa4,0xcd,0x81,0xf3,0x2d,0x1b
},
0xfb89c8efd09ecd7b, 0x94fe5a63cdc60230, 0x6107abebbb6bfad8, 0x7966841421800120,
0xcab948eaef711d8a, 0x986e477d1dcdbaef, 0x5dd86fc04a59a2de, 0x1b2df381cda4ca6b
},
{
0x37,0x8e,0xe7,0x67,0xf1,0x16,0x31,0xba,0xd2,0x13,0x80,0xb0,0x04,0x49,0xb1,0x7a,
0xcd,0xa4,0x3c,0x32,0xbc,0xdf,0x1d,0x77,0xf8,0x20,0x12,0xd4,0x30,0x21,0x9f,0x9b,
0x5d,0x80,0xef,0x9d,0x18,0x91,0xcc,0x86,0xe7,0x1d,0xa4,0xaa,0x88,0xe1,0x28,0x52,
0xfa,0xf4,0x17,0xd5,0xd9,0xb2,0x1b,0x99,0x48,0xbc,0x92,0x4a,0xf1,0x1b,0xd7,0x20
0xba3116f167e78e37, 0x7ab14904b08013d2, 0x771ddfbc323ca4cd, 0x9b9f2130d41220f8,
0x86cc91189def805d, 0x5228e188aaa41de7, 0x991bb2d9d517f4fa, 0x20d71bf14a92bc48
}
};
union GOST3411Block // 8 bytes aligned
{
@@ -307,15 +781,15 @@ namespace crypto
ret.ll[i] = ll[i]^other.ll[i];
return ret;
}
GOST3411Block operator^(const uint8_t * other) const
GOST3411Block operator^(const uint64_t * other) const
{
GOST3411Block ret;
for (int i = 0; i < 64; i++)
ret.buf[i] = buf[i]^other[i];
for (int i = 0; i < 8; i++)
ret.ll[i] = ll[i]^other[i];
return ret;
}
GOST3411Block operator+(const GOST3411Block& other) const
{
GOST3411Block ret;
@@ -340,26 +814,24 @@ namespace crypto
}
}
void SPL ()
void F ()
{
uint8_t p[64];
memcpy (p, buf, 64); // we need to copy it for P's transposition
for (int i = 0; i < 8; i++)
uint64_t res[8];
for (int b=0; b<8; b++)
{
uint64_t c = 0;
for (int j = 0; j < 8; j++)
{
uint8_t bit = 0x80;
uint8_t byte = sbox_[p[j*8+i]]; // S - sbox_, P - transpose (i,j)
for (int k = 0; k < 8; k++)
{
if (byte & bit) c ^= A_[j*8+k];
bit >>= 1;
}
}
ll[i] = htobe64 (c);
}
}
uint64_t r;
r = T0[buf[b+56]];
r ^= T1[buf[b+48]];
r ^= T2[buf[b+40]];
r ^= T3[buf[b+32]];
r ^= T4[buf[b+24]];
r ^= T5[buf[b+16]];
r ^= T6[buf[b+8]];
r ^= T7[buf[b]];
res[b] = r;
}
memcpy (buf, res, 64);
}
GOST3411Block E (const GOST3411Block& m)
{
@@ -367,9 +839,9 @@ namespace crypto
GOST3411Block res = k^m;
for (int i = 0; i < 12; i++)
{
res.SPL ();
res.F ();
k = k^C_[i];
k.SPL ();
k.F ();
res = k^res;
}
return res;
@@ -379,7 +851,7 @@ namespace crypto
static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m)
{
GOST3411Block res = N ^ h;
res.SPL ();
res.F ();
res = res.E (m);
res = res^h;
res = res^m;

View File

@@ -29,7 +29,7 @@ namespace http {
inline bool is_http_method(const std::string & str) {
return std::find(HTTP_METHODS.begin(), HTTP_METHODS.end(), str) != std::end(HTTP_METHODS);
}
void strsplit(const std::string & line, std::vector<std::string> &tokens, char delim, std::size_t limit = 0) {
std::size_t count = 0;
std::stringstream ss(line);
@@ -195,6 +195,11 @@ namespace http {
return out;
}
bool URL::is_i2p() const
{
return host.rfind(".i2p") == ( host.size() - 4 );
}
void HTTPMsg::add_header(const char *name, std::string & value, bool replace) {
add_header(name, value.c_str(), replace);
}

View File

@@ -56,6 +56,11 @@ namespace http
* @note Returns relative url if schema if empty, absolute url otherwise
*/
std::string to_string ();
/**
* @brief return true if the host is inside i2p
*/
bool is_i2p() const;
};
struct HTTPMsg
@@ -89,7 +94,7 @@ namespace http
/** @brief Serialize HTTP request to string */
std::string to_string();
void write(std::ostream & o);
void write(std::ostream & o);
void AddHeader (const std::string& name, const std::string& value);
void UpdateHeader (const std::string& name, const std::string& value);
@@ -131,7 +136,7 @@ namespace http
std::string to_string();
void write(std::ostream & o);
/** @brief Checks that response declared as chunked data */
bool is_chunked() const ;

View File

@@ -327,7 +327,7 @@ namespace i2p
{
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
BN_CTX * ctx = BN_CTX_new ();
i2p::crypto::ElGamalDecrypt (i2p::context.GetEncryptionPrivateKey (), record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
BN_CTX_free (ctx);
// replace record to reply
if (i2p::context.AcceptsTunnels () &&
@@ -546,18 +546,40 @@ namespace i2p
return msg;
}
size_t GetI2NPMessageLength (const uint8_t * msg)
size_t GetI2NPMessageLength (const uint8_t * msg, size_t len)
{
return bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
if (len < I2NP_HEADER_SIZE_OFFSET + 2)
{
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);
l = len;
}
return l;
}
void HandleI2NPMessage (uint8_t * msg, size_t len)
{
if (len < I2NP_HEADER_SIZE)
{
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header");
return;
}
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + I2NP_HEADER_SIZE;
int size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
len -= I2NP_HEADER_SIZE;
if (size > len)
{
LogPrint (eLogError, "I2NP: payload size ", size, " exceeds buffer length ", len);
size = len;
}
switch (typeID)
{
case eI2NPVariableTunnelBuild:

View File

@@ -243,7 +243,7 @@ namespace tunnel
const uint8_t * buf, size_t len, uint32_t replyMsgID = 0);
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr<I2NPMessage> msg);
size_t GetI2NPMessageLength (const uint8_t * msg);
size_t GetI2NPMessageLength (const uint8_t * msg, size_t len);
void HandleI2NPMessage (uint8_t * msg, size_t len);
void HandleI2NPMessage (std::shared_ptr<I2NPMessage> msg);

View File

@@ -39,10 +39,10 @@ namespace data
{
}
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type):
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType):
m_IsVerifierCreated (false)
{
memcpy (m_StandardIdentity.publicKey, publicKey, sizeof (m_StandardIdentity.publicKey));
{
memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{
size_t excessLen = 0;
@@ -103,7 +103,6 @@ namespace data
break;
}
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
{
// 256
size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64
@@ -112,7 +111,6 @@ namespace data
break;
}
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
{
// 512
// no padding, key length is 128
@@ -129,7 +127,7 @@ namespace data
// fill extended buffer
m_ExtendedBuffer = new uint8_t[m_ExtendedLen];
htobe16buf (m_ExtendedBuffer, type);
htobe16buf (m_ExtendedBuffer + 2, CRYPTO_KEY_TYPE_ELGAMAL);
htobe16buf (m_ExtendedBuffer + 2, cryptoType);
if (excessLen && excessBuf)
{
memcpy (m_ExtendedBuffer + 4, excessBuf, excessLen);
@@ -326,6 +324,12 @@ namespace data
return SIGNING_KEY_TYPE_DSA_SHA1;
}
bool IdentityEx::IsRSA () const
{
auto sigType = GetSigningKeyType ();
return sigType <= SIGNING_KEY_TYPE_RSA_SHA512_4096 && sigType >= SIGNING_KEY_TYPE_RSA_SHA256_2048;
}
CryptoKeyType IdentityEx::GetCryptoKeyType () const
{
if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4)
@@ -397,14 +401,12 @@ namespace data
break;
}
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
{
size_t padding = 128 - i2p::crypto::GOSTR3410_256_PUBLIC_KEY_LENGTH; // 64 = 128 - 64
UpdateVerifier (new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA, m_StandardIdentity.signingKey + padding));
break;
}
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
{
// zero padding
UpdateVerifier (new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512, m_StandardIdentity.signingKey));
@@ -446,6 +448,27 @@ namespace data
m_Verifier = nullptr;
}
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (const uint8_t * key) const
{
if (!key) key = GetEncryptionPublicKey (); // use publicKey
switch (GetCryptoKeyType ())
{
case CRYPTO_KEY_TYPE_ELGAMAL:
return std::make_shared<i2p::crypto::ElGamalEncryptor>(key);
break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
return std::make_shared<i2p::crypto::ECIESP256Encryptor>(key);
break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
return std::make_shared<i2p::crypto::ECIESGOSTR3410Encryptor>(key);
break;
default:
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)GetCryptoKeyType ());
};
return nullptr;
}
PrivateKeys& PrivateKeys::operator=(const Keys& keys)
{
m_Public = std::make_shared<IdentityEx>(Identity (keys));
@@ -553,11 +576,9 @@ namespace data
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH));
break;
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey));
break;
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey));
break;
default:
@@ -573,7 +594,34 @@ namespace data
return nullptr; // TODO: implement me
}
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type)
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> PrivateKeys::CreateDecryptor (const uint8_t * key) const
{
if (!key) key = m_PrivateKey; // use privateKey
return CreateDecryptor (m_Public->GetCryptoKeyType (), key);
}
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> PrivateKeys::CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key)
{
if (!key) return nullptr;
switch (cryptoType)
{
case CRYPTO_KEY_TYPE_ELGAMAL:
return std::make_shared<i2p::crypto::ElGamalDecryptor>(key);
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);
break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
return std::make_shared<i2p::crypto::ECIESGOSTR3410Decryptor>(key);
break;
default:
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType);
};
return nullptr;
}
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType)
{
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{
@@ -592,34 +640,28 @@ namespace data
i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break;
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA2562048_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break;
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA3843072_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break;
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA5124096_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey);
break;
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA");
// no break here
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey);
break;
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey);
break;
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey);
break;
default:
LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
}
// encryption
uint8_t publicKey[256];
i2p::crypto::GenerateElGamalKeyPair (keys.m_PrivateKey, publicKey);
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
// identity
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type);
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type, cryptoType);
keys.CreateSigner ();
return keys;
@@ -627,6 +669,25 @@ namespace data
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
}
void PrivateKeys::GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub)
{
switch (type)
{
case CRYPTO_KEY_TYPE_ELGAMAL:
i2p::crypto::GenerateElGamalKeyPair(priv, pub);
break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST:
i2p::crypto::CreateECIESP256RandomKeys (priv, pub);
break;
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub);
break;
default:
LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported");
}
}
Keys CreateRandomKeys ()
{
Keys keys;

View File

@@ -8,6 +8,7 @@
#include <atomic>
#include "Base.h"
#include "Signature.h"
#include "CryptoKey.h"
namespace i2p
{
@@ -52,6 +53,10 @@ namespace data
const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later
const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES
const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0;
const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA256_P256 = 1;
const uint16_t SIGNING_KEY_TYPE_ECDSA_SHA384_P384 = 2;
@@ -64,9 +69,6 @@ namespace data
// following signature type should never appear in netid=2
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9;
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB
// TODO: remove later
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST = 65281;
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST = 65282;
typedef uint16_t SigningKeyType;
typedef uint16_t CryptoKeyType;
@@ -77,7 +79,7 @@ namespace data
IdentityEx ();
IdentityEx (const uint8_t * publicKey, const uint8_t * signingKey,
SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1);
SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
IdentityEx (const uint8_t * buf, size_t len);
IdentityEx (const IdentityEx& other);
IdentityEx (const Identity& standard);
@@ -89,17 +91,19 @@ namespace data
size_t ToBuffer (uint8_t * buf, size_t len) const;
size_t FromBase64(const std::string& s);
std::string ToBase64 () const;
const Identity& GetStandardIdentity () const { return m_StandardIdentity; };
const Identity& GetStandardIdentity () const { return m_StandardIdentity; };
const IdentHash& GetIdentHash () const { return m_IdentHash; };
const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; };
uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; };
const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; };
uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; };
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (const uint8_t * key) const;
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
size_t GetSigningPublicKeyLen () const;
size_t GetSigningPrivateKeyLen () const;
size_t GetSignatureLen () const;
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
SigningKeyType GetSigningKeyType () const;
bool IsRSA () const; // signing key type
CryptoKeyType GetCryptoKeyType () const;
void DropVerifier () const; // to save memory
@@ -137,7 +141,7 @@ namespace data
const uint8_t * GetPrivateKey () const { return m_PrivateKey; };
const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
uint8_t * GetPadding();
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); };
@@ -147,7 +151,11 @@ namespace data
size_t FromBase64(const std::string& s);
std::string ToBase64 () const;
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1);
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (const uint8_t * key) const;
static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
private:
@@ -186,9 +194,11 @@ namespace data
RoutingDestination () {};
virtual ~RoutingDestination () {};
virtual const IdentHash& GetIdentHash () const = 0;
virtual const uint8_t * GetEncryptionPublicKey () const = 0;
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 bool IsDestination () const = 0; // for garlic
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };
};
class LocalDestination
@@ -196,7 +206,7 @@ namespace data
public:
virtual ~LocalDestination() {};
virtual const uint8_t * GetEncryptionPrivateKey () const = 0;
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const = 0;
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
const IdentHash& GetIdentHash () const { return GetIdentity ()->GetIdentHash (); };

View File

@@ -208,6 +208,13 @@ namespace data
return ts > m_ExpirationTime;
}
void LeaseSet::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
{
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
if (encryptor)
encryptor->Encrypt (data, encrypted, ctx);
}
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
m_ExpirationTime (0), m_Identity (identity)
{

View File

@@ -59,8 +59,7 @@ namespace data
~LeaseSet () { delete[] m_Buffer; };
void Update (const uint8_t * buf, size_t len);
bool IsNewer (const uint8_t * buf, size_t len) const;
void PopulateLeases (); // from buffer
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
void PopulateLeases (); // from buffer
const uint8_t * GetBuffer () const { return m_Buffer; };
size_t GetBufferLen () const { return m_BufferLen; };
@@ -76,8 +75,8 @@ namespace data
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
// implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); };
const uint8_t * GetEncryptionPublicKey () const { return m_EncryptionKey; };
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
bool IsDestination () const { return true; };
private:

View File

@@ -16,10 +16,11 @@ namespace log {
*/
static const char * g_LogLevelStr[eNumLogLevels] =
{
"none", // eLogNone
"error", // eLogError
"warn", // eLogWarn
"info", // eLogInfo
"debug" // eLogDebug
"debug" // eLogDebug
};
/**
@@ -27,9 +28,10 @@ namespace log {
* @note Using ISO 6429 (ANSI) color sequences
*/
#ifdef _WIN32
static const char *LogMsgColors[] = { "", "", "", "", "" };
static const char *LogMsgColors[] = { "", "", "", "", "", "" };
#else /* UNIX */
static const char *LogMsgColors[] = {
[eLogNone] = "\033[0m", /* reset */
[eLogError] = "\033[1;31m", /* red */
[eLogWarning] = "\033[1;33m", /* yellow */
[eLogInfo] = "\033[1;36m", /* cyan */
@@ -46,6 +48,7 @@ namespace log {
static inline int GetSyslogPrio (enum LogLevel l) {
int priority = LOG_DEBUG;
switch (l) {
case eLogNone : priority = LOG_CRIT; break;
case eLogError : priority = LOG_ERR; break;
case eLogWarning : priority = LOG_WARNING; break;
case eLogInfo : priority = LOG_INFO; break;
@@ -58,7 +61,7 @@ namespace log {
Log::Log():
m_Destination(eLogStdout), m_MinLevel(eLogInfo),
m_LogStream (nullptr), m_Logfile(""), m_HasColors(true),
m_LogStream (nullptr), m_Logfile(""), m_HasColors(true), m_TimeFormat("%H:%M:%S"),
m_IsRunning (false), m_Thread (nullptr)
{
}
@@ -71,15 +74,15 @@ namespace log {
void Log::Start ()
{
if (!m_IsRunning)
{
m_IsRunning = true;
{
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Log::Run, this));
}
}
void Log::Stop ()
void Log::Stop ()
{
switch (m_Destination)
switch (m_Destination)
{
#ifndef _WIN32
case eLogSyslog :
@@ -97,15 +100,16 @@ namespace log {
m_IsRunning = false;
m_Queue.WakeUp ();
if (m_Thread)
{
m_Thread->join ();
{
m_Thread->join ();
delete m_Thread;
m_Thread = nullptr;
}
}
}
void Log::SetLogLevel (const std::string& level) {
if (level == "error") { m_MinLevel = eLogError; }
if (level == "none") { m_MinLevel = eLogNone; }
else if (level == "error") { m_MinLevel = eLogError; }
else if (level == "warn") { m_MinLevel = eLogWarning; }
else if (level == "info") { m_MinLevel = eLogInfo; }
else if (level == "debug") { m_MinLevel = eLogDebug; }
@@ -115,10 +119,10 @@ namespace log {
}
LogPrint(eLogInfo, "Log: min messages level set to ", level);
}
const char * Log::TimeAsString(std::time_t t) {
if (t != m_LastTimestamp) {
strftime(m_LastDateTime, sizeof(m_LastDateTime), "%H:%M:%S", localtime(&t));
strftime(m_LastDateTime, sizeof(m_LastDateTime), m_TimeFormat.c_str(), localtime(&t));
m_LastTimestamp = t;
}
return m_LastDateTime;
@@ -129,7 +133,7 @@ namespace log {
* Unfortunately, with current startup process with late fork() this
* will give us nothing but pain. Maybe later. See in NetDb as example.
*/
void Log::Process(std::shared_ptr<LogMsg> msg)
void Log::Process(std::shared_ptr<LogMsg> msg)
{
if (!msg) return;
std::hash<std::thread::id> hasher;
@@ -165,25 +169,26 @@ namespace log {
while (m_IsRunning)
{
std::shared_ptr<LogMsg> msg;
while (msg = m_Queue.Get ())
while ((msg = m_Queue.Get ()))
Process (msg);
if (m_LogStream) m_LogStream->flush();
if (m_IsRunning)
m_Queue.Wait ();
}
}
}
void Log::Append(std::shared_ptr<i2p::log::LogMsg> & msg)
void Log::Append(std::shared_ptr<i2p::log::LogMsg> & msg)
{
m_Queue.Put(msg);
}
void Log::SendTo (const std::string& path)
void Log::SendTo (const std::string& path)
{
if (m_LogStream) m_LogStream = nullptr; // close previous
if (m_LogStream) m_LogStream = nullptr; // close previous
if (m_MinLevel == eLogNone) return;
auto flags = std::ofstream::out | std::ofstream::app;
auto os = std::make_shared<std::ofstream> (path, flags);
if (os->is_open ())
if (os->is_open ())
{
m_HasColors = false;
m_Logfile = path;
@@ -202,6 +207,7 @@ namespace log {
#ifndef _WIN32
void Log::SendTo(const char *name, int facility) {
if (m_MinLevel == eLogNone) return;
m_HasColors = false;
m_Destination = eLogSyslog;
m_LogStream = nullptr;

View File

@@ -25,10 +25,11 @@
enum LogLevel
{
eLogError = 0,
eLogNone = 0,
eLogError,
eLogWarning,
eLogInfo,
eLogDebug,
eLogDebug,
eNumLogLevels
};
@@ -58,6 +59,7 @@ namespace log {
char m_LastDateTime[64];
i2p::util::Queue<std::shared_ptr<LogMsg> > m_Queue;
bool m_HasColors;
std::string m_TimeFormat;
volatile bool m_IsRunning;
std::thread * m_Thread;
@@ -107,6 +109,12 @@ namespace log {
*/
void SendTo (std::shared_ptr<std::ostream> os);
/**
* @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

View File

@@ -791,7 +791,8 @@ namespace transport
NTCPServer::NTCPServer ():
m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service),
m_TerminationTimer (m_Service), m_NTCPAcceptor (nullptr), m_NTCPV6Acceptor (nullptr),
m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr)
m_ProxyType(eNoProxy), m_Resolver(m_Service), m_ProxyEndpoint(nullptr),
m_SoftLimit(0), m_HardLimit(0)
{
}
@@ -965,6 +966,13 @@ namespace transport
auto ep = conn->GetSocket ().remote_endpoint(ec);
if (!ec)
{
if(ShouldLimit())
{
// hit limit, close premature
LogPrint(eLogWarning, "NTCP: limiting with backoff session from ", ep);
conn->Terminate();
return;
}
LogPrint (eLogDebug, "NTCP: Connected from ", ep);
if (conn)
{
@@ -993,6 +1001,14 @@ namespace transport
auto ep = conn->GetSocket ().remote_endpoint(ec);
if (!ec)
{
if(ShouldLimit())
{
// hit limit, close premature
LogPrint(eLogWarning, "NTCP: limiting with backoff on session from ", ep);
conn->Terminate();
return;
}
LogPrint (eLogDebug, "NTCP: Connected from ", ep);
if (conn)
{
@@ -1231,7 +1247,7 @@ namespace transport
return;
}
buff[4] = (uint8_t) addrsize;
memcpy(buff+4, host.c_str(), addrsize);
memcpy(buff+5, host.c_str(), addrsize);
}
htobe16buf(buff+sz, port);
sz += 2;
@@ -1243,7 +1259,7 @@ namespace transport
}
});
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, sz), [=](const boost::system::error_code & e, std::size_t transferred) {
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 10), [=](const boost::system::error_code & e, std::size_t transferred) {
if(e)
{
LogPrint(eLogError, "NTCP: socks proxy read error ", e.message());

View File

@@ -167,8 +167,19 @@ namespace transport
boost::asio::io_service& GetService () { return m_Service; };
void SetSessionLimits(uint16_t softLimit, uint16_t hardLimit) { m_SoftLimit = softLimit; m_HardLimit = hardLimit; }
bool ShouldLimit() const { return ShouldHardLimit() || ShouldSoftLimit(); }
private:
/** @brief return true for hard limit */
bool ShouldHardLimit() const { return m_HardLimit && m_NTCPSessions.size() >= m_HardLimit; }
/** @brief return true for probabalistic soft backoff */
bool ShouldSoftLimit() const
{
auto sessions = m_NTCPSessions.size();
return sessions && m_SoftLimit && m_SoftLimit < sessions && ( rand() % sessions ) <= m_SoftLimit;
}
void Run ();
void HandleAccept (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
void HandleAcceptV6 (std::shared_ptr<NTCPSession> conn, const boost::system::error_code& error);
@@ -198,6 +209,8 @@ namespace transport
uint16_t m_ProxyPort;
boost::asio::ip::tcp::resolver m_Resolver;
boost::asio::ip::tcp::endpoint * m_ProxyEndpoint;
uint16_t m_SoftLimit, m_HardLimit;
public:
// for HTTP/I2PControl

View File

@@ -489,6 +489,27 @@ namespace data
std::string Reseeder::HttpsRequest (const std::string& address)
{
i2p::http::URL proxyUrl;
std::string proxy; i2p::config::GetOption("reseed.proxy", proxy);
// check for proxy url
if(proxy.size()) {
// parse
if(proxyUrl.parse(proxy)) {
if (proxyUrl.schema == "http" && !proxyUrl.port) {
proxyUrl.port = 80;
} else if (proxyUrl.schema == "socks" && !proxyUrl.port) {
proxyUrl.port = 1080;
}
// check for valid proxy url schema
if (proxyUrl.schema != "http" && proxyUrl.schema != "socks") {
LogPrint(eLogError, "Reseed: bad proxy url: ", proxy);
return "";
}
} else {
LogPrint(eLogError, "Reseed: bad proxy url: ", proxy);
return "";
}
}
i2p::http::URL url;
if (!url.parse(address)) {
LogPrint(eLogError, "Reseed: failed to parse url: ", address);
@@ -500,68 +521,185 @@ namespace data
boost::asio::io_service service;
boost::system::error_code ecode;
auto it = boost::asio::ip::tcp::resolver(service).resolve (
boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode);
if (!ecode)
boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::context::verify_none);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> s(service, ctx);
if(proxyUrl.schema.size())
{
boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23);
ctx.set_verify_mode(boost::asio::ssl::context::verify_none);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> s(service, ctx);
s.lowest_layer().connect (*it, ecode);
if (!ecode)
// proxy connection
auto it = boost::asio::ip::tcp::resolver(service).resolve (
boost::asio::ip::tcp::resolver::query (proxyUrl.host, std::to_string(proxyUrl.port)), ecode);
if(!ecode)
{
SSL_set_tlsext_host_name(s.native_handle(), url.host.c_str ());
s.handshake (boost::asio::ssl::stream_base::client, ecode);
if (!ecode)
s.lowest_layer().connect(*it, ecode);
if(!ecode)
{
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
i2p::http::HTTPReq req;
req.uri = url.to_string();
req.AddHeader("User-Agent", "Wget/1.11.4");
req.AddHeader("Connection", "close");
s.write_some (boost::asio::buffer (req.to_string()));
// read response
std::stringstream rs;
char recv_buf[1024]; size_t l = 0;
do {
l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
if (l) rs.write (recv_buf, l);
} while (!ecode && l);
// process response
std::string data = rs.str();
i2p::http::HTTPRes res;
int len = res.parse(data);
if (len <= 0) {
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host);
return "";
}
if (res.code != 200) {
LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code);
return "";
}
data.erase(0, len); /* drop http headers from response */
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host);
if (res.is_chunked()) {
std::stringstream in(data), out;
if (!i2p::http::MergeChunkedResponse(in, out)) {
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host);
auto & sock = s.next_layer();
if(proxyUrl.schema == "http")
{
i2p::http::HTTPReq proxyReq;
i2p::http::HTTPRes proxyRes;
proxyReq.method = "CONNECT";
proxyReq.version = "HTTP/1.1";
proxyReq.uri = url.host + ":" + std::to_string(url.port);
boost::asio::streambuf writebuf, readbuf;
std::ostream out(&writebuf);
out << proxyReq.to_string();
boost::asio::write(sock, writebuf.data(), boost::asio::transfer_all(), ecode);
if (ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: HTTP CONNECT write error: ", ecode.message());
return "";
}
boost::asio::read_until(sock, readbuf, "\r\n\r\n", ecode);
if (ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: HTTP CONNECT read error: ", ecode.message());
return "";
}
if(proxyRes.parse(boost::asio::buffer_cast<const char *>(readbuf.data()), readbuf.size()) <= 0)
{
sock.close();
LogPrint(eLogError, "Reseed: HTTP CONNECT malformed reply");
return "";
}
if(proxyRes.code != 200)
{
sock.close();
LogPrint(eLogError, "Reseed: HTTP CONNECT got bad status: ", proxyRes.code);
return "";
}
}
else
{
// assume socks if not http, is checked before this for other types
// TODO: support username/password auth etc
uint8_t hs_writebuf[3] = {0x05, 0x01, 0x00};
uint8_t hs_readbuf[2];
boost::asio::write(sock, boost::asio::buffer(hs_writebuf, 3), boost::asio::transfer_all(), ecode);
if(ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake write failed: ", ecode.message());
return "";
}
boost::asio::read(sock, boost::asio::buffer(hs_readbuf, 2), ecode);
if(ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake read failed: ", ecode.message());
return "";
}
size_t sz = 0;
uint8_t buf[256];
buf[0] = 0x05;
buf[1] = 0x01;
buf[2] = 0x00;
buf[3] = 0x03;
sz += 4;
size_t hostsz = url.host.size();
if(1 + 2 + hostsz + sz > sizeof(buf))
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake failed, hostname too big: ", url.host);
return "";
}
buf[4] = (uint8_t) hostsz;
memcpy(buf+5, url.host.c_str(), hostsz);
sz += hostsz + 1;
htobe16buf(buf+sz, url.port);
sz += 2;
boost::asio::write(sock, boost::asio::buffer(buf, sz), boost::asio::transfer_all(), ecode);
if(ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake failed writing: ", ecode.message());
return "";
}
boost::asio::read(sock, boost::asio::buffer(buf, 10), ecode);
if(ecode)
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake failed reading: ", ecode.message());
return "";
}
if(buf[1] != 0x00)
{
sock.close();
LogPrint(eLogError, "Reseed: SOCKS handshake bad reply code: ", std::to_string(buf[1]));
return "";
}
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host);
data = out.str();
}
return data;
}
else
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
}
else
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
}
else
LogPrint (eLogError, "Reseed: Couldn't resolve address ", url.host, ": ", ecode.message ());
{
// direct connection
auto it = boost::asio::ip::tcp::resolver(service).resolve (
boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode);
if(!ecode)
s.lowest_layer().connect (*it, ecode);
}
if (!ecode)
{
SSL_set_tlsext_host_name(s.native_handle(), url.host.c_str ());
s.handshake (boost::asio::ssl::stream_base::client, ecode);
if (!ecode)
{
LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port);
i2p::http::HTTPReq req;
req.uri = url.to_string();
req.AddHeader("User-Agent", "Wget/1.11.4");
req.AddHeader("Connection", "close");
s.write_some (boost::asio::buffer (req.to_string()));
// read response
std::stringstream rs;
char recv_buf[1024]; size_t l = 0;
do {
l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode);
if (l) rs.write (recv_buf, l);
} while (!ecode && l);
// process response
std::string data = rs.str();
i2p::http::HTTPRes res;
int len = res.parse(data);
if (len <= 0) {
LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host);
return "";
}
if (res.code != 200) {
LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code);
return "";
}
data.erase(0, len); /* drop http headers from response */
LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host);
if (res.is_chunked()) {
std::stringstream in(data), out;
if (!i2p::http::MergeChunkedResponse(in, out)) {
LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host);
return "";
}
LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host);
data = out.str();
}
return data;
}
else
LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ());
}
else
LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ());
return "";
}
}
}
}

View File

@@ -16,8 +16,8 @@ namespace i2p
RouterContext context;
RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_StartupTime (0), m_ShareRatio (100), m_Status (eRouterStatusOK),
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_StartupTime (0), m_ShareRatio (100), m_Status (eRouterStatusOK),
m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID)
{
}
@@ -28,16 +28,17 @@ namespace i2p
m_StartupTime = i2p::util::GetSecondsSinceEpoch ();
if (!Load ())
CreateNewRouter ();
m_Decryptor = m_Keys.CreateDecryptor (nullptr);
UpdateRouterInfo ();
}
void RouterContext::CreateNewRouter ()
{
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
#else
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_DSA_SHA1);
#endif
#endif
SaveKeys ();
NewRouterInfo ();
}
@@ -75,7 +76,7 @@ namespace i2p
std::string host = "::";
if (!i2p::config::IsDefault("host") && !ipv4) // override if v6 only
i2p::config::GetOption("host", host);
else if (!ifname.empty())
else if (!ifname.empty())
host = i2p::util::net::GetInterfaceAddress(ifname, true).to_string(); // v6
if(ifname6.size())
@@ -84,10 +85,10 @@ namespace i2p
routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ());
routerInfo.AddNTCPAddress (host.c_str(), port);
}
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
routerInfo.SetCaps (i2p::data::RouterInfo::eReachable |
i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("netId", std::to_string (m_NetID));
routerInfo.SetProperty ("router.version", I2P_VERSION);
routerInfo.CreateBuffer (m_Keys);
m_RouterInfo.SetRouterIdentity (GetIdentity ());
@@ -99,39 +100,39 @@ namespace i2p
m_RouterInfo.CreateBuffer (m_Keys);
m_RouterInfo.SaveToFile (i2p::fs::DataDirPath (ROUTER_INFO));
m_LastUpdateTime = i2p::util::GetSecondsSinceEpoch ();
}
}
void RouterContext::SetStatus (RouterStatus status)
{
void RouterContext::SetStatus (RouterStatus status)
{
if (status != m_Status)
{
{
m_Status = status;
m_Error = eRouterErrorNone;
switch (m_Status)
{
{
case eRouterStatusOK:
SetReachable ();
break;
case eRouterStatusFirewalled:
SetUnreachable ();
break;
break;
default:
;
}
}
}
}
void RouterContext::UpdatePort (int port)
{
bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ())
{
if (address->port != port)
{
{
address->port = port;
updated = true;
}
}
}
}
if (updated)
UpdateRouterInfo ();
}
@@ -142,11 +143,11 @@ namespace i2p
for (auto& address : m_RouterInfo.GetAddresses ())
{
if (address->host != host && address->IsCompatible (host))
{
{
address->host = host;
updated = true;
}
}
}
}
auto ts = i2p::util::GetSecondsSinceEpoch ();
if (updated || ts > m_LastUpdateTime + ROUTER_INFO_UPDATE_INTERVAL)
UpdateRouterInfo ();
@@ -156,16 +157,16 @@ namespace i2p
{
bool ret = m_RouterInfo.AddIntroducer (introducer);
if (ret)
UpdateRouterInfo ();
UpdateRouterInfo ();
return ret;
}
}
void RouterContext::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e)
{
if (m_RouterInfo.RemoveIntroducer (e))
UpdateRouterInfo ();
}
}
void RouterContext::SetFloodfill (bool floodfill)
{
m_IsFloodfill = floodfill;
@@ -195,19 +196,20 @@ namespace i2p
{
m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY, family);
m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY_SIG, signature);
}
}
else
{
m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY);
m_RouterInfo.DeleteProperty (i2p::data::ROUTER_INFO_PROPERTY_FAMILY_SIG);
}
}
}
}
void RouterContext::SetBandwidth (char L) {
uint16_t limit = 0;
void RouterContext::SetBandwidth (char L)
{
uint32_t limit = 0;
enum { low, high, extra, unlim } type = high;
/* detect parameters */
switch (L)
switch (L)
{
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH1 : limit = 12; type = low; break;
case i2p::data::CAPS_FLAG_LOW_BANDWIDTH2 : limit = 48; type = low; break;
@@ -215,7 +217,7 @@ namespace i2p
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH2 : limit = 128; type = high; break;
case i2p::data::CAPS_FLAG_HIGH_BANDWIDTH3 : limit = 256; type = high; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH1 : limit = 2048; type = extra; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 9999; type = unlim; break;
case i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2 : limit = 1000000; type = unlim; break; // 1Gbyte/s
default:
limit = 48; type = low;
}
@@ -223,7 +225,7 @@ namespace i2p
auto caps = m_RouterInfo.GetCaps ();
caps &= ~i2p::data::RouterInfo::eHighBandwidth;
caps &= ~i2p::data::RouterInfo::eExtraBandwidth;
switch (type)
switch (type)
{
case low : /* not set */; break;
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
@@ -235,7 +237,7 @@ namespace i2p
m_BandwidthLimit = limit;
}
void RouterContext::SetBandwidth (int limit)
void RouterContext::SetBandwidth (int limit)
{
if (limit > 2000) { SetBandwidth('X'); }
else if (limit > 256) { SetBandwidth('P'); }
@@ -256,8 +258,8 @@ namespace i2p
bool RouterContext::IsUnreachable () const
{
return m_RouterInfo.GetCaps () & i2p::data::RouterInfo::eUnreachable;
}
}
void RouterContext::SetUnreachable ()
{
// set caps
@@ -266,7 +268,7 @@ namespace i2p
caps |= i2p::data::RouterInfo::eUnreachable;
caps &= ~i2p::data::RouterInfo::eFloodfill; // can't be floodfill
caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
m_RouterInfo.SetCaps (caps);
m_RouterInfo.SetCaps (caps);
// remove NTCP address
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto it = addresses.begin (); it != addresses.end (); ++it)
@@ -277,12 +279,12 @@ namespace i2p
addresses.erase (it);
break;
}
}
}
// delete previous introducers
for (auto& addr : addresses)
for (auto& addr : addresses)
if (addr->ssu)
addr->ssu->introducers.clear ();
// update
UpdateRouterInfo ();
}
@@ -297,7 +299,7 @@ namespace i2p
if (m_IsFloodfill)
caps |= i2p::data::RouterInfo::eFloodfill;
m_RouterInfo.SetCaps (caps);
// insert NTCP back
auto& addresses = m_RouterInfo.GetAddresses ();
for (const auto& addr : addresses)
@@ -309,16 +311,16 @@ namespace i2p
m_RouterInfo.AddNTCPAddress (addr->host.to_string ().c_str (), addr->port);
break;
}
}
}
// delete previous introducers
for (auto& addr : addresses)
if (addr->ssu)
addr->ssu->introducers.clear ();
// update
UpdateRouterInfo ();
}
}
void RouterContext::SetSupportsV6 (bool supportsV6)
{
if (supportsV6)
@@ -327,7 +329,7 @@ namespace i2p
m_RouterInfo.DisableV6 ();
UpdateRouterInfo ();
}
void RouterContext::SetSupportsV4 (bool supportsV4)
{
if (supportsV4)
@@ -336,11 +338,11 @@ namespace i2p
m_RouterInfo.DisableV4 ();
UpdateRouterInfo ();
}
void RouterContext::UpdateNTCPV6Address (const boost::asio::ip::address& host)
{
bool updated = false, found = false;
bool updated = false, found = false;
int port = 0;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr: addresses)
@@ -352,24 +354,24 @@ namespace i2p
addr->host = host;
updated = true;
}
found = true;
}
found = true;
}
else
port = addr->port;
}
port = addr->port;
}
if (!found)
{
// create new address
m_RouterInfo.AddNTCPAddress (host.to_string ().c_str (), port);
auto mtu = i2p::util::net::GetMTU (host);
if (mtu)
{
{
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
if (mtu > 1472) { // TODO: magic constant
mtu = 1472;
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of 1472 bytes");
}
}
}
m_RouterInfo.AddSSUAddress (host.to_string ().c_str (), port, GetIdentHash (), mtu ? mtu : 1472); // TODO
updated = true;
}
@@ -384,21 +386,21 @@ namespace i2p
// update routers and leasesets
m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_LEASESETS, std::to_string(i2p::data::netdb.GetNumLeaseSets ()));
m_RouterInfo.SetProperty (i2p::data::ROUTER_INFO_PROPERTY_ROUTERS, std::to_string(i2p::data::netdb.GetNumRouters ()));
UpdateRouterInfo ();
UpdateRouterInfo ();
}
}
bool RouterContext::Load ()
{
std::ifstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ifstream::in | std::ifstream::binary);
if (!fk.is_open ()) return false;
fk.seekg (0, std::ios::end);
size_t len = fk.tellg();
fk.seekg (0, std::ios::beg);
fk.seekg (0, std::ios::beg);
if (len == sizeof (i2p::data::Keys)) // old keys file format
{
i2p::data::Keys keys;
i2p::data::Keys keys;
fk.read ((char *)&keys, sizeof (keys));
m_Keys = keys;
}
@@ -411,7 +413,7 @@ namespace i2p
}
m_RouterInfo.SetRouterIdentity (GetIdentity ());
i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO));
i2p::data::RouterInfo routerInfo(i2p::fs::DataDirPath (ROUTER_INFO));
if (!routerInfo.IsUnreachable ()) // router.info looks good
{
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
@@ -426,16 +428,16 @@ namespace i2p
{
LogPrint (eLogError, ROUTER_INFO, " is malformed. Creating new");
NewRouterInfo ();
}
}
if (IsUnreachable ())
SetReachable (); // we assume reachable until we discover firewall through peer tests
return true;
}
void RouterContext::SaveKeys ()
{
{
// save in the same format as .dat files
std::ofstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ofstream::binary | std::ofstream::out);
size_t len = m_Keys.GetFullLen ();
@@ -447,34 +449,39 @@ namespace i2p
std::shared_ptr<i2p::tunnel::TunnelPool> RouterContext::GetTunnelPool () const
{
return i2p::tunnel::tunnels.GetExploratoryPool ();
}
return i2p::tunnel::tunnels.GetExploratoryPool ();
}
void RouterContext::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from)
{
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from));
i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len), from));
}
void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
std::unique_lock<std::mutex> l(m_GarlicMutex);
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
}
}
void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
{
std::unique_lock<std::mutex> l(m_GarlicMutex);
i2p::garlic::GarlicDestination::ProcessDeliveryStatusMessage (msg);
}
}
void RouterContext::CleanupDestination ()
{
std::unique_lock<std::mutex> l(m_GarlicMutex);
i2p::garlic::GarlicDestination::CleanupExpiredTags ();
}
uint32_t RouterContext::GetUptime () const
{
return i2p::util::GetSecondsSinceEpoch () - m_StartupTime;
}
}
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
{
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx) : false;
}
}

View File

@@ -48,8 +48,8 @@ namespace i2p
{
return std::shared_ptr<i2p::garlic::GarlicDestination> (this,
[](i2p::garlic::GarlicDestination *) {});
}
}
uint32_t GetUptime () const;
uint32_t GetStartupTime () const { return m_StartupTime; };
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
@@ -89,8 +89,7 @@ namespace i2p
// implements LocalDestination
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
const uint8_t * GetEncryptionPrivateKey () const { return m_Keys.GetPrivateKey (); };
const uint8_t * GetEncryptionPublicKey () const { return GetIdentity ()->GetStandardIdentity ().publicKey; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); };
void SetLeaseSetUpdated () {};
@@ -115,6 +114,7 @@ namespace i2p
i2p::data::RouterInfo m_RouterInfo;
i2p::data::PrivateKeys m_Keys;
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
uint64_t m_LastUpdateTime;
bool m_AcceptsTunnels, m_IsFloodfill;
uint64_t m_StartupTime; // in seconds since epoch

View File

@@ -132,6 +132,13 @@ namespace data
}
if (verifySignature)
{
// reject RSA signatures
if (m_RouterIdentity->IsRSA ())
{
LogPrint (eLogError, "RouterInfo: RSA signature type is not allowed");
m_IsUnreachable = true;
return;
}
// verify signature
int l = m_BufferLen - m_RouterIdentity->GetSignatureLen ();
if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l))
@@ -166,7 +173,6 @@ namespace data
for (int i = 0; i < numAddresses; i++)
{
uint8_t supportedTransports = 0;
bool isValidAddress = true;
auto address = std::make_shared<Address>();
s.read ((char *)&address->cost, sizeof (address->cost));
s.read ((char *)&address->date, sizeof (address->date));
@@ -269,7 +275,8 @@ namespace data
}
if (!s) return;
}
if (isValidAddress)
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
if (supportedTransports)
{
addresses->push_back(address);
m_SupportedTransports |= supportedTransports;
@@ -828,5 +835,12 @@ namespace data
m_Profile = GetRouterProfile (GetIdentHash ());
return m_Profile;
}
void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
{
auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr);
if (encryptor)
encryptor->Encrypt (data, encrypted, ctx);
}
}
}

View File

@@ -181,12 +181,13 @@ namespace data
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
bool IsNewer (const uint8_t * buf, size_t len) const;
/** return true if we are in a router family and the signature is valid */
bool IsFamily(const std::string & fam) const;
/** return true if we are in a router family and the signature is valid */
bool IsFamily(const std::string & fam) const;
// implements RoutingDestination
const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); };
const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; };
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
bool IsDestination () const { return false; };
private:

View File

@@ -353,6 +353,7 @@ namespace crypto
BN_mod_mul (x, x, I, q, ctx);
if (BN_is_odd (x))
BN_sub (x, q, x);
BN_CTX_end (ctx);
return x;
}
@@ -370,7 +371,7 @@ namespace crypto
buf1[0] &= 0x7f; // clear highest bit
BIGNUM * y = BN_new ();
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
auto x = RecoverX (y, ctx);
BIGNUM * x = RecoverX (y, ctx);
if (BN_is_bit_set (x, 0) != isHighestBitSet)
BN_sub (x, q, x); // x = q - x
BIGNUM * z = BN_new (), * t = BN_new ();

View File

@@ -363,31 +363,43 @@ namespace crypto
// EdDSA
struct EDDSAPoint
{
BIGNUM * x, * y;
BIGNUM * z, * t; // projective coordinates
EDDSAPoint (): x(nullptr), y(nullptr), z(nullptr), t(nullptr) {};
EDDSAPoint (const EDDSAPoint& other): x(nullptr), y(nullptr), z(nullptr), t(nullptr)
{ *this = other; };
EDDSAPoint (EDDSAPoint&& other): x(nullptr), y(nullptr), z(nullptr), t(nullptr)
{ *this = std::move (other); };
EDDSAPoint (BIGNUM * x1, BIGNUM * y1, BIGNUM * z1 = nullptr, BIGNUM * t1 = nullptr): x(x1), y(y1), z(z1), t(t1) {};
~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); };
BIGNUM * x {nullptr};
BIGNUM * y {nullptr};
BIGNUM * z {nullptr};
BIGNUM * t {nullptr}; // projective coordinates
EDDSAPoint () {}
EDDSAPoint (const EDDSAPoint& other) { *this = other; }
EDDSAPoint (EDDSAPoint&& other) { *this = std::move (other); }
EDDSAPoint (BIGNUM * x1, BIGNUM * y1, BIGNUM * z1 = nullptr, BIGNUM * t1 = nullptr)
: x(x1)
, y(y1)
, z(z1)
, t(t1)
{}
~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); }
EDDSAPoint& operator=(EDDSAPoint&& other)
{
if (x) BN_free (x); x = other.x; other.x = nullptr;
if (y) BN_free (y); y = other.y; other.y = nullptr;
if (z) BN_free (z); z = other.z; other.z = nullptr;
if (t) BN_free (t); t = other.t; other.t = nullptr;
if (this != &other)
{
BN_free (x); x = other.x; other.x = nullptr;
BN_free (y); y = other.y; other.y = nullptr;
BN_free (z); z = other.z; other.z = nullptr;
BN_free (t); t = other.t; other.t = nullptr;
}
return *this;
}
EDDSAPoint& operator=(const EDDSAPoint& other)
{
if (x) BN_free (x); x = other.x ? BN_dup (other.x) : nullptr;
if (y) BN_free (y); y = other.y ? BN_dup (other.y) : nullptr;
if (z) BN_free (z); z = other.z ? BN_dup (other.z) : nullptr;
if (t) BN_free (t); t = other.t ? BN_dup (other.t) : nullptr;
if (this != &other)
{
BN_free (x); x = other.x ? BN_dup (other.x) : nullptr;
BN_free (y); y = other.y ? BN_dup (other.y) : nullptr;
BN_free (z); z = other.z ? BN_dup (other.z) : nullptr;
BN_free (t); t = other.t ? BN_dup (other.t) : nullptr;
}
return *this;
}

View File

@@ -62,6 +62,7 @@ namespace stream
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service),
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO),
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0)
{
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
@@ -73,7 +74,8 @@ namespace stream
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE),
m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0)
m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0)
{
RAND_bytes ((uint8_t *)&m_RecvStreamID, 4);
}
@@ -161,7 +163,7 @@ namespace stream
{
m_IsAckSendScheduled = true;
auto ackTimeout = m_RTT/10;
if (ackTimeout > ACK_SEND_TIMEOUT) ackTimeout = ACK_SEND_TIMEOUT;
if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay;
m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout));
m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
shared_from_this (), std::placeholders::_1));
@@ -199,7 +201,7 @@ namespace stream
{
// wait for SYN
m_IsAckSendScheduled = true;
m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ACK_SEND_TIMEOUT));
m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT));
m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer,
shared_from_this (), std::placeholders::_1));
}
@@ -228,6 +230,13 @@ namespace stream
if (flags & PACKET_FLAG_FROM_INCLUDED)
{
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, packet->GetOptionSize ());
if (m_RemoteIdentity->IsRSA ())
{
LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded");
m_LocalDestination.DeletePacket (packet);
Terminate ();
return;
}
optionData += m_RemoteIdentity->GetFullLen ();
if (!m_RemoteLeaseSet)
LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID);
@@ -244,16 +253,23 @@ namespace stream
{
uint8_t signature[256];
auto signatureLen = m_RemoteIdentity->GetSignatureLen ();
memcpy (signature, optionData, signatureLen);
memset (const_cast<uint8_t *>(optionData), 0, signatureLen);
if (!m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature))
if(signatureLen <= sizeof(signature))
{
LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID);
Close ();
flags |= PACKET_FLAG_CLOSE;
memcpy (signature, optionData, signatureLen);
memset (const_cast<uint8_t *>(optionData), 0, signatureLen);
if (!m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature))
{
LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID);
Close ();
flags |= PACKET_FLAG_CLOSE;
}
memcpy (const_cast<uint8_t *>(optionData), signature, signatureLen);
optionData += signatureLen;
}
else
{
LogPrint(eLogError, "Streaming: Signature too big, ", signatureLen, " bytes");
}
memcpy (const_cast<uint8_t *>(optionData), signature, signatureLen);
optionData += signatureLen;
}
packet->offset = packet->GetPayload () - packet->buf;
@@ -798,7 +814,7 @@ namespace stream
{
if (m_LastReceivedSequenceNumber < 0)
{
LogPrint (eLogWarning, "Streaming: SYN has not been received after ", ACK_SEND_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID);
LogPrint (eLogWarning, "Streaming: SYN has not been received after ", SYN_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID);
m_Status = eStreamStatusReset;
Close ();
return;
@@ -882,7 +898,8 @@ namespace stream
m_PendingIncomingTimer (m_Owner->GetService ()),
m_ConnTrackTimer(m_Owner->GetService()),
m_ConnsPerMinute(DEFAULT_MAX_CONNS_PER_MIN),
m_LastBanClear(i2p::util::GetMillisecondsSinceEpoch())
m_LastBanClear(i2p::util::GetMillisecondsSinceEpoch()),
m_EnableDrop(false)
{
}
@@ -946,7 +963,7 @@ namespace stream
auto incomingStream = CreateNewIncomingStream ();
incomingStream->HandleNextPacket (packet); // SYN
auto ident = incomingStream->GetRemoteIdentity();
if(ident)
if(ident && m_EnableDrop)
{
auto ih = ident->GetIdentHash();
if(DropNewStream(ih))
@@ -1153,6 +1170,7 @@ namespace stream
void StreamingDestination::SetMaxConnsPerMinute(const uint32_t conns)
{
m_EnableDrop = conns > 0;
m_ConnsPerMinute = conns;
LogPrint(eLogDebug, "Streaming: Set max conns per minute per destination to ", conns);
}

View File

@@ -42,13 +42,13 @@ namespace stream
const size_t STREAMING_MTU = 1730;
const size_t MAX_PACKET_SIZE = 4096;
const size_t COMPRESSION_THRESHOLD_SIZE = 66;
const int ACK_SEND_TIMEOUT = 200; // in milliseconds
const int MAX_NUM_RESEND_ATTEMPTS = 6;
const int WINDOW_SIZE = 6; // in messages
const int MIN_WINDOW_SIZE = 1;
const int MAX_WINDOW_SIZE = 128;
const int INITIAL_RTT = 8000; // in milliseconds
const int INITIAL_RTO = 9000; // in milliseconds
const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds
const size_t MAX_PENDING_INCOMING_BACKLOG = 128;
const int PENDING_INCOMING_TIMEOUT = 10; // in seconds
const int MAX_RECEIVE_TIMEOUT = 30; // in seconds
@@ -242,7 +242,7 @@ namespace stream
std::mutex m_SendBufferMutex;
SendBufferQueue m_SendBuffer;
int m_WindowSize, m_RTT, m_RTO;
int m_WindowSize, m_RTT, m_RTO, m_AckDelay;
uint64_t m_LastWindowSizeIncreaseTime;
int m_NumResendAttempts;
};
@@ -276,8 +276,8 @@ namespace stream
/** set max connections per minute per destination */
void SetMaxConnsPerMinute(const uint32_t conns);
Packet * NewPacket () { return m_PacketsPool.Acquire (); };
void DeletePacket (Packet * p) { if (p) m_PacketsPool.Release (p); };
Packet * NewPacket () { return m_PacketsPool.Acquire (); }
void DeletePacket (Packet * p) { m_PacketsPool.Release (p); }
private:
@@ -317,6 +317,7 @@ namespace stream
uint64_t m_LastBanClear;
i2p::util::MemoryPool<Packet> m_PacketsPool;
bool m_EnableDrop;
public:

View File

@@ -102,9 +102,14 @@ namespace transport
void DHKeysPairSupplier::Return (std::shared_ptr<i2p::crypto::DHKeys> pair)
{
std::unique_lock<std::mutex>l(m_AcquiredMutex);
if ((int)m_Queue.size () < 2*m_QueueSize)
m_Queue.push (pair);
if (pair)
{
std::unique_lock<std::mutex>l(m_AcquiredMutex);
if ((int)m_Queue.size () < 2*m_QueueSize)
m_Queue.push (pair);
}
else
LogPrint(eLogError, "Transports: return null DHKeys");
}
Transports transports;
@@ -142,13 +147,20 @@ namespace transport
m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service);
}
i2p::config::GetOption("nat", m_IsNAT);
i2p::config::GetOption("nat", m_IsNAT);
m_DHKeysPairSupplier.Start ();
m_IsRunning = true;
m_Thread = new std::thread (std::bind (&Transports::Run, this));
std::string ntcpproxy; i2p::config::GetOption("ntcpproxy", ntcpproxy);
i2p::http::URL proxyurl;
uint16_t softLimit, hardLimit;
i2p::config::GetOption("limits.ntcpsoft", softLimit);
i2p::config::GetOption("limits.ntcphard", hardLimit);
if(softLimit > 0 && hardLimit > 0 && softLimit >= hardLimit)
{
LogPrint(eLogError, "ntcp soft limit must be less than ntcp hard limit");
return;
}
if(ntcpproxy.size() && enableNTCP)
{
if(proxyurl.parse(ntcpproxy))
@@ -156,12 +168,11 @@ namespace transport
if(proxyurl.schema == "socks" || proxyurl.schema == "http")
{
m_NTCPServer = new NTCPServer();
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
NTCPServer::ProxyType proxytype = NTCPServer::eSocksProxy;
if (proxyurl.schema == "http")
proxytype = NTCPServer::eHTTPProxy;
m_NTCPServer->UseProxy(proxytype, proxyurl.host, proxyurl.port) ;
m_NTCPServer->Start();
if(!m_NTCPServer->NetworkIsReady())
@@ -188,6 +199,7 @@ namespace transport
if (m_NTCPServer == nullptr && enableNTCP)
{
m_NTCPServer = new NTCPServer ();
m_NTCPServer->SetSessionLimits(softLimit, hardLimit);
m_NTCPServer->Start ();
if (!(m_NTCPServer->IsBoundV6() || m_NTCPServer->IsBoundV4())) {
/** failed to bind to NTCP */
@@ -389,20 +401,27 @@ namespace transport
{
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
{
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
if(m_NTCPServer->UsingProxy())
if(!m_NTCPServer->ShouldLimit())
{
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
std::string addr = address->host.to_string();
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
if(m_NTCPServer->UsingProxy())
{
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
std::string addr = address->host.to_string();
if(address->host.is_v6())
remote = NTCPServer::eIP6Address;
if(address->host.is_v6())
remote = NTCPServer::eIP6Address;
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
}
else
m_NTCPServer->Connect (address->host, address->port, s);
return true;
}
else
m_NTCPServer->Connect (address->host, address->port, s);
return true;
{
LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
}
}
}
else // we don't have address

View File

@@ -5,6 +5,7 @@
#include <functional>
#include <memory>
#include <mutex>
#include <utility>
#include <boost/asio.hpp>
#ifdef ANDROID
@@ -14,7 +15,7 @@ namespace std
template <typename T>
std::string to_string(T value)
{
return boost::lexical_cast<std::string>(value);
return boost::lexical_cast<std::string>(value);
}
inline int stoi(const std::string& str)
@@ -29,12 +30,14 @@ namespace i2p
namespace util
{
template<class T>
template<class T>
class MemoryPool
{
//BOOST_STATIC_ASSERT_MSG(sizeof(T) >= sizeof(void*), "size cannot be less that general pointer size");
public:
MemoryPool (): m_Head (nullptr) {};
MemoryPool (): m_Head (nullptr) {}
~MemoryPool ()
{
while (m_Head)
@@ -48,12 +51,12 @@ namespace util
template<typename... TArgs>
T * Acquire (TArgs&&... args)
{
if (!m_Head) return new T(args...);
if (!m_Head) return new T(std::forward<TArgs>(args)...);
else
{
auto tmp = m_Head;
m_Head = static_cast<T*>(*(void * *)m_Head); // next
return new (tmp)T(args...);
return new (tmp)T(std::forward<TArgs>(args)...);
}
}
@@ -68,14 +71,15 @@ namespace util
template<typename... TArgs>
std::unique_ptr<T, std::function<void(T*)> > AcquireUnique (TArgs&&... args)
{
return std::unique_ptr<T, std::function<void(T*)> >(Acquire (args...),
return std::unique_ptr<T, std::function<void(T*)> >(Acquire (std::forward<TArgs>(args)...),
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
}
template<typename... TArgs>
std::shared_ptr<T> AcquireShared (TArgs&&... args)
{
return std::shared_ptr<T>(Acquire (args...), std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
return std::shared_ptr<T>(Acquire (std::forward<TArgs>(args)...),
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
}
protected:
@@ -88,13 +92,13 @@ namespace util
{
public:
MemoryPoolMt () {};
MemoryPoolMt () {}
template<typename... TArgs>
T * AcquireMt (TArgs&&... args)
{
if (!this->m_Head) return new T(args...);
if (!this->m_Head) return new T(std::forward<TArgs>(args)...);
std::lock_guard<std::mutex> l(m_Mutex);
return this->Acquire (args...);
return this->Acquire (std::forward<TArgs>(args)...);
}
void ReleaseMt (T * t)

View File

@@ -7,7 +7,7 @@
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
#define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 15
#define I2PD_VERSION_MINOR 17
#define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
@@ -21,7 +21,7 @@
#define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 31
#define I2P_VERSION_MICRO 32
#define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

View File

@@ -8,9 +8,8 @@ namespace i2p
{
namespace client
{
BOBI2PInboundTunnel::BOBI2PInboundTunnel (int port, std::shared_ptr<ClientDestination> localDestination):
BOBI2PTunnel (localDestination),
m_Acceptor (localDestination->GetService (), boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port))
BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr<ClientDestination> localDestination):
BOBI2PTunnel (localDestination), m_Acceptor (localDestination->GetService (), ep)
{
}
@@ -189,10 +188,22 @@ namespace client
}
}
void BOBDestination::CreateInboundTunnel (int port)
void BOBDestination::CreateInboundTunnel (int port, const std::string& address)
{
if (!m_InboundTunnel)
m_InboundTunnel = new BOBI2PInboundTunnel (port, m_LocalDestination);
{
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), port);
if (!address.empty ())
{
boost::system::error_code ec;
auto addr = boost::asio::ip::address::from_string (address, ec);
if (!ec)
ep.address (addr);
else
LogPrint (eLogError, "BOB: ", ec.message ());
}
m_InboundTunnel = new BOBI2PInboundTunnel (ep, m_LocalDestination);
}
}
void BOBDestination::CreateOutboundTunnel (const std::string& address, int port, bool quiet)
@@ -365,7 +376,7 @@ namespace client
m_Owner.AddDestination (m_Nickname, m_CurrentDestination);
}
if (m_InPort)
m_CurrentDestination->CreateInboundTunnel (m_InPort);
m_CurrentDestination->CreateInboundTunnel (m_InPort, m_Address);
if (m_OutPort && !m_Address.empty ())
m_CurrentDestination->CreateOutboundTunnel (m_Address, m_OutPort, m_IsQuiet);
m_CurrentDestination->Start ();
@@ -422,8 +433,29 @@ namespace client
void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len)
{
LogPrint (eLogDebug, "BOB: newkeys");
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys ();
LogPrint (eLogDebug, "BOB: newkeys");
i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1;
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
if (*operand)
{
try
{
char * operand1 = (char *)strchr (operand, ' ');
if (operand1)
{
*operand1 = 0; operand1++;
cryptoType = std::stoi(operand1);
}
signatureType = std::stoi(operand);
}
catch (std::invalid_argument& ex)
{
LogPrint (eLogWarning, "BOB: newkeys ", ex.what ());
}
}
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType);
SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ());
}
@@ -448,7 +480,10 @@ namespace client
void BOBCommandSession::GetdestCommandHandler (const char * operand, size_t len)
{
LogPrint (eLogDebug, "BOB: getdest");
SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ());
if (m_Keys.GetPublic ()) // keys are set ?
SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ());
else
SendReplyError ("keys are not set");
}
void BOBCommandSession::OuthostCommandHandler (const char * operand, size_t len)

View File

@@ -68,7 +68,7 @@ namespace client
public:
BOBI2PInboundTunnel (int port, std::shared_ptr<ClientDestination> localDestination);
BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr<ClientDestination> localDestination);
~BOBI2PInboundTunnel ();
void Start ();
@@ -125,7 +125,7 @@ namespace client
void Start ();
void Stop ();
void StopTunnels ();
void CreateInboundTunnel (int port);
void CreateInboundTunnel (int port, const std::string& address);
void CreateOutboundTunnel (const std::string& address, int port, bool quiet);
const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); };
std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDestination; };

View File

@@ -48,12 +48,13 @@ namespace client
std::shared_ptr<ClientDestination> localDestination;
bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy);
if (httproxy)
if (httproxy)
{
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
if (httpProxyKeys.length () > 0)
{
@@ -68,14 +69,14 @@ namespace client
else
LogPrint(eLogError, "Clients: failed to load HTTP Proxy key");
}
try
try
{
m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination);
m_HttpProxy->Start();
}
catch (std::exception& e)
m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination);
m_HttpProxy->Start();
}
catch (std::exception& e)
{
LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
}
}
@@ -106,7 +107,8 @@ namespace client
}
try
{
m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination);
m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort,
socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination);
m_SocksProxy->Start();
}
catch (std::exception& e)
@@ -253,7 +255,7 @@ namespace client
void ClientContext::ReloadConfig ()
{
// TODO: handle config changes
// TODO: handle config changes
/*std::string config; i2p::config::GetOption("conf", config);
i2p::config::ParseConfig(config);*/
@@ -269,7 +271,7 @@ namespace client
std::unique_lock<std::mutex> l(m_DestinationsMutex);
for (auto it = m_Destinations.begin (); it != m_Destinations.end ();)
{
auto dest = it->second;
auto dest = it->second;
if (dest->GetRefCounter () > 0) ++it; // skip
else
{
@@ -279,8 +281,16 @@ namespace client
}
}
bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType)
bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType)
{
if (filename == "transient")
{
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType);
LogPrint (eLogInfo, "Clients: New transient keys address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created");
return true;
}
bool success = true;
std::string fullPath = i2p::fs::DataDirPath (filename);
std::ifstream s(fullPath, std::ifstream::binary);
@@ -302,8 +312,8 @@ namespace client
}
else
{
LogPrint (eLogError, "Clients: can't open file ", fullPath, " Creating new one with signature type ", sigType);
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
LogPrint (eLogError, "Clients: can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType);
keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType);
std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out);
size_t len = keys.GetFullLen ();
uint8_t * buf = new uint8_t[len];
@@ -339,10 +349,11 @@ namespace client
return infos;
}
std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType,
const std::map<std::string, std::string> * params)
std::shared_ptr<ClientDestination> ClientContext::CreateNewLocalDestination (bool isPublic,
i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType,
const std::map<std::string, std::string> * params)
{
i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType);
i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType);
auto localDestination = std::make_shared<ClientDestination> (keys, isPublic, params);
std::unique_lock<std::mutex> l(m_DestinationsMutex);
m_Destinations[localDestination->GetIdentHash ()] = localDestination;
@@ -420,6 +431,7 @@ namespace client
options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND);
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY);
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY);
options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY);
}
void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const
@@ -436,7 +448,7 @@ namespace client
if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value))
options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value;
if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value))
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value;
options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value;
}
void ClientContext::ReadTunnels ()
@@ -487,6 +499,7 @@ namespace client
std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
// I2CP
std::map<std::string, std::string> options;
ReadI2CPOptions (section, options);
@@ -495,7 +508,7 @@ namespace client
if (keys.length () > 0)
{
i2p::data::PrivateKeys k;
if(LoadPrivateKeys (k, keys, sigType))
if(LoadPrivateKeys (k, keys, sigType, cryptoType))
{
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
if (!localDestination)
@@ -530,13 +543,14 @@ namespace client
if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS)
{
// socks proxy
clientTunnel = new i2p::proxy::SOCKSProxy(address, port, false, "", destinationPort, localDestination);
clientTunnel = new i2p::proxy::SOCKSProxy(name, address, port, false, "", destinationPort, localDestination);
clientEndpoint = ((i2p::proxy::SOCKSProxy*)clientTunnel)->GetLocalEndpoint ();
}
else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY)
{
// http proxy
clientTunnel = new i2p::proxy::HTTPProxy(address, port, localDestination);
std::string outproxy = section.second.get("outproxy", "");
clientTunnel = new i2p::proxy::HTTPProxy(name, address, port, outproxy, localDestination);
clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint ();
}
else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS)
@@ -551,6 +565,13 @@ namespace client
clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort);
clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetLocalEndpoint ();
}
uint32_t timeout = section.second.get<uint32_t>(I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT, 0);
if(timeout)
{
clientTunnel->SetConnectTimeout(timeout);
LogPrint(eLogInfo, "Clients: I2P Client tunnel connect timeout set to ", timeout);
}
auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr<I2PService>(clientTunnel)));
if (ins.second)
{
@@ -560,8 +581,13 @@ namespace client
else
{
// TODO: update
if (ins.first->second->GetLocalDestination () != clientTunnel->GetLocalDestination ())
{
LogPrint (eLogInfo, "Clients: I2P client tunnel destination updated");
ins.first->second->SetLocalDestination (clientTunnel->GetLocalDestination ());
}
ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, "already exists");
LogPrint (eLogInfo, "Clients: I2P client tunnel for endpoint ", clientEndpoint, " already exists");
}
}
}
@@ -581,6 +607,7 @@ namespace client
std::string webircpass = section.second.get<std::string> (I2P_SERVER_TUNNEL_WEBIRC_PASSWORD, "");
bool gzip = section.second.get (I2P_SERVER_TUNNEL_GZIP, true);
i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
i2p::data::CryptoKeyType cryptoType = section.second.get (I2P_CLIENT_TUNNEL_CRYPTO_TYPE, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
uint32_t maxConns = section.second.get(i2p::stream::I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN, i2p::stream::DEFAULT_MAX_CONNS_PER_MIN);
std::string address = section.second.get<std::string> (I2P_SERVER_TUNNEL_ADDRESS, "127.0.0.1");
bool isUniqueLocal = section.second.get(I2P_SERVER_TUNNEL_ENABLE_UNIQUE_LOCAL, true);
@@ -591,7 +618,7 @@ namespace client
std::shared_ptr<ClientDestination> localDestination = nullptr;
i2p::data::PrivateKeys k;
if(!LoadPrivateKeys (k, keys, sigType))
if(!LoadPrivateKeys (k, keys, sigType, cryptoType))
continue;
localDestination = FindLocalDestination (k.GetPublic ()->GetIdentHash ());
if (!localDestination)
@@ -657,7 +684,7 @@ namespace client
}
auto ins = m_ServerTunnels.insert (std::make_pair (
std::make_pair (localDestination->GetIdentHash (), inPort),
std::unique_ptr<I2PServerTunnel>(serverTunnel)));
std::unique_ptr<I2PServerTunnel>(serverTunnel)));
if (ins.second)
{
serverTunnel->Start ();
@@ -666,6 +693,11 @@ namespace client
else
{
// TODO: update
if (ins.first->second->GetLocalDestination () != serverTunnel->GetLocalDestination ())
{
LogPrint (eLogInfo, "Clients: I2P server tunnel destination updated");
ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
}
ins.first->second->isUpdated = true;
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
}
@@ -715,8 +747,8 @@ namespace client
it = c.erase (it);
}
else
it++;
}
it++;
}
}
template<typename Visitor>

View File

@@ -34,8 +34,10 @@ namespace client
const char I2P_CLIENT_TUNNEL_DESTINATION[] = "destination";
const char I2P_CLIENT_TUNNEL_KEYS[] = "keys";
const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype";
const char I2P_CLIENT_TUNNEL_CRYPTO_TYPE[] = "cryptotype";
const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport";
const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels";
const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout";
const char I2P_SERVER_TUNNEL_HOST[] = "host";
const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride";
const char I2P_SERVER_TUNNEL_PORT[] = "port";
@@ -62,16 +64,21 @@ namespace client
void ReloadConfig ();
std::shared_ptr<ClientDestination> GetSharedLocalDestination () const { return m_SharedLocalDestination; };
std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1,
const std::map<std::string, std::string> * params = nullptr); // transient
std::shared_ptr<ClientDestination> CreateNewLocalDestination (bool isPublic = false, // transient
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL,
const std::map<std::string, std::string> * params = nullptr); // used by SAM only
std::shared_ptr<ClientDestination> CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true,
const std::map<std::string, std::string> * params = nullptr);
const std::map<std::string, std::string> * params = nullptr);
std::shared_ptr<ClientDestination> CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map<std::string, std::string> * params = nullptr);
void DeleteLocalDestination (std::shared_ptr<ClientDestination> destination);
std::shared_ptr<ClientDestination> FindLocalDestination (const i2p::data::IdentHash& destination) const;
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename,
i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256,
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL);
AddressBook& GetAddressBook () { return m_AddressBook; };
const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; };
const SAMBridge * GetSAMBridge () const { return m_SamBridge; };
const I2CPServer * GetI2CPServer () const { return m_I2CPServer; };
@@ -83,8 +90,8 @@ namespace client
template<typename Section, typename Type>
std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const;
template<typename Section>
void ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const;
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const;
void ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const; // for tunnels
void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map<std::string, std::string>& options) const; // for HTTP and SOCKS proxy
void CleanupUDP(const boost::system::error_code & ecode);
void ScheduleCleanupUDP();

View File

@@ -54,7 +54,7 @@ namespace proxy {
void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
void Terminate();
void AsyncSockRead();
bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64);
bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm);
void SanitizeHTTPRequest(i2p::http::HTTPReq & req);
void SentHTTPFailed(const boost::system::error_code & ecode);
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
@@ -67,23 +67,26 @@ namespace proxy {
void ForwardToUpstreamProxy();
void HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec);
void HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec);
void HTTPConnect(const std::string & host, uint16_t port);
void HandleHTTPConnectStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream);
void HandleSocksProxySendHandshake(const boost::system::error_code & ec, std::size_t bytes_transfered);
void HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transfered);
typedef std::function<void(boost::asio::ip::tcp::endpoint)> ProxyResolvedHandler;
void HandleUpstreamProxyResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr, ProxyResolvedHandler handler);
void SocksProxySuccess();
void HandoverToUpstreamProxy();
uint8_t m_recv_chunk[8192];
std::string m_recv_buf; // from client
std::string m_send_buf; // to upstream
std::shared_ptr<boost::asio::ip::tcp::socket> m_sock;
std::shared_ptr<boost::asio::ip::tcp::socket> m_proxysock;
boost::asio::ip::tcp::resolver m_proxy_resolver;
std::string m_OutproxyUrl;
i2p::http::URL m_ProxyURL;
i2p::http::URL m_RequestURL;
uint8_t m_socks_buf[255+8]; // for socks request/response
@@ -97,7 +100,8 @@ namespace proxy {
HTTPReqHandler(HTTPProxy * parent, std::shared_ptr<boost::asio::ip::tcp::socket> sock) :
I2PServiceHandler(parent), m_sock(sock),
m_proxysock(std::make_shared<boost::asio::ip::tcp::socket>(parent->GetService())),
m_proxy_resolver(parent->GetService()) {}
m_proxy_resolver(parent->GetService()),
m_OutproxyUrl(parent->GetOutproxyURL()) {}
~HTTPReqHandler() { Terminate(); }
void Handle () { AsyncSockRead(); } /* overload */
};
@@ -116,7 +120,7 @@ namespace proxy {
void HTTPReqHandler::Terminate() {
if (Kill()) return;
if (m_sock)
if (m_sock)
{
LogPrint(eLogDebug, "HTTPProxy: close sock");
m_sock->close();
@@ -178,13 +182,15 @@ namespace proxy {
std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
}
bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64)
bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm)
{
confirm = false;
const char *param = "i2paddresshelper=";
std::size_t pos = url.query.find(param);
std::size_t len = std::strlen(param);
std::map<std::string, std::string> params;
if (pos == std::string::npos)
return false; /* not found */
if (!url.parse_query(params))
@@ -193,6 +199,8 @@ namespace proxy {
std::string value = params["i2paddresshelper"];
len += value.length();
b64 = i2p::http::UrlDecode(value);
// if we need update exists, request formed with update param
if (params["update"] == "true") { len += std::strlen("&update=true"); confirm = true; }
url.query.replace(pos, len, "");
return true;
}
@@ -200,13 +208,14 @@ namespace proxy {
void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req)
{
/* drop common headers */
req.RemoveHeader ("Referer");
req.RemoveHeader("Referer");
req.RemoveHeader("Via");
req.RemoveHeader("Forwarded");
req.RemoveHeader("Accept-", "Accept-Encoding"); // Accept-*, but Accept-Encoding
req.RemoveHeader("From");
req.RemoveHeader("Forwarded");
req.RemoveHeader("Accept", "Accept-Encoding"); // Accept*, but Accept-Encoding
/* drop proxy-disclosing headers */
req.RemoveHeader("X-Forwarded");
req.RemoveHeader("Proxy-"); // Proxy-*
req.RemoveHeader("Proxy-"); // Proxy-*
/* replace headers */
req.UpdateHeader("User-Agent", "MYOB/6.66 (AN/ON)");
/* add headers */
@@ -237,62 +246,94 @@ namespace proxy {
/* parsing success, now let's look inside request */
LogPrint(eLogDebug, "HTTPProxy: requested: ", m_ClientRequest.uri);
m_RequestURL.parse(m_ClientRequest.uri);
bool m_Confirm;
if (ExtractAddressHelper(m_RequestURL, b64))
if (ExtractAddressHelper(m_RequestURL, b64, m_Confirm))
{
bool addresshelper; i2p::config::GetOption("httpproxy.addresshelper", addresshelper);
if (!addresshelper)
{
LogPrint(eLogWarning, "HTTPProxy: addresshelper disabled");
GenericProxyError("Invalid request", "adddresshelper is not supported");
return true;
}
i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, b64);
LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", m_RequestURL.host);
std::string full_url = m_RequestURL.to_string();
std::stringstream ss;
ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. "
<< "Click <a href=\"" << full_url << "\">here</a> to proceed.";
GenericProxyInfo("Addresshelper found", ss.str().c_str());
return true; /* request processed */
}
SanitizeHTTPRequest(m_ClientRequest);
std::string dest_host = m_RequestURL.host;
uint16_t dest_port = m_RequestURL.port;
/* always set port, even if missing in request */
if (!dest_port)
dest_port = (m_RequestURL.schema == "https") ? 443 : 80;
/* detect dest_host, set proper 'Host' header in upstream request */
if (dest_host != "")
{
/* absolute url, replace 'Host' header */
std::string h = dest_host;
if (dest_port != 0 && dest_port != 80)
h += ":" + std::to_string(dest_port);
m_ClientRequest.UpdateHeader("Host", h);
}
else
{
auto h = m_ClientRequest.GetHeader ("Host");
if (h.length () > 0)
{
/* relative url and 'Host' header provided. transparent proxy mode? */
i2p::http::URL u;
std::string t = "http://" + h;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
}
else
{
/* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request");
LogPrint(eLogWarning, "HTTPProxy: addresshelper request rejected");
GenericProxyError("Invalid request", "addresshelper is not supported");
return true;
}
}
if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm)
{
i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, b64);
LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", m_RequestURL.host);
std::string full_url = m_RequestURL.to_string();
std::stringstream ss;
ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. "
<< "Click <a href=\"" << full_url << "\">here</a> to proceed.";
GenericProxyInfo("Addresshelper found", ss.str().c_str());
return true; /* request processed */
}
else
{
std::stringstream ss;
ss << "Host " << m_RequestURL.host << " <font color=red>already in router's addressbook</font>. "
<< "Click <a href=\"" << m_RequestURL.query << "?i2paddresshelper=" << b64 << "&update=true\">here</a> to update record.";
GenericProxyInfo("Addresshelper found", ss.str().c_str());
return true; /* request processed */
}
}
std::string dest_host;
uint16_t dest_port;
bool useConnect = false;
if(m_ClientRequest.method == "CONNECT")
{
std::string uri(m_ClientRequest.uri);
auto pos = uri.find(":");
if(pos == std::string::npos || pos == uri.size() - 1)
{
GenericProxyError("Invalid Request", "invalid request uri");
return true;
}
else
{
useConnect = true;
dest_port = std::stoi(uri.substr(pos+1));
dest_host = uri.substr(0, pos);
}
}
else
{
SanitizeHTTPRequest(m_ClientRequest);
dest_host = m_RequestURL.host;
dest_port = m_RequestURL.port;
/* always set port, even if missing in request */
if (!dest_port)
dest_port = (m_RequestURL.schema == "https") ? 443 : 80;
/* detect dest_host, set proper 'Host' header in upstream request */
if (dest_host != "")
{
/* absolute url, replace 'Host' header */
std::string h = dest_host;
if (dest_port != 0 && dest_port != 80)
h += ":" + std::to_string(dest_port);
m_ClientRequest.UpdateHeader("Host", h);
}
else
{
auto h = m_ClientRequest.GetHeader ("Host");
if (h.length () > 0)
{
/* relative url and 'Host' header provided. transparent proxy mode? */
i2p::http::URL u;
std::string t = "http://" + h;
u.parse(t);
dest_host = u.host;
dest_port = u.port;
}
else
{
/* relative url and missing 'Host' header */
GenericProxyError("Invalid request", "Can't detect destination host from request");
return true;
}
}
}
/* check dest_host really exists and inside I2P network */
i2p::data::IdentHash identHash;
if (str_rmatch(dest_host, ".i2p")) {
@@ -301,10 +342,9 @@ namespace proxy {
return true; /* request processed */
}
} else {
std::string outproxyUrl; i2p::config::GetOption("httpproxy.outproxy", outproxyUrl);
if(outproxyUrl.size()) {
LogPrint (eLogDebug, "HTTPProxy: use outproxy ", outproxyUrl);
if(m_ProxyURL.parse(outproxyUrl))
if(m_OutproxyUrl.size()) {
LogPrint (eLogDebug, "HTTPProxy: use outproxy ", m_OutproxyUrl);
if(m_ProxyURL.parse(m_OutproxyUrl))
ForwardToUpstreamProxy();
else
GenericProxyError("Outproxy failure", "bad outproxy settings");
@@ -315,6 +355,11 @@ namespace proxy {
}
return true;
}
if(useConnect)
{
HTTPConnect(dest_host, dest_port);
return true;
}
/* make relative url */
m_RequestURL.schema = "";
@@ -346,15 +391,24 @@ namespace proxy {
m_ClientRequest.write(m_ClientRequestBuffer);
m_ClientRequestBuffer << m_recv_buf.substr(m_req_len);
// assume http if empty schema
if (m_ProxyURL.schema == "" || m_ProxyURL.schema == "http") {
// handle upstream http proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 80;
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1));
}));
if (m_ProxyURL.is_i2p())
{
m_send_buf = m_recv_buf;
GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleStreamRequestComplete,
shared_from_this(), std::placeholders::_1), m_ProxyURL.host, m_ProxyURL.port);
}
else
{
boost::asio::ip::tcp::resolver::query q(m_ProxyURL.host, std::to_string(m_ProxyURL.port));
m_proxy_resolver.async_resolve(q, std::bind(&HTTPReqHandler::HandleUpstreamProxyResolved, this, std::placeholders::_1, std::placeholders::_2, [&](boost::asio::ip::tcp::endpoint ep) {
m_proxysock->async_connect(ep, std::bind(&HTTPReqHandler::HandleUpstreamHTTPProxyConnect, this, std::placeholders::_1));
}));
}
} else if (m_ProxyURL.schema == "socks") {
// handle upstream socks proxy
if (!m_ProxyURL.port) m_ProxyURL.port = 9050; // default to tor default if not specified
@@ -371,7 +425,7 @@ namespace proxy {
void HTTPReqHandler::HandleUpstreamProxyResolved(const boost::system::error_code & ec, boost::asio::ip::tcp::resolver::iterator it, ProxyResolvedHandler handler)
{
if(ec) GenericProxyError("cannot resolve upstream proxy", ec.message().c_str());
else handler(*it);
else handler(*it);
}
void HTTPReqHandler::HandleUpstreamSocksProxyConnect(const boost::system::error_code & ec)
@@ -425,7 +479,38 @@ namespace proxy {
connection->Start();
Terminate();
}
void HTTPReqHandler::HTTPConnect(const std::string & host, uint16_t port)
{
LogPrint(eLogDebug, "HTTPProxy: CONNECT ",host, ":", port);
std::string hostname(host);
if(str_rmatch(hostname, ".i2p"))
GetOwner()->CreateStream (std::bind (&HTTPReqHandler::HandleHTTPConnectStreamRequestComplete,
shared_from_this(), std::placeholders::_1), host, port);
else
ForwardToUpstreamProxy();
}
void HTTPReqHandler::HandleHTTPConnectStreamRequestComplete(std::shared_ptr<i2p::stream::Stream> stream)
{
if(stream)
{
m_ClientResponse.code = 200;
m_ClientResponse.status = "OK";
m_send_buf = m_ClientResponse.to_string();
m_sock->send(boost::asio::buffer(m_send_buf));
auto connection = std::make_shared<i2p::client::I2PTunnelConnection>(GetOwner(), m_sock, stream);
GetOwner()->AddHandler(connection);
connection->I2PConnect();
m_sock = nullptr;
Terminate();
}
else
{
GenericProxyError("CONNECT error", "Failed to Connect");
}
}
void HTTPReqHandler::SocksProxySuccess()
{
if(m_ClientRequest.method == "CONNECT") {
@@ -444,7 +529,7 @@ namespace proxy {
});
}
}
void HTTPReqHandler::HandleSocksProxyReply(const boost::system::error_code & ec, std::size_t bytes_transferred)
{
if(!ec)
@@ -462,7 +547,7 @@ namespace proxy {
}
else GenericProxyError("No Reply From socks proxy", ec.message().c_str());
}
void HTTPReqHandler::HandleUpstreamHTTPProxyConnect(const boost::system::error_code & ec)
{
if(!ec) {
@@ -470,12 +555,12 @@ namespace proxy {
GenericProxyError("cannot connect", "http out proxy not implemented");
} else GenericProxyError("cannot connect to upstream http proxy", ec.message().c_str());
}
/* will be called after some data received from client */
void HTTPReqHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len)
{
LogPrint(eLogDebug, "HTTPProxy: sock recv: ", len, " bytes, recv buf: ", m_recv_buf.length(), ", send buf: ", m_send_buf.length());
if(ecode)
if(ecode)
{
LogPrint(eLogWarning, "HTTPProxy: sock recv got error: ", ecode);
Terminate();
@@ -501,7 +586,7 @@ namespace proxy {
{
if (!stream) {
LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info");
GenericProxyError("Host is down", "Can't create connection to requested host, it may be down");
GenericProxyError("Host is down", "Can't create connection to requested host, it may be down. Please try again later.");
return;
}
if (Kill())
@@ -513,11 +598,12 @@ namespace proxy {
Done (shared_from_this());
}
HTTPProxy::HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination):
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ())
HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination):
TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()),
m_Name (name), m_OutproxyUrl(outproxy)
{
}
std::shared_ptr<i2p::client::I2PServiceHandler> HTTPProxy::CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
{
return std::make_shared<HTTPReqHandler> (this, socket);

View File

@@ -6,14 +6,21 @@ namespace proxy {
class HTTPProxy: public i2p::client::TCPIPAcceptor
{
public:
HTTPProxy(const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, std::shared_ptr<i2p::client::ClientDestination> localDestination);
HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr) :
HTTPProxy(name, address, port, "", localDestination) {} ;
~HTTPProxy() {};
std::string GetOutproxyURL() const { return m_OutproxyUrl; }
protected:
// Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return "HTTP Proxy"; }
const char* GetName() { return m_Name.c_str (); }
private:
std::string m_Name;
std::string m_OutproxyUrl;
};
} // http
} // i2p

View File

@@ -31,6 +31,16 @@ namespace client
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
{
memcpy (m_EncryptionPrivateKey, key, 256);
m_Decryptor = i2p::data::PrivateKeys::CreateDecryptor (m_Identity->GetCryptoKeyType (), m_EncryptionPrivateKey);
}
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
{
if (m_Decryptor)
return m_Decryptor->Decrypt (encrypted, data, ctx);
else
LogPrint (eLogError, "I2CP: decryptor is not set");
return false;
}
void I2CPDestination::HandleDataMessage (const uint8_t * buf, size_t len)

View File

@@ -71,7 +71,7 @@ namespace client
void SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce); // called from I2CPSession
// implements LocalDestination
const uint8_t * GetEncryptionPrivateKey () const { return m_EncryptionPrivateKey; };
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Identity; };
protected:
@@ -91,6 +91,7 @@ namespace client
std::shared_ptr<I2CPSession> m_Owner;
std::shared_ptr<const i2p::data::IdentityEx> m_Identity;
uint8_t m_EncryptionPrivateKey[256];
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
uint64_t m_LeaseSetExpirationTime;
};

View File

@@ -2,6 +2,7 @@
#include "Identity.h"
#include "ClientContext.h"
#include "I2PService.h"
#include <boost/asio/error.hpp>
namespace i2p
{
@@ -11,37 +12,99 @@ namespace client
I2PService::I2PService (std::shared_ptr<ClientDestination> localDestination):
m_LocalDestination (localDestination ? localDestination :
i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), isUpdated (true)
i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated (true)
{
m_LocalDestination->Acquire ();
m_LocalDestination->Acquire ();
}
I2PService::I2PService (i2p::data::SigningKeyType kt):
m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)),
m_ReadyTimer(m_LocalDestination->GetService()),
m_ConnectTimeout(0),
isUpdated (true)
{
m_LocalDestination->Acquire ();
}
I2PService::~I2PService ()
{
ClearHandlers ();
if (m_LocalDestination) m_LocalDestination->Release ();
I2PService::~I2PService ()
{
ClearHandlers ();
if (m_LocalDestination) m_LocalDestination->Release ();
}
void I2PService::ClearHandlers ()
{
if(m_ConnectTimeout)
m_ReadyTimer.cancel();
std::unique_lock<std::mutex> l(m_HandlersMutex);
for (auto it: m_Handlers)
it->Terminate ();
m_Handlers.clear();
}
void I2PService::SetConnectTimeout(uint32_t timeout)
{
if(timeout && !m_ConnectTimeout)
{
TriggerReadyCheckTimer();
}
else if (m_ConnectTimeout && !timeout)
{
m_ReadyTimer.cancel();
}
m_ConnectTimeout = timeout;
}
void I2PService::AddReadyCallback(ReadyCallback cb)
{
uint32_t now = i2p::util::GetSecondsSinceEpoch();
uint32_t tm = now + m_ConnectTimeout;
LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now);
m_ReadyCallbacks.push_back({cb, tm});
}
void I2PService::TriggerReadyCheckTimer()
{
m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1));
m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1));
}
void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec)
{
if(ec || m_LocalDestination->IsReady())
{
for(auto & itr : m_ReadyCallbacks)
itr.first(ec);
m_ReadyCallbacks.clear();
}
else if(!m_LocalDestination->IsReady())
{
// expire timed out requests
uint32_t now = i2p::util::GetSecondsSinceEpoch ();
auto itr = m_ReadyCallbacks.begin();
while(itr != m_ReadyCallbacks.end())
{
if(itr->second >= now)
{
itr->first(boost::asio::error::timed_out);
itr = m_ReadyCallbacks.erase(itr);
}
else
++itr;
}
}
if(!ec)
TriggerReadyCheckTimer();
}
void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) {
assert(streamRequestComplete);
i2p::data::IdentHash identHash;
if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash))
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
CreateStream(streamRequestComplete, identHash, port);
else
{
LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest);
@@ -49,6 +112,29 @@ namespace client
}
}
void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash & identHash, int port)
{
if(m_ConnectTimeout)
{
if(m_LocalDestination->IsReady())
m_LocalDestination->CreateStream (streamRequestComplete, identHash, port);
else
{
AddReadyCallback([this, streamRequestComplete, identHash, port] (const boost::system::error_code & ec) {
if(ec)
{
LogPrint(eLogWarning, "I2PService::CeateStream() ", ec.message());
streamRequestComplete(nullptr);
}
else
this->m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
});
}
}
else
m_LocalDestination->CreateStream(streamRequestComplete, identHash, port);
}
TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream)
{
boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE);
@@ -60,7 +146,7 @@ namespace client
{
Terminate();
}
void TCPIPPipe::Start()
{
AsyncReceiveUpstream();
@@ -70,124 +156,127 @@ namespace client
void TCPIPPipe::Terminate()
{
if(Kill()) return;
if (m_up) {
if (m_up->is_open()) {
if (m_up)
{
if (m_up->is_open())
m_up->close();
}
m_up = nullptr;
}
if (m_down) {
if (m_down->is_open()) {
if (m_down)
{
if (m_down->is_open())
m_down->close();
}
m_down = nullptr;
}
Done(shared_from_this());
}
void TCPIPPipe::AsyncReceiveUpstream()
{
if (m_up) {
if (m_up)
{
m_up->async_read_some(boost::asio::buffer(m_upstream_to_down_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
} else {
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
std::bind(&TCPIPPipe::HandleUpstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
else
LogPrint(eLogError, "TCPIPPipe: upstream receive: no socket");
}
void TCPIPPipe::AsyncReceiveDownstream()
{
if (m_down) {
m_down->async_read_some(boost::asio::buffer(m_downstream_to_up_buf, TCP_IP_PIPE_BUFFER_SIZE),
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
} else {
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
std::bind(&TCPIPPipe::HandleDownstreamReceived, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
else
LogPrint(eLogError, "TCPIPPipe: downstream receive: no socket");
}
void TCPIPPipe::UpstreamWrite(size_t len)
{
if (m_up) {
if (m_up)
{
LogPrint(eLogDebug, "TCPIPPipe: upstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_up, boost::asio::buffer(m_upstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(),
std::placeholders::_1)
);
} else {
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleUpstreamWrite,
shared_from_this(),
std::placeholders::_1));
}
else
LogPrint(eLogError, "TCPIPPipe: upstream write: no socket");
}
void TCPIPPipe::DownstreamWrite(size_t len)
{
if (m_down) {
if (m_down)
{
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) len, " bytes written");
boost::asio::async_write(*m_down, boost::asio::buffer(m_downstream_buf, len),
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(),
std::placeholders::_1)
);
} else {
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
boost::asio::transfer_all(),
std::bind(&TCPIPPipe::HandleDownstreamWrite,
shared_from_this(),
std::placeholders::_1));
}
else
LogPrint(eLogError, "TCPIPPipe: downstream write: no socket");
}
void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{
LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received");
if (ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: downstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0 ) {
if (bytes_transfered > 0 )
memcpy(m_upstream_buf, m_downstream_to_up_buf, bytes_transfered);
}
UpstreamWrite(bytes_transfered);
}
}
void TCPIPPipe::HandleDownstreamWrite(const boost::system::error_code & ecode) {
if (ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: downstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
AsyncReceiveUpstream();
}
else
AsyncReceiveUpstream();
}
void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) {
if (ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
AsyncReceiveDownstream();
}
else
AsyncReceiveDownstream();
}
void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered)
{
LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received");
if (ecode) {
if (ecode)
{
LogPrint(eLogError, "TCPIPPipe: upstream read error:" , ecode.message());
if (ecode != boost::asio::error::operation_aborted)
Terminate();
} else {
if (bytes_transfered > 0 ) {
if (bytes_transfered > 0 )
memcpy(m_downstream_buf, m_upstream_to_down_buf, bytes_transfered);
}
DownstreamWrite(bytes_transfered);
}
}
void TCPIPAcceptor::Start ()
{
m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint));
@@ -198,10 +287,10 @@ namespace client
void TCPIPAcceptor::Stop ()
{
if (m_Acceptor)
{
{
m_Acceptor->close();
m_Acceptor.reset (nullptr);
}
}
m_Timer.cancel ();
ClearHandlers();
}
@@ -219,12 +308,12 @@ namespace client
{
LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted");
auto handler = CreateHandler(socket);
if (handler)
if (handler)
{
AddHandler(handler);
handler->Handle();
}
else
}
else
socket->close();
Accept();
}

View File

@@ -14,8 +14,11 @@ namespace i2p
namespace client
{
class I2PServiceHandler;
class I2PService
class I2PService : std::enable_shared_from_this<I2PService>
{
public:
typedef std::function<void(const boost::system::error_code &)> ReadyCallback;
public:
I2PService (std::shared_ptr<ClientDestination> localDestination = nullptr);
I2PService (i2p::data::SigningKeyType kt);
@@ -33,25 +36,41 @@ namespace client
}
void ClearHandlers ();
void SetConnectTimeout(uint32_t timeout);
void AddReadyCallback(ReadyCallback cb);
inline std::shared_ptr<ClientDestination> GetLocalDestination () { return m_LocalDestination; }
inline std::shared_ptr<const ClientDestination> GetLocalDestination () const { return m_LocalDestination; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest) { m_LocalDestination = dest; }
inline void SetLocalDestination (std::shared_ptr<ClientDestination> dest)
{
if (m_LocalDestination) m_LocalDestination->Release ();
if (dest) dest->Acquire ();
m_LocalDestination = dest;
}
void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0);
void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port);
inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); }
virtual void Start () = 0;
virtual void Stop () = 0;
virtual const char* GetName() { return "Generic I2P Service"; }
private:
private:
void TriggerReadyCheckTimer();
void HandleReadyCheckTimer(const boost::system::error_code & ec);
private:
std::shared_ptr<ClientDestination> m_LocalDestination;
std::unordered_set<std::shared_ptr<I2PServiceHandler> > m_Handlers;
std::mutex m_HandlersMutex;
std::vector<std::pair<ReadyCallback, uint32_t> > m_ReadyCallbacks;
boost::asio::deadline_timer m_ReadyTimer;
uint32_t m_ConnectTimeout;
public:
bool isUpdated; // transient, used during reload only
bool isUpdated; // transient, used during reload only
};
/*Simple interface for I2PHandlers, allows detection of finalization amongst other things */
@@ -64,7 +83,7 @@ namespace client
virtual void Handle() {}; //Start handling the socket
void Terminate () { Kill (); };
protected:
// Call when terminating or handing over to avoid race conditions
inline bool Kill () { return m_Dead.exchange(true); }
@@ -74,6 +93,7 @@ namespace client
inline void Done (std::shared_ptr<I2PServiceHandler> me) { if(m_Service) m_Service->RemoveHandler(me); }
// Call to talk with the owner
inline I2PService * GetOwner() { return m_Service; }
private:
I2PService *m_Service;
std::atomic<bool> m_Dead; //To avoid cleaning up multiple times
@@ -82,27 +102,30 @@ namespace client
const size_t TCP_IP_PIPE_BUFFER_SIZE = 8192 * 8;
// bidirectional pipe for 2 tcp/ip sockets
class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe> {
public:
TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
~TCPIPPipe();
void Start();
protected:
void Terminate();
void AsyncReceiveUpstream();
void AsyncReceiveDownstream();
void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleUpstreamWrite(const boost::system::error_code & ecode);
void HandleDownstreamWrite(const boost::system::error_code & ecode);
void UpstreamWrite(size_t len);
void DownstreamWrite(size_t len);
private:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
class TCPIPPipe: public I2PServiceHandler, public std::enable_shared_from_this<TCPIPPipe>
{
public:
TCPIPPipe(I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> upstream, std::shared_ptr<boost::asio::ip::tcp::socket> downstream);
~TCPIPPipe();
void Start();
protected:
void Terminate();
void AsyncReceiveUpstream();
void AsyncReceiveDownstream();
void HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transferred);
void HandleUpstreamWrite(const boost::system::error_code & ecode);
void HandleDownstreamWrite(const boost::system::error_code & ecode);
void UpstreamWrite(size_t len);
void DownstreamWrite(size_t len);
private:
uint8_t m_upstream_to_down_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_to_up_buf[TCP_IP_PIPE_BUFFER_SIZE];
uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_up, m_down;
};
/* TODO: support IPv6 too */
//This is a service that listens for connections on the IP network and interacts with I2P
class TCPIPAcceptor: public I2PService
@@ -124,10 +147,11 @@ namespace client
const boost::asio::ip::tcp::endpoint& GetLocalEndpoint () const { return m_LocalEndpoint; };
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
virtual const char* GetName() { return "Generic TCP/IP accepting daemon"; }
protected:
virtual std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket) = 0;
private:
void Accept();
void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);

View File

@@ -14,29 +14,29 @@ namespace client
static void I2PTunnelSetSocketOptions(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
{
if (socket && socket->is_open())
{
{
boost::asio::socket_base::receive_buffer_size option(I2P_TUNNEL_CONNECTION_BUFFER_SIZE);
socket->set_option(option);
}
}
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port):
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port):
I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()),
m_IsQuiet (true)
{
m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port);
}
}
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream):
std::shared_ptr<boost::asio::ip::tcp::socket> socket, std::shared_ptr<i2p::stream::Stream> stream):
I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream),
m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true)
{
}
I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket, const boost::asio::ip::tcp::endpoint& target, bool quiet):
std::shared_ptr<boost::asio::ip::tcp::socket> socket, const boost::asio::ip::tcp::endpoint& target, bool quiet):
I2PServiceHandler(owner), m_Socket (socket), m_Stream (stream),
m_RemoteEndpoint (target), m_IsQuiet (quiet)
{
@@ -44,15 +44,15 @@ namespace client
I2PTunnelConnection::~I2PTunnelConnection ()
{
}
}
void I2PTunnelConnection::I2PConnect (const uint8_t * msg, size_t len)
{
if (m_Stream)
{
if (msg)
m_Stream->Send (msg, len); // connect and send
else
else
m_Stream->Send (m_Buffer, 0); // connect
}
StreamReceive ();
@@ -68,11 +68,11 @@ namespace client
boost::asio::ip::address ourIP = boost::asio::ip::address_v4 (bytes);
return ourIP;
}
static void MapToLoopback(const std::shared_ptr<boost::asio::ip::tcp::socket> & sock, const i2p::data::IdentHash & addr)
{
// bind to 127.x.x.x address
// bind to 127.x.x.x address
// where x.x.x are first three bytes from ident
auto ourIP = GetLoopbackAddressFor(addr);
sock->bind (boost::asio::ip::tcp::endpoint (ourIP, 0));
@@ -82,7 +82,7 @@ namespace client
void I2PTunnelConnection::Connect (bool isUniqueLocal)
{
I2PTunnelSetSocketOptions(m_Socket);
if (m_Socket)
if (m_Socket)
{
#ifdef __linux__
if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () &&
@@ -96,8 +96,8 @@ namespace client
m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect,
shared_from_this (), std::placeholders::_1));
}
}
}
void I2PTunnelConnection::Terminate ()
{
if (Kill()) return;
@@ -105,21 +105,21 @@ namespace client
{
m_Stream->Close ();
m_Stream.reset ();
}
}
boost::system::error_code ec;
m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); // avoid RST
m_Socket->close ();
Done(shared_from_this ());
}
}
void I2PTunnelConnection::Receive ()
{
m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind(&I2PTunnelConnection::HandleReceived, shared_from_this (),
m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind(&I2PTunnelConnection::HandleReceived, shared_from_this (),
std::placeholders::_1, std::placeholders::_2));
}
}
void I2PTunnelConnection::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode)
@@ -131,21 +131,21 @@ namespace client
}
}
else
{
{
if (m_Stream)
{
{
auto s = shared_from_this ();
m_Stream->AsyncSend (m_Buffer, bytes_transferred,
[s](const boost::system::error_code& ecode)
{
{
if (!ecode)
s->Receive ();
else
s->Terminate ();
});
}
}
}
}
}
void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode)
{
@@ -164,13 +164,13 @@ namespace client
if (m_Stream)
{
if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew ||
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
{
m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular
{
m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE),
std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (),
std::placeholders::_1, std::placeholders::_2),
I2P_TUNNEL_CONNECTION_MAX_IDLE);
}
}
else // closed by peer
{
// get remaning data
@@ -178,10 +178,10 @@ namespace client
if (len > 0) // still some data
Write (m_StreamBuffer, len);
else // no more data
Terminate ();
}
}
}
Terminate ();
}
}
}
void I2PTunnelConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
@@ -207,7 +207,7 @@ namespace client
void I2PTunnelConnection::Write (const uint8_t * buf, size_t len)
{
boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, len), boost::asio::transfer_all (),
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
std::bind (&I2PTunnelConnection::HandleWrite, shared_from_this (), std::placeholders::_1));
}
void I2PTunnelConnection::HandleConnect (const boost::system::error_code& ecode)
@@ -231,8 +231,8 @@ namespace client
memcpy (m_StreamBuffer, dest.c_str (), dest.size ());
}
HandleStreamReceive (boost::system::error_code (), dest.size ());
}
Receive ();
}
Receive ();
}
}
@@ -253,20 +253,20 @@ namespace client
{
if (line == "\r") endOfHeader = true;
else
{
{
if (!m_ConnectionSent && !line.compare(0, 10, "Connection"))
{
{
m_OutHeader << "Connection: close\r\n";
m_ConnectionSent = true;
}
}
else if (!m_ProxyConnectionSent && !line.compare(0, 16, "Proxy-Connection"))
{
{
m_OutHeader << "Proxy-Connection: close\r\n";
m_ProxyConnectionSent = true;
}
}
else
m_OutHeader << line << "\n";
}
}
}
else
break;
@@ -283,10 +283,10 @@ namespace client
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
}
}
}
}
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& host):
I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false), m_From (stream->GetRemoteIdentity ())
{
@@ -297,7 +297,7 @@ namespace client
if (m_HeaderSent)
I2PTunnelConnection::Write (buf, len);
else
{
{
m_InHeader.clear ();
m_InHeader.write ((const char *)buf, len);
std::string line;
@@ -309,12 +309,12 @@ namespace client
{
if (line == "\r") endOfHeader = true;
else
{
{
if (m_Host.length () > 0 && line.find ("Host:") != std::string::npos)
m_OutHeader << "Host: " << m_Host << "\r\n"; // override host
else
m_OutHeader << line << "\n";
}
}
}
else
break;
@@ -335,52 +335,52 @@ namespace client
m_HeaderSent = true;
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
}
}
}
}
I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()),
m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass)
{
}
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass):
I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()),
m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass)
{
}
void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len)
{
void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len)
{
m_OutPacket.str ("");
if (m_NeedsWebIrc)
if (m_NeedsWebIrc)
{
m_NeedsWebIrc = false;
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl;
}
m_NeedsWebIrc = false;
m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl;
}
m_InPacket.clear ();
m_InPacket.write ((const char *)buf, len);
while (!m_InPacket.eof () && !m_InPacket.fail ())
{
m_InPacket.clear ();
m_InPacket.write ((const char *)buf, len);
while (!m_InPacket.eof () && !m_InPacket.fail ())
{
std::string line;
std::getline (m_InPacket, line);
if (line.length () == 0 && m_InPacket.eof ())
m_InPacket.str ("");
auto pos = line.find ("USER");
if (!pos) // start of line
{
pos = line.find (" ");
pos++;
pos = line.find (" ", pos);
pos++;
auto nextpos = line.find (" ", pos);
m_OutPacket << line.substr (0, pos);
m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ());
m_OutPacket << line.substr (nextpos) << '\n';
}
std::getline (m_InPacket, line);
if (line.length () == 0 && m_InPacket.eof ())
m_InPacket.str ("");
auto pos = line.find ("USER");
if (!pos) // start of line
{
pos = line.find (" ");
pos++;
pos = line.find (" ", pos);
pos++;
auto nextpos = line.find (" ", pos);
m_OutPacket << line.substr (0, pos);
m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ());
m_OutPacket << line.substr (nextpos) << '\n';
}
else
m_OutPacket << line << '\n';
}
I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ());
}
m_OutPacket << line << '\n';
}
I2PTunnelConnection::Write ((uint8_t *)m_OutPacket.str ().c_str (), m_OutPacket.str ().length ());
}
/* This handler tries to stablish a connection with the desired server and dies if it fails to do so */
@@ -389,7 +389,7 @@ namespace client
public:
I2PClientTunnelHandler (I2PClientTunnel * parent, i2p::data::IdentHash destination,
int destinationPort, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
I2PServiceHandler(parent), m_DestinationIdentHash(destination),
I2PServiceHandler(parent), m_DestinationIdentHash(destination),
m_DestinationPort (destinationPort), m_Socket(socket) {};
void Handle();
void Terminate();
@@ -402,8 +402,8 @@ namespace client
void I2PClientTunnelHandler::Handle()
{
GetOwner()->GetLocalDestination ()->CreateStream (
std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1),
GetOwner()->CreateStream (
std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1),
m_DestinationIdentHash, m_DestinationPort);
}
@@ -436,12 +436,12 @@ namespace client
Done(shared_from_this());
}
I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort):
TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination),
m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort)
I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort):
TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination),
m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort)
{
}
}
void I2PClientTunnel::Start ()
{
@@ -480,8 +480,8 @@ namespace client
return nullptr;
}
I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination, int inport, bool gzip):
I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination, int inport, bool gzip):
I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false)
{
m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip);
@@ -489,10 +489,10 @@ namespace client
void I2PServerTunnel::Start ()
{
m_Endpoint.port (m_Port);
m_Endpoint.port (m_Port);
boost::system::error_code ec;
auto addr = boost::asio::ip::address::from_string (m_Address, ec);
if (!ec)
if (!ec)
{
m_Endpoint.address (addr);
Accept ();
@@ -500,27 +500,27 @@ namespace client
else
{
auto resolver = std::make_shared<boost::asio::ip::tcp::resolver>(GetService ());
resolver->async_resolve (boost::asio::ip::tcp::resolver::query (m_Address, ""),
std::bind (&I2PServerTunnel::HandleResolve, this,
resolver->async_resolve (boost::asio::ip::tcp::resolver::query (m_Address, ""),
std::bind (&I2PServerTunnel::HandleResolve, this,
std::placeholders::_1, std::placeholders::_2, resolver));
}
}
}
void I2PServerTunnel::Stop ()
{
ClearHandlers ();
}
}
void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver)
{
{
if (!ecode)
{
{
auto addr = (*it).endpoint ().address ();
LogPrint (eLogInfo, "I2PTunnel: server tunnel ", (*it).host_name (), " has been resolved to ", addr);
m_Endpoint.address (addr);
Accept ();
}
Accept ();
}
else
LogPrint (eLogError, "I2PTunnel: Unable to resolve server tunnel address: ", ecode.message ());
}
@@ -528,7 +528,7 @@ namespace client
void I2PServerTunnel::SetAccessList (const std::set<i2p::data::IdentHash>& accessList)
{
m_AccessList = accessList;
m_IsAccessList = true;
m_IsAccessList = true;
}
void I2PServerTunnel::Accept ()
@@ -536,7 +536,7 @@ namespace client
if (m_PortDestination)
m_PortDestination->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1));
auto localDestination = GetLocalDestination ();
auto localDestination = GetLocalDestination ();
if (localDestination)
{
if (!localDestination->IsAcceptingStreams ()) // set it as default if not set yet
@@ -549,7 +549,7 @@ namespace client
void I2PServerTunnel::HandleAccept (std::shared_ptr<i2p::stream::Stream> stream)
{
if (stream)
{
{
if (m_IsAccessList)
{
if (!m_AccessList.count (stream->GetRemoteIdentity ()->GetIdentHash ()))
@@ -563,53 +563,53 @@ namespace client
auto conn = CreateI2PConnection (stream);
AddHandler (conn);
conn->Connect (m_IsUniqueLocal);
}
}
}
std::shared_ptr<I2PTunnelConnection> I2PServerTunnel::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{
return std::make_shared<I2PTunnelConnection> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint ());
}
I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& host, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip),
I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& host, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip),
m_Host (host)
{
}
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{
return std::make_shared<I2PServerTunnelConnectionHTTP> (this, stream,
return std::make_shared<I2PServerTunnelConnectionHTTP> (this, stream,
std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), m_Host);
}
I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& webircpass, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip),
m_WebircPass (webircpass)
{
}
I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address,
int port, std::shared_ptr<ClientDestination> localDestination,
const std::string& webircpass, int inport, bool gzip):
I2PServerTunnel (name, address, port, localDestination, inport, gzip),
m_WebircPass (webircpass)
{
}
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{
return std::make_shared<I2PTunnelConnectionIRC> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), this->m_WebircPass);
}
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelIRC::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
{
return std::make_shared<I2PTunnelConnectionIRC> (this, stream, std::make_shared<boost::asio::ip::tcp::socket> (GetService ()), GetEndpoint (), this->m_WebircPass);
}
void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
std::lock_guard<std::mutex> lock(m_SessionsMutex);
auto session = ObtainUDPSession(from, toPort, fromPort);
session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
session->LastActivity = i2p::util::GetMillisecondsSinceEpoch();
}
void I2PUDPServerTunnel::HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
std::lock_guard<std::mutex> lock(m_SessionsMutex);
auto session = ObtainUDPSession(from, toPort, fromPort);
session->IPSocket.send_to(boost::asio::buffer(buf, len), m_RemoteEndpoint);
session->LastActivity = i2p::util::GetMillisecondsSinceEpoch();
}
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
void I2PUDPServerTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
auto itr = m_Sessions.begin();
while(itr != m_Sessions.end()) {
if(now - (*itr)->LastActivity >= delta )
@@ -617,11 +617,11 @@ namespace client
else
++itr;
}
}
}
void I2PUDPClientTunnel::ExpireStale(const uint64_t delta) {
std::lock_guard<std::mutex> lock(m_SessionsMutex);
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
uint64_t now = i2p::util::GetMillisecondsSinceEpoch();
std::vector<uint16_t> removePorts;
for (const auto & s : m_Sessions) {
if (now - s.second.second >= delta)
@@ -630,40 +630,40 @@ namespace client
for(auto port : removePorts) {
m_Sessions.erase(port);
}
}
}
UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort)
{
auto ih = from.GetIdentHash();
for (auto & s : m_Sessions )
{
if ( s->Identity == ih)
{
/** found existing session */
LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32());
return s;
}
}
{
auto ih = from.GetIdentHash();
for (auto & s : m_Sessions )
{
if ( s->Identity == ih)
{
/** found existing session */
LogPrint(eLogDebug, "UDPServer: found session ", s->IPSocket.local_endpoint(), " ", ih.ToBase32());
return s;
}
}
boost::asio::ip::address addr;
/** create new udp session */
if(m_IsUniqueLocal && m_LocalAddress.is_loopback())
if(m_IsUniqueLocal && m_LocalAddress.is_loopback())
{
auto ident = from.GetIdentHash();
addr = GetLoopbackAddressFor(ident);
}
else
}
else
addr = m_LocalAddress;
boost::asio::ip::udp::endpoint ep(addr, 0);
m_Sessions.push_back(std::make_shared<UDPSession>(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort));
m_Sessions.push_back(std::make_shared<UDPSession>(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort));
auto & back = m_Sessions.back();
return back;
}
}
UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to,
uint16_t ourPort, uint16_t theirPort) :
m_Destination(localDestination->GetDatagramDestination()),
UDPSession::UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
boost::asio::ip::udp::endpoint endpoint, const i2p::data::IdentHash * to,
uint16_t ourPort, uint16_t theirPort) :
m_Destination(localDestination->GetDatagramDestination()),
IPSocket(localDestination->GetService(), localEndpoint),
SendEndpoint(endpoint),
LastActivity(i2p::util::GetMillisecondsSinceEpoch()),
@@ -674,13 +674,12 @@ namespace client
Receive();
}
void UDPSession::Receive() {
LogPrint(eLogDebug, "UDPSession: Receive");
IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU),
FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2));
}
void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len)
{
if(!ecode)
@@ -694,8 +693,6 @@ namespace client
}
}
I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) :
m_IsUniqueLocal(true),
@@ -713,7 +710,7 @@ namespace client
{
auto dgram = m_LocalDest->GetDatagramDestination();
if (dgram) dgram->ResetReceiver();
LogPrint(eLogInfo, "UDPServer: done");
}
@@ -742,7 +739,7 @@ namespace client
}
return sessions;
}
I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
boost::asio::ip::udp::endpoint localEndpoint,
std::shared_ptr<i2p::client::ClientDestination> localDestination,
@@ -759,13 +756,11 @@ namespace client
{
auto dgram = m_LocalDest->CreateDatagramDestination();
dgram->SetReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2P, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5));
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5));
}
void I2PUDPClientTunnel::Start() {
m_LocalDest->Start();
if (m_ResolveThread == nullptr)
@@ -803,14 +798,14 @@ namespace client
m_Sessions[remotePort].second = i2p::util::GetMillisecondsSinceEpoch();
RecvFromLocal();
}
std::vector<std::shared_ptr<DatagramSessionInfo> > I2PUDPClientTunnel::GetSessions()
{
// TODO: implement
std::vector<std::shared_ptr<DatagramSessionInfo> > infos;
return infos;
}
void I2PUDPClientTunnel::TryResolving() {
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
i2p::data::IdentHash * h = new i2p::data::IdentHash;
@@ -846,11 +841,10 @@ namespace client
}
}
else
LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort);
LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort);
}
else
LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32());
}
I2PUDPClientTunnel::~I2PUDPClientTunnel() {
@@ -858,7 +852,7 @@ namespace client
if (dgram) dgram->ResetReceiver();
m_Sessions.clear();
if(m_LocalSocket.is_open())
m_LocalSocket.close();

View File

@@ -29,7 +29,6 @@ namespace client
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
{
public:
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
@@ -41,7 +40,6 @@ namespace client
void Connect (bool isUniqueLocal = true);
protected:
void Terminate ();
void Receive ();
@@ -56,7 +54,6 @@ namespace client
std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
private:
uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
std::shared_ptr<i2p::stream::Stream> m_Stream;
@@ -67,18 +64,15 @@ namespace client
class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
{
public:
I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
std::shared_ptr<i2p::stream::Stream> stream):
I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
protected:
void Write (const uint8_t * buf, size_t len);
private:
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
};
@@ -86,17 +80,14 @@ namespace client
class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
{
public:
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& host);
protected:
void Write (const uint8_t * buf, size_t len);
private:
std::string m_Host;
std::stringstream m_InHeader, m_OutHeader;
bool m_HeaderSent;
@@ -104,35 +95,30 @@ namespace client
};
class I2PTunnelConnectionIRC: public I2PTunnelConnection
{
public:
{
public:
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
std::shared_ptr<boost::asio::ip::tcp::socket> socket,
const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
protected:
void Write (const uint8_t * buf, size_t len);
protected:
void Write (const uint8_t * buf, size_t len);
private:
std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket;
private:
std::shared_ptr<const i2p::data::IdentityEx> m_From;
std::stringstream m_OutPacket, m_InPacket;
bool m_NeedsWebIrc;
std::string m_WebircPass;
};
std::string m_WebircPass;
};
class I2PClientTunnel: public TCPIPAcceptor
{
protected:
// Implements TCPIPAcceptor
std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
public:
I2PClientTunnel (const std::string& name, const std::string& destination,
const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
~I2PClientTunnel () {}
@@ -143,11 +129,9 @@ namespace client
const char* GetName() { return m_Name.c_str (); }
private:
const i2p::data::IdentHash * GetIdentHash ();
private:
std::string m_Name, m_Destination;
const i2p::data::IdentHash * m_DestinationIdentHash;
int m_DestinationPort;
@@ -208,11 +192,11 @@ namespace client
/** server side udp tunnel, many i2p inbound to 1 ip outbound */
class I2PUDPServerTunnel
{
{
public:
I2PUDPServerTunnel(const std::string & name,
std::shared_ptr<i2p::client::ClientDestination> localDestination,
boost::asio::ip::address localAddress,
boost::asio::ip::address localAddress,
boost::asio::ip::udp::endpoint forwardTo, uint16_t port);
~I2PUDPServerTunnel();
/** expire stale udp conversations */
@@ -225,7 +209,6 @@ namespace client
void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
private:
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
@@ -256,22 +239,22 @@ namespace client
void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
private:
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal();
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
void RecvFromLocal();
void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
void TryResolving();
const std::string m_Name;
std::mutex m_SessionsMutex;
std::map<uint16_t, UDPConvo > m_Sessions; // maps i2p port -> local udp convo
std::mutex m_SessionsMutex;
std::map<uint16_t, UDPConvo > m_Sessions; // maps i2p port -> local udp convo
const std::string m_RemoteDest;
std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
const boost::asio::ip::udp::endpoint m_LocalEndpoint;
i2p::data::IdentHash * m_RemoteIdent;
std::thread * m_ResolveThread;
boost::asio::ip::udp::socket m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
boost::asio::ip::udp::socket m_LocalSocket;
boost::asio::ip::udp::endpoint m_RecvEndpoint;
uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
uint16_t RemotePort;
bool m_cancel_resolve;
};
@@ -279,7 +262,6 @@ namespace client
class I2PServerTunnel: public I2PService
{
public:
I2PServerTunnel (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
@@ -298,10 +280,9 @@ namespace client
const char* GetName() { return m_Name.c_str (); }
void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); }
private:
void SetMaxConnsPerMinute(const uint32_t conns) { m_PortDestination->SetMaxConnsPerMinute(conns); }
private:
void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
@@ -310,7 +291,6 @@ namespace client
virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private:
bool m_IsUniqueLocal;
std::string m_Name, m_Address;
int m_Port;
@@ -323,37 +303,30 @@ namespace client
class I2PServerTunnelHTTP: public I2PServerTunnel
{
public:
I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& host,
int inport = 0, bool gzip = true);
int inport = 0, bool gzip = true);
private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private:
std::string m_Host;
};
class I2PServerTunnelIRC: public I2PServerTunnel
{
public:
class I2PServerTunnelIRC: public I2PServerTunnel
{
public:
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
int inport = 0, bool gzip = true);
I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
int inport = 0, bool gzip = true);
private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private:
std::string m_WebircPass;
};
private:
std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
private:
std::string m_WebircPass;
};
}
}

View File

@@ -489,11 +489,15 @@ namespace client
ExtractParams (buf, params);
// extract signature type
i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1;
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
auto it = params.find (SAM_PARAM_SIGNATURE_TYPE);
if (it != params.end ())
// TODO: extract string values
signatureType = std::stoi(it->second);
auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType);
it = params.find (SAM_PARAM_CRYPTO_TYPE);
if (it != params.end ())
cryptoType = std::stoi(it->second);
auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType);
#ifdef _MSC_VER
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY,
keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ());
@@ -692,8 +696,9 @@ namespace client
}
else
{
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
if (m_SocketType != eSAMSocketTypeTerminated) // check for possible race condition with Terminate()
boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred),
std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1));
}
}
@@ -910,14 +915,18 @@ namespace client
{
// extract signature type
i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1;
i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
if (params)
{
auto it = params->find (SAM_PARAM_SIGNATURE_TYPE);
if (it != params->end ())
// TODO: extract string values
signatureType = std::stoi(it->second);
it = params->find (SAM_PARAM_CRYPTO_TYPE);
if (it != params->end ())
cryptoType = std::stoi(it->second);
}
localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, params);
localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, params);
}
if (localDestination)
{

View File

@@ -53,6 +53,7 @@ namespace client
const char SAM_PARAM_DESTINATION[] = "DESTINATION";
const char SAM_PARAM_NAME[] = "NAME";
const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE";
const char SAM_PARAM_CRYPTO_TYPE[] = "CRYPTO_TYPE";
const char SAM_PARAM_SIZE[] = "SIZE";
const char SAM_VALUE_TRANSIENT[] = "TRANSIENT";
const char SAM_VALUE_STREAM[] = "STREAM";

View File

@@ -768,9 +768,10 @@ namespace proxy
shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
SOCKSServer::SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination) :
TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ())
SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port,
bool outEnable, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination) :
TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name)
{
m_UseUpstreamProxy = false;
if (outAddress.length() > 0 && outEnable)

View File

@@ -14,7 +14,7 @@ namespace proxy
class SOCKSServer: public i2p::client::TCPIPAcceptor
{
public:
SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort,
std::shared_ptr<i2p::client::ClientDestination> localDestination = nullptr);
~SOCKSServer() {};
@@ -23,9 +23,11 @@ namespace proxy
protected:
// Implements TCPIPAcceptor
std::shared_ptr<i2p::client::I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
const char* GetName() { return "SOCKS"; }
const char* GetName() { return m_Name.c_str (); }
private:
std::string m_Name;
std::string m_UpstreamProxyAddress;
uint16_t m_UpstreamProxyPort;
bool m_UseUpstreamProxy;

View File

@@ -3,5 +3,7 @@ moc_*
ui_*
qrc_*
i2pd_qt
Makefile
Makefile*
*.stash
object_script.*
i2pd_qt_plugin_import.cpp

View File

@@ -3,14 +3,15 @@
#include "SignatureTypeComboboxFactory.h"
#include "QVBoxLayout"
ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf):
TunnelPane(tunnelsPageUpdateListener, tunconf) {}
ClientTunnelPane::ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow):
TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_, mainWindow) {}
void ClientTunnelPane::setGroupBoxTitle(const QString & title) {
clientTunnelNameGroupBox->setTitle(title);
}
void ClientTunnelPane::deleteClientTunnelForm() {
TunnelPane::deleteTunnelForm();
delete clientTunnelNameGroupBox;
clientTunnelNameGroupBox=nullptr;
@@ -179,6 +180,9 @@ int ClientTunnelPane::appendClientTunnelForm(
QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(updated()));
horizontalLayout_2->addWidget(sigTypeComboBox);
QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_2->addWidget(lockButton2);
widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2));
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer);
tunnelGridLayout->addLayout(horizontalLayout_2);

View File

@@ -14,7 +14,7 @@ class TunnelPane;
class ClientTunnelPane : public TunnelPane {
Q_OBJECT
public:
ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf);
ClientTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ClientTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow);
virtual ~ClientTunnelPane(){}
virtual ServerTunnelPane* asServerTunnelPane();
virtual ClientTunnelPane* asClientTunnelPane();
@@ -68,6 +68,7 @@ private:
}
protected:
virtual bool applyDataFromUIToTunnelConfig() {
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
bool ok=TunnelPane::applyDataFromUIToTunnelConfig();
if(!ok)return false;
ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig();
@@ -78,16 +79,23 @@ protected:
auto portStr=portLineEdit->text();
int portInt=portStr.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit);
return false;
}
ctc->setport(portInt);
ctc->setkeys(keysLineEdit->text().toStdString());
ctc->setaddress(addressLineEdit->text().toStdString());
auto dportStr=portLineEdit->text();
auto dportStr=destinationPortLineEdit->text();
int dportInt=dportStr.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad destinationPort, must be int.")+" "+cannotSaveSettings,destinationPortLineEdit);
return false;
}
ctc->setdestinationPort(dportInt);
ctc->setsigType(readSigTypeComboboxUI(sigTypeComboBox));

View File

@@ -2,8 +2,8 @@
#include "ClientContext.h"
#include "SignatureTypeComboboxFactory.h"
ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf):
TunnelPane(tunnelsPageUpdateListener, tunconf) {}
ServerTunnelPane::ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow):
TunnelPane(tunnelsPageUpdateListener, tunconf, wrongInputPane_, wrongInputLabel_, mainWindow) {}
void ServerTunnelPane::setGroupBoxTitle(const QString & title) {
serverTunnelNameGroupBox->setTitle(title);
@@ -197,6 +197,9 @@ int ServerTunnelPane::appendServerTunnelForm(
QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(updated()));
horizontalLayout_2->addWidget(sigTypeComboBox);
QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_2->addWidget(lockButton2);
widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2));
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer);
tunnelGridLayout->addLayout(horizontalLayout_2);
@@ -263,6 +266,7 @@ int ServerTunnelPane::appendServerTunnelForm(
}
void ServerTunnelPane::deleteServerTunnelForm() {
TunnelPane::deleteTunnelForm();
delete serverTunnelNameGroupBox;//->deleteLater();
serverTunnelNameGroupBox=nullptr;

View File

@@ -1,9 +1,6 @@
#ifndef SERVERTUNNELPANE_H
#define SERVERTUNNELPANE_H
#include "TunnelPane.h"
#include "TunnelsPageUpdateListener.h"
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
@@ -23,6 +20,9 @@
#include "assert.h"
#include "TunnelPane.h"
#include "TunnelsPageUpdateListener.h"
class ServerTunnelConfig;
class ClientTunnelPane;
@@ -31,7 +31,7 @@ class ServerTunnelPane : public TunnelPane {
Q_OBJECT
public:
ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf);
ServerTunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener, ServerTunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow);
virtual ~ServerTunnelPane(){}
virtual ServerTunnelPane* asServerTunnelPane();
@@ -119,6 +119,7 @@ private:
protected:
virtual bool applyDataFromUIToTunnelConfig() {
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
bool ok=TunnelPane::applyDataFromUIToTunnelConfig();
if(!ok)return false;
ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig();
@@ -127,14 +128,20 @@ protected:
auto portStr=portLineEdit->text();
int portInt=portStr.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad port, must be int.")+" "+cannotSaveSettings,portLineEdit);
return false;
}
stc->setport(portInt);
stc->setkeys(keysLineEdit->text().toStdString());
auto str=inPortLineEdit->text();
int inPortInt=str.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad inPort, must be int.")+" "+cannotSaveSettings,inPortLineEdit);
return false;
}
stc->setinPort(inPortInt);
stc->setaccessList(accessListLineEdit->text().toStdString());
@@ -147,7 +154,10 @@ protected:
auto mcStr=maxConnsLineEdit->text();
uint32_t mcInt=(uint32_t)mcStr.toInt(&ok);
if(!ok)return false;
if(!ok){
highlightWrongInput(QApplication::tr("Bad maxConns, must be int.")+" "+cannotSaveSettings,maxConnsLineEdit);
return false;
}
stc->setmaxConns(mcInt);
stc->setgzip(gzipCheckBox->isChecked());

View File

@@ -70,13 +70,6 @@ public:
addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_TC26_A_512_GOSTR3411_512", 0), SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512); //10
if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;}
++index;
// TODO: remove later
addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST", 0), SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST); //65281
if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;}
++index;
addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_TC26_A_512_GOSTR3411_512_TEST", 0), SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST); //65282
if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;}
++index;
if(!foundSelected){
addItem(signatureTypeCombobox, QString::number(selectedSigType), selectedSigType); //unknown sigtype
signatureTypeCombobox->setCurrentIndex(index);

View File

@@ -6,12 +6,25 @@ void TunnelConfig::saveHeaderToStringStream(std::stringstream& out) {
}
void TunnelConfig::saveI2CPParametersToStringStream(std::stringstream& out) {
out << "inbound.length=" << i2cpParameters.getInbound_length().toStdString() << "\n"
<< "outbound.length=" << i2cpParameters.getOutbound_length().toStdString() << "\n"
<< "inbound.quantity=" << i2cpParameters.getInbound_quantity().toStdString() << "\n"
<< "outbound.quantity=" << i2cpParameters.getOutbound_quantity().toStdString() << "\n"
<< "crypto.tagsToSend=" << i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n"
<< "explicitPeers=" << i2cpParameters.getExplicitPeers().toStdString() << "\n\n";
if (i2cpParameters.getInbound_length().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNEL_LENGTH)
out << i2p::client::I2CP_PARAM_INBOUND_TUNNEL_LENGTH << "="
<< i2cpParameters.getInbound_length().toStdString() << "\n";
if (i2cpParameters.getOutbound_length().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNEL_LENGTH)
out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH << "="
<< i2cpParameters.getOutbound_length().toStdString() << "\n";
if (i2cpParameters.getInbound_quantity().toUShort() != i2p::client::DEFAULT_INBOUND_TUNNELS_QUANTITY)
out << i2p::client::I2CP_PARAM_INBOUND_TUNNELS_QUANTITY << "="
<< i2cpParameters.getInbound_quantity().toStdString() << "\n";
if (i2cpParameters.getOutbound_quantity().toUShort() != i2p::client::DEFAULT_OUTBOUND_TUNNELS_QUANTITY)
out << i2p::client::I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY << "="
<< i2cpParameters.getOutbound_quantity().toStdString() << "\n";
if (i2cpParameters.getCrypto_tagsToSend().toUShort() != i2p::client::DEFAULT_TAGS_TO_SEND)
out << i2p::client::I2CP_PARAM_TAGS_TO_SEND << "="
<< i2cpParameters.getCrypto_tagsToSend().toStdString() << "\n";
if (!i2cpParameters.getExplicitPeers().isEmpty()) //todo #947
out << i2p::client::I2CP_PARAM_EXPLICIT_PEERS << "="
<< i2cpParameters.getExplicitPeers().toStdString() << "\n";
out << "\n";
}
void ClientTunnelConfig::saveToStringStream(std::stringstream& out) {

View File

@@ -5,6 +5,7 @@
#include <string>
#include "../../libi2pd_client/ClientContext.h"
#include "../../libi2pd/Destination.h"
#include "TunnelsPageUpdateListener.h"

View File

@@ -1,8 +1,14 @@
#include "TunnelPane.h"
#include "QMessageBox"
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_):
#include "QMessageBox"
#include "mainwindow.h"
#include "ui_mainwindow.h"
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_):
QObject(),
mainWindow(mainWindow_),
wrongInputPane(wrongInputPane_),
wrongInputLabel(wrongInputLabel_),
tunnelConfig(tunnelConfig_),
tunnelsPageUpdateListener(tunnelsPageUpdateListener_),
gridLayoutWidget_2(nullptr) {}
@@ -65,6 +71,9 @@ void TunnelPane::setupTunnelPane(
typeLabel->setObjectName(QStringLiteral("typeLabel"));
horizontalLayout_->addWidget(typeLabel);
horizontalLayout_->addWidget(tunnelTypeComboBox);
QPushButton * lockButton1 = new QPushButton(gridLayoutWidget_2);
horizontalLayout_->addWidget(lockButton1);
widgetlocks.add(new widgetlock(tunnelTypeComboBox, lockButton1));
this->tunnelTypeComboBox=tunnelTypeComboBox;
QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_->addItem(horizontalSpacer);
@@ -176,7 +185,9 @@ void TunnelPane::appendControlsForI2CPParameters(I2CPParameters& i2cpParameters,
void TunnelPane::updated() {
std::string oldName=tunnelConfig->getName();
if(!applyDataFromUIToTunnelConfig())return;//TODO visualise bad input
//validate and show red if invalid
hideWrongInputLabel();
if(!mainWindow->applyTunnelsUiToConfigs())return;
tunnelsPageUpdateListener->updated(oldName, tunnelConfig);
}
@@ -189,6 +200,7 @@ void TunnelPane::deleteButtonReleased() {
switch (ret) {
case QMessageBox::Ok:
// OK was clicked
hideWrongInputLabel();
tunnelsPageUpdateListener->needsDeleting(tunnelConfig->getName());
break;
case QMessageBox::Cancel:
@@ -215,3 +227,23 @@ QString TunnelPane::readTunnelTypeComboboxData() {
i2p::data::SigningKeyType TunnelPane::readSigTypeComboboxUI(QComboBox* sigTypeComboBox) {
return (i2p::data::SigningKeyType) sigTypeComboBox->currentData().toInt();
}
void TunnelPane::deleteTunnelForm() {
widgetlocks.deleteListeners();
}
void TunnelPane::highlightWrongInput(QString warningText, QWidget* controlWithWrongInput) {
wrongInputPane->setVisible(true);
wrongInputLabel->setText(warningText);
mainWindow->adjustSizesAccordingToWrongLabel();
if(controlWithWrongInput){
mainWindow->ui->tunnelsScrollArea->ensureWidgetVisible(controlWithWrongInput);
controlWithWrongInput->setFocus();
}
mainWindow->showTunnelsPage();
}
void TunnelPane::hideWrongInputLabel() const {
wrongInputPane->setVisible(false);
mainWindow->adjustSizesAccordingToWrongLabel();
}

View File

@@ -14,25 +14,39 @@
#include "TunnelConfig.h"
#include <widgetlock.h>
#include <widgetlockregistry.h>
class ServerTunnelPane;
class ClientTunnelPane;
class TunnelConfig;
class I2CPParameters;
class MainWindow;
class TunnelPane : public QObject {
Q_OBJECT
public:
TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf);
TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunconf, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_);
virtual ~TunnelPane(){}
void deleteTunnelForm();
void hideWrongInputLabel() const;
void highlightWrongInput(QString warningText, QWidget* controlWithWrongInput);
virtual ServerTunnelPane* asServerTunnelPane()=0;
virtual ClientTunnelPane* asClientTunnelPane()=0;
protected:
MainWindow* mainWindow;
QWidget * wrongInputPane;
QLabel* wrongInputLabel;
TunnelConfig* tunnelConfig;
widgetlockregistry widgetlocks;
TunnelsPageUpdateListener* tunnelsPageUpdateListener;
QVBoxLayout *tunnelGridLayout;
QGroupBox *tunnelGroupBox;
@@ -78,6 +92,7 @@ protected:
//should be created by factory
i2p::data::SigningKeyType readSigTypeComboboxUI(QComboBox* sigTypeComboBox);
public:
//returns false when invalid data at UI
virtual bool applyDataFromUIToTunnelConfig() {
tunnelConfig->setName(nameLineEdit->text().toStdString());
@@ -90,7 +105,7 @@ protected:
i2cpParams.setCrypto_tagsToSend(crypto_tagsToSendLineEdit->text());
return true;
}
protected:
void setupTunnelPane(
TunnelConfig* tunnelConfig,
QGroupBox *tunnelGroupBox,

View File

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.15.0" android:versionCode="2" android:installLocation="auto">
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.17.0" android:versionCode="2" android:installLocation="auto">
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- <application android:hardwareAccelerated="true" -->

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
../../libi2pd/BloomFilter.cpp \
../../libi2pd/Config.cpp \
../../libi2pd/Crypto.cpp \
../../libi2pd/CryptoKey.cpp \
../../libi2pd/Datagram.cpp \
../../libi2pd/Destination.cpp \
../../libi2pd/Event.cpp \
@@ -87,7 +88,11 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
../../daemon/i2pd.cpp \
../../daemon/I2PControl.cpp \
../../daemon/UnixDaemon.cpp \
../../daemon/UPnP.cpp
../../daemon/UPnP.cpp \
textbrowsertweaked1.cpp \
pagewithbackbutton.cpp \
widgetlock.cpp \
widgetlockregistry.cpp
#qt creator does not handle this well
#SOURCES += $$files(../../libi2pd/*.cpp)
@@ -103,6 +108,7 @@ HEADERS += DaemonQT.h mainwindow.h \
../../libi2pd/BloomFilter.h \
../../libi2pd/Config.h \
../../libi2pd/Crypto.h \
../../libi2pd/CryptoKey.h \
../../libi2pd/Datagram.h \
../../libi2pd/Destination.h \
../../libi2pd/Event.h \
@@ -166,7 +172,11 @@ HEADERS += DaemonQT.h mainwindow.h \
../../daemon/Daemon.h \
../../daemon/HTTPServer.h \
../../daemon/I2PControl.h \
../../daemon/UPnP.h
../../daemon/UPnP.h \
textbrowsertweaked1.h \
pagewithbackbutton.h \
widgetlock.h \
widgetlockregistry.h
INCLUDEPATH += ../../libi2pd
INCLUDEPATH += ../../libi2pd_client
@@ -174,10 +184,31 @@ INCLUDEPATH += ../../daemon
INCLUDEPATH += .
FORMS += mainwindow.ui \
tunnelform.ui
tunnelform.ui \
statusbuttons.ui \
routercommandswidget.ui \
generalsettingswidget.ui
LIBS += -lz
macx {
message("using mac os x target")
BREWROOT=/usr/local
BOOSTROOT=$$BREWROOT/opt/boost
SSLROOT=$$BREWROOT/opt/libressl
UPNPROOT=$$BREWROOT/opt/miniupnpc
INCLUDEPATH += $$BOOSTROOT/include
INCLUDEPATH += $$SSLROOT/include
INCLUDEPATH += $$UPNPROOT/include
LIBS += $$SSLROOT/lib/libcrypto.a
LIBS += $$SSLROOT/lib/libssl.a
LIBS += $$BOOSTROOT/lib/libboost_system.a
LIBS += $$BOOSTROOT/lib/libboost_date_time.a
LIBS += $$BOOSTROOT/lib/libboost_filesystem.a
LIBS += $$BOOSTROOT/lib/libboost_program_options.a
LIBS += $$UPNPROOT/lib/libminiupnpc.a
}
android {
message("Using Android settings")
DEFINES += ANDROID=1

View File

@@ -1,5 +1,12 @@
#include <fstream>
#include <assert.h>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_statusbuttons.h"
#include "ui_routercommandswidget.h"
#include "ui_generalsettingswidget.h"
#include <sstream>
#include <QScrollBar>
#include <QMessageBox>
#include <QTimer>
#include <QFile>
@@ -8,15 +15,15 @@
#include "Config.h"
#include "FS.h"
#include "Log.h"
#include "RouterContext.h"
#include "Transports.h"
#include "HTTPServer.h"
#ifndef ANDROID
# include <QtDebug>
#endif
#include <QScrollBar>
#include <fstream>
#include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h"
@@ -27,7 +34,14 @@ MainWindow::MainWindow(QWidget *parent) :
#ifndef ANDROID
,quitting(false)
#endif
,wasSelectingAtStatusMainPage(false)
,showHiddenInfoStatusMainPage(false)
,ui(new Ui::MainWindow)
,statusButtonsUI(new Ui::StatusButtonsForm)
,routerCommandsUI(new Ui::routerCommandsWidget)
,uiSettings(new Ui::GeneralSettingsContentsForm)
,routerCommandsParent(new QWidget(this))
,widgetlocks()
,i2pController(nullptr)
,configItems()
,datadir()
@@ -37,21 +51,31 @@ MainWindow::MainWindow(QWidget *parent) :
{
ui->setupUi(this);
statusButtonsUI->setupUi(ui->statusButtonsPane);
routerCommandsUI->setupUi(routerCommandsParent);
uiSettings->setupUi(ui->settingsContents);
routerCommandsParent->hide();
ui->verticalLayout_2->addWidget(routerCommandsParent);
//,statusHtmlUI(new Ui::StatusHtmlPaneForm)
//statusHtmlUI->setupUi(lastStatusWidgetui->statusWidget);
ui->statusButtonsPane->setFixedSize(171,300);
ui->verticalLayout->setGeometry(QRect(0,0,171,ui->verticalLayout->geometry().height()));
//ui->statusButtonsPane->adjustSize();
//ui->centralWidget->adjustSize();
setWindowTitle(QApplication::translate("AppTitle","I2PD"));
//TODO handle resizes and change the below into resize() call
setFixedSize(width(), 480);
ui->centralWidget->setMinimumHeight(480);
ui->centralWidget->setMaximumHeight(480);
setFixedHeight(550);
ui->centralWidget->setFixedHeight(550);
onResize();
ui->stackedWidget->setCurrentIndex(0);
ui->settingsScrollArea->resize(ui->settingsContentsGridLayout->sizeHint().width()+10,380);
ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380);
QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar();
//QSize szSettContents = ui->settingsContentsGridLayout->minimumSize();
int w = 683;
int h = 3060;
ui->settingsContents->setFixedSize(w, h);
ui->settingsContents->setGeometry(QRect(0,0,w,h));
/*
QPalette pal(palette());
@@ -59,17 +83,55 @@ MainWindow::MainWindow(QWidget *parent) :
ui->settingsContents->setAutoFillBackground(true);
ui->settingsContents->setPalette(pal);
*/
QPalette pal(palette());
pal.setColor(QPalette::Background, Qt::red);
ui->wrongInputLabel->setAutoFillBackground(true);
ui->wrongInputLabel->setPalette(pal);
ui->wrongInputLabel->setMaximumHeight(ui->wrongInputLabel->sizeHint().height());
ui->wrongInputLabel->setVisible(false);
//ui->settingsScrollArea->adjustSize();
/*ui->tunnelsScrollAreaWidgetContents->setFixedSize(
ui->tunnelsScrollArea->width() - barSett->width(), 0);*/
settingsTitleLabelNominalHeight = ui->settingsTitleLabel->height();
#ifndef ANDROID
createActions();
createTrayIcon();
#endif
QObject::connect(ui->statusPagePushButton, SIGNAL(released()), this, SLOT(showStatusPage()));
textBrowser = new TextBrowserTweaked1(this);
//textBrowser->setOpenExternalLinks(false);
textBrowser->setOpenLinks(false);
/*textBrowser->setTextInteractionFlags(textBrowser->textInteractionFlags()|
Qt::LinksAccessibleByMouse|Qt::LinksAccessibleByKeyboard|
Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard);*/
ui->verticalLayout_2->addWidget(textBrowser);
childTextBrowser = new TextBrowserTweaked1(this);
//childTextBrowser->setOpenExternalLinks(false);
childTextBrowser->setOpenLinks(false);
connect(textBrowser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClickedHandler(const QUrl&)));
pageWithBackButton = new PageWithBackButton(this, childTextBrowser);
ui->verticalLayout_2->addWidget(pageWithBackButton);
pageWithBackButton->hide();
connect(pageWithBackButton, SIGNAL(backReleased()), this, SLOT(backClickedFromChild()));
scheduleStatusPageUpdates();
QObject::connect(ui->statusPagePushButton, SIGNAL(released()), this, SLOT(showStatusMainPage()));
showStatusMainPage();
QObject::connect(statusButtonsUI->mainPagePushButton, SIGNAL(released()), this, SLOT(showStatusMainPage()));
QObject::connect(statusButtonsUI->routerCommandsPushButton, SIGNAL(released()), this, SLOT(showStatus_commands_Page()));
QObject::connect(statusButtonsUI->localDestinationsPushButton, SIGNAL(released()), this, SLOT(showStatus_local_destinations_Page()));
QObject::connect(statusButtonsUI->leasesetsPushButton, SIGNAL(released()), this, SLOT(showStatus_leasesets_Page()));
QObject::connect(statusButtonsUI->tunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_tunnels_Page()));
QObject::connect(statusButtonsUI->transitTunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_transit_tunnels_Page()));
QObject::connect(statusButtonsUI->transportsPushButton, SIGNAL(released()), this, SLOT(showStatus_transports_Page()));
QObject::connect(statusButtonsUI->i2pTunnelsPushButton, SIGNAL(released()), this, SLOT(showStatus_i2p_tunnels_Page()));
QObject::connect(statusButtonsUI->samSessionsPushButton, SIGNAL(released()), this, SLOT(showStatus_sam_sessions_Page()));
QObject::connect(textBrowser, SIGNAL(mouseReleased()), this, SLOT(statusHtmlPageMouseReleased()));
QObject::connect(textBrowser, SIGNAL(selectionChanged()), this, SLOT(statusHtmlPageSelectionChanged()));
QObject::connect(routerCommandsUI->runPeerTestPushButton, SIGNAL(released()), this, SLOT(runPeerTest()));
QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit()));
QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit()));
QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage()));
QObject::connect(ui->tunnelsPagePushButton, SIGNAL(released()), this, SLOT(showTunnelsPage()));
@@ -83,132 +145,146 @@ MainWindow::MainWindow(QWidget *parent) :
# define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option))
initFileChooser( OPTION("","conf",[](){return "";}), ui->configFileLineEdit, ui->configFileBrowsePushButton);
initFolderChooser( OPTION("","datadir",[]{return "";}), ui->dataFolderLineEdit, ui->dataFolderBrowsePushButton);
initFileChooser( OPTION("","tunconf",[](){return "";}), ui->tunnelsConfigFileLineEdit, ui->tunnelsConfigFileBrowsePushButton);
initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton);
initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton);
initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton);
initFileChooser( OPTION("","pidfile",[]{return "";}), ui->pidFileLineEdit, ui->pidFileBrowsePushButton);
logOption=initNonGUIOption( OPTION("","log",[]{return "";}));
initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton);
daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";}));
serviceOption=initNonGUIOption( OPTION("","service",[]{return "";}));
logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), ui->logFileLineEdit, ui->logFileBrowsePushButton);
initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), ui->logLevelComboBox);
uiSettings->logDestinationComboBox->clear();
uiSettings->logDestinationComboBox->insertItems(0, QStringList()
<< QApplication::translate("MainWindow", "syslog", 0)
<< QApplication::translate("MainWindow", "stdout", 0)
<< QApplication::translate("MainWindow", "file", 0)
);
initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox);
initIPAddressBox( OPTION("","host",[]{return "";}), ui->routerExternalHostLineEdit, tr("Router external address -> Host"));
initTCPPortBox( OPTION("","port",[]{return "";}), ui->routerExternalPortLineEdit, tr("Router external address -> Port"));
logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton);
initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox);
initCheckBox( OPTION("","ipv6",[]{return "false";}), ui->ipv6CheckBox);
initCheckBox( OPTION("","notransit",[]{return "false";}), ui->notransitCheckBox);
initCheckBox( OPTION("","floodfill",[]{return "false";}), ui->floodfillCheckBox);
initStringBox( OPTION("","bandwidth",[]{return "";}), ui->bandwidthLineEdit);
initStringBox( OPTION("","family",[]{return "";}), ui->familyLineEdit);
initIntegerBox( OPTION("","netid",[]{return "2";}), ui->netIdLineEdit, tr("NetID"));
initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host"));
initTCPPortBox( OPTION("","port",[]{return "";}), uiSettings->routerExternalPortLineEdit, tr("Router external address -> Port"));
initCheckBox( OPTION("","ipv6",[]{return "false";}), uiSettings->ipv6CheckBox);
initCheckBox( OPTION("","notransit",[]{return "false";}), uiSettings->notransitCheckBox);
initCheckBox( OPTION("","floodfill",[]{return "false";}), uiSettings->floodfillCheckBox);
initStringBox( OPTION("","bandwidth",[]{return "";}), uiSettings->bandwidthLineEdit);
initStringBox( OPTION("","family",[]{return "";}), uiSettings->familyLineEdit);
initIntegerBox( OPTION("","netid",[]{return "2";}), uiSettings->netIdLineEdit, tr("NetID"));
#ifdef Q_OS_WIN
initCheckBox( OPTION("","insomnia",[]{return "";}), ui->insomniaCheckBox);
initCheckBox( OPTION("","insomnia",[]{return "";}), uiSettings->insomniaCheckBox);
initNonGUIOption( OPTION("","svcctl",[]{return "";}));
initNonGUIOption( OPTION("","close",[]{return "";}));
#else
ui->insomniaCheckBox->setEnabled(false);
uiSettings->insomniaCheckBox->setEnabled(false);
#endif
initCheckBox( OPTION("http","enabled",[]{return "true";}), ui->webconsoleEnabledCheckBox);
initIPAddressBox( OPTION("http","address",[]{return "";}), ui->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address"));
initTCPPortBox( OPTION("http","port",[]{return "7070";}), ui->webconsolePortLineEdit, tr("HTTP webconsole -> Port"));
initCheckBox( OPTION("http","auth",[]{return "";}), ui->webconsoleBasicAuthCheckBox);
initStringBox( OPTION("http","user",[]{return "i2pd";}), ui->webconsoleUserNameLineEditBasicAuth);
initStringBox( OPTION("http","pass",[]{return "";}), ui->webconsolePasswordLineEditBasicAuth);
initCheckBox( OPTION("http","enabled",[]{return "true";}), uiSettings->webconsoleEnabledCheckBox);
initIPAddressBox( OPTION("http","address",[]{return "";}), uiSettings->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address"));
initTCPPortBox( OPTION("http","port",[]{return "7070";}), uiSettings->webconsolePortLineEdit, tr("HTTP webconsole -> Port"));
initCheckBox( OPTION("http","auth",[]{return "";}), uiSettings->webconsoleBasicAuthCheckBox);
initStringBox( OPTION("http","user",[]{return "i2pd";}), uiSettings->webconsoleUserNameLineEditBasicAuth);
initStringBox( OPTION("http","pass",[]{return "";}), uiSettings->webconsolePasswordLineEditBasicAuth);
initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), ui->httpProxyEnabledCheckBox);
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), ui->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), ui->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), ui->httpProxyKeyFileLineEdit, ui->httpProxyKeyFilePushButton);
initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), uiSettings->httpProxyEnabledCheckBox);
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), ui->comboBox_httpPorxySignatureType);
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), ui->httpProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), ui->httpProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), ui->httpProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), ui->httpProxyOutboundTunnQuantityLineEdit);
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType);
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), uiSettings->httpProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), uiSettings->httpProxyOutboundTunnQuantityLineEdit);
initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), ui->socksProxyEnabledCheckBox);
initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), ui->socksProxyAddressLineEdit, tr("Socks proxy -> IP address"));
initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), ui->socksProxyPortLineEdit, tr("Socks proxy -> Port"));
initFileChooser( OPTION("socksproxy","keys",[]{return "";}), ui->socksProxyKeyFileLineEdit, ui->socksProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), ui->comboBox_socksProxySignatureType);
initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), ui->socksProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), ui->socksProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), ui->socksProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), ui->socksProxyOutboundTunnQuantityLineEdit);
initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), ui->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address"));
initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), ui->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port"));
initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox);
initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address"));
initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), uiSettings->socksProxyPortLineEdit, tr("Socks proxy -> Port"));
initFileChooser( OPTION("socksproxy","keys",[]{return "";}), uiSettings->socksProxyKeyFileLineEdit, uiSettings->socksProxyKeyFilePushButton);
initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_socksProxySignatureType);
initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), uiSettings->socksProxyInboundTunnelsLenLineEdit);
initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit);
initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), uiSettings->socksProxyOutBoundTunnLenLineEdit);
initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), uiSettings->socksProxyOutboundTunnQuantityLineEdit);
initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), uiSettings->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address"));
initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), uiSettings->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port"));
initCheckBox( OPTION("sam","enabled",[]{return "false";}), ui->samEnabledCheckBox);
initIPAddressBox( OPTION("sam","address",[]{return "";}), ui->samAddressLineEdit, tr("SAM -> IP address"));
initTCPPortBox( OPTION("sam","port",[]{return "7656";}), ui->samPortLineEdit, tr("SAM -> Port"));
initCheckBox( OPTION("sam","enabled",[]{return "false";}), uiSettings->samEnabledCheckBox);
initIPAddressBox( OPTION("sam","address",[]{return "";}), uiSettings->samAddressLineEdit, tr("SAM -> IP address"));
initTCPPortBox( OPTION("sam","port",[]{return "7656";}), uiSettings->samPortLineEdit, tr("SAM -> Port"));
initCheckBox( OPTION("bob","enabled",[]{return "false";}), ui->bobEnabledCheckBox);
initIPAddressBox( OPTION("bob","address",[]{return "";}), ui->bobAddressLineEdit, tr("BOB -> IP address"));
initTCPPortBox( OPTION("bob","port",[]{return "2827";}), ui->bobPortLineEdit, tr("BOB -> Port"));
initCheckBox( OPTION("bob","enabled",[]{return "false";}), uiSettings->bobEnabledCheckBox);
initIPAddressBox( OPTION("bob","address",[]{return "";}), uiSettings->bobAddressLineEdit, tr("BOB -> IP address"));
initTCPPortBox( OPTION("bob","port",[]{return "2827";}), uiSettings->bobPortLineEdit, tr("BOB -> Port"));
initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), ui->i2cpEnabledCheckBox);
initIPAddressBox( OPTION("i2cp","address",[]{return "";}), ui->i2cpAddressLineEdit, tr("I2CP -> IP address"));
initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), ui->i2cpPortLineEdit, tr("I2CP -> Port"));
initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), uiSettings->i2cpEnabledCheckBox);
initIPAddressBox( OPTION("i2cp","address",[]{return "";}), uiSettings->i2cpAddressLineEdit, tr("I2CP -> IP address"));
initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), uiSettings->i2cpPortLineEdit, tr("I2CP -> Port"));
initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), ui->i2pControlEnabledCheckBox);
initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), ui->i2pControlAddressLineEdit, tr("I2PControl -> IP address"));
initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), ui->i2pControlPortLineEdit, tr("I2PControl -> Port"));
initStringBox( OPTION("i2pcontrol","password",[]{return "";}), ui->i2pControlPasswordLineEdit);
initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), ui->i2pControlCertFileLineEdit, ui->i2pControlCertFileBrowsePushButton);
initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), ui->i2pControlKeyFileLineEdit, ui->i2pControlKeyFileBrowsePushButton);
initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), uiSettings->i2pControlEnabledCheckBox);
initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address"));
initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), uiSettings->i2pControlPortLineEdit, tr("I2PControl -> Port"));
initStringBox( OPTION("i2pcontrol","password",[]{return "";}), uiSettings->i2pControlPasswordLineEdit);
initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), uiSettings->i2pControlCertFileLineEdit, uiSettings->i2pControlCertFileBrowsePushButton);
initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), uiSettings->i2pControlKeyFileLineEdit, uiSettings->i2pControlKeyFileBrowsePushButton);
initCheckBox( OPTION("upnp","enabled",[]{return "true";}), ui->enableUPnPCheckBox);
initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), ui->upnpNameLineEdit);
initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox);
initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit);
initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), ui->useElGamalPrecomputedTablesCheckBox);
initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox);
initCheckBox( OPTION("reseed","verify",[]{return "";}), ui->reseedVerifyCheckBox);
initFileChooser( OPTION("reseed","file",[]{return "";}), ui->reseedFileLineEdit, ui->reseedFileBrowsePushButton);
initStringBox( OPTION("reseed","urls",[]{return "";}), ui->reseedURLsLineEdit);
initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox);
initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton);
initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit);
initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), ui->addressbookDefaultURLLineEdit);
initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), ui->addressbookSubscriptionsURLslineEdit);
initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit);
initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit);
initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), ui->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels"));
initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), ui->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles"));
initUInt32Box( OPTION("limits","coresize",[]{return "0";}), ui->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize"));
initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), uiSettings->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels"));
initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), uiSettings->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles"));
initUInt32Box( OPTION("limits","coresize",[]{return "0";}), uiSettings->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize"));
initCheckBox( OPTION("trust","enabled",[]{return "false";}), ui->checkBoxTrustEnable);
initStringBox( OPTION("trust","family",[]{return "";}), ui->lineEditTrustFamily);
initStringBox( OPTION("trust","routers",[]{return "";}), ui->lineEditTrustRouters);
initCheckBox( OPTION("trust","hidden",[]{return "false";}), ui->checkBoxTrustHidden);
initCheckBox( OPTION("trust","enabled",[]{return "false";}), uiSettings->checkBoxTrustEnable);
initStringBox( OPTION("trust","family",[]{return "";}), uiSettings->lineEditTrustFamily);
initStringBox( OPTION("trust","routers",[]{return "";}), uiSettings->lineEditTrustRouters);
initCheckBox( OPTION("trust","hidden",[]{return "false";}), uiSettings->checkBoxTrustHidden);
initCheckBox( OPTION("websockets","enabled",[]{return "false";}), ui->checkBoxWebsocketsEnable);
initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), ui->lineEdit_webSock_addr, tr("Websocket server -> IP address"));
initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), ui->lineEdit_webSock_port, tr("Websocket server -> Port"));
initCheckBox( OPTION("websockets","enabled",[]{return "false";}), uiSettings->checkBoxWebsocketsEnable);
initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->lineEdit_webSock_addr, tr("Websocket server -> IP address"));
initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), uiSettings->lineEdit_webSock_port, tr("Websocket server -> Port"));
# undef OPTION
//widgetlocks.add(new widgetlock(widget,lockbtn));
widgetlocks.add(new widgetlock(uiSettings->logDestinationComboBox,uiSettings->logDestComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->logLevelComboBox,uiSettings->logLevelComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton));
widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton));
loadAllConfigs();
//tunnelsFormGridLayoutWidget = new QWidget(ui->tunnelsScrollAreaWidgetContents);
//tunnelsFormGridLayoutWidget->setObjectName(QStringLiteral("tunnelsFormGridLayoutWidget"));
//tunnelsFormGridLayoutWidget->setGeometry(QRect(0, 0, 621, 451));
QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)),
this, SLOT(logDestinationComboBoxValueChanged(const QString &)));
logDestinationComboBoxValueChanged(uiSettings->logDestinationComboBox->currentText());
ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, 451));
appendTunnelForms("");
ui->configFileLineEdit->setEnabled(false);
ui->configFileBrowsePushButton->setEnabled(false);
ui->configFileLineEdit->setText(confpath);
ui->tunnelsConfigFileLineEdit->setText(tunconfpath);
uiSettings->configFileLineEdit->setEnabled(false);
uiSettings->configFileBrowsePushButton->setEnabled(false);
uiSettings->configFileLineEdit->setText(confpath);
uiSettings->tunnelsConfigFileLineEdit->setText(tunconfpath);
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it;
item->installListeners(this);
}
QObject::connect(ui->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)),
QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)),
this, SLOT(reloadTunnelsConfigAndUI()));
QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased()));
@@ -226,11 +302,104 @@ MainWindow::MainWindow(QWidget *parent) :
//QMetaObject::connectSlotsByName(this);
}
void MainWindow::showStatusPage(){ui->stackedWidget->setCurrentIndex(0);}
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(1);}
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(2);}
void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(3);}
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(4);}
void MainWindow::logDestinationComboBoxValueChanged(const QString & text) {
bool fileEnabled = text==QString("file");
uiSettings->logFileLineEdit->setEnabled(fileEnabled);
uiSettings->logFileBrowsePushButton->setEnabled(fileEnabled);
}
void MainWindow::updateRouterCommandsButtons() {
bool acceptsTunnels = i2p::context.AcceptsTunnels ();
routerCommandsUI->declineTransitTunnelsPushButton->setEnabled(acceptsTunnels);
routerCommandsUI->acceptTransitTunnelsPushButton->setEnabled(!acceptsTunnels);
}
void MainWindow::showStatusPage(StatusPage newStatusPage){
ui->stackedWidget->setCurrentIndex(0);
setStatusButtonsVisible(true);
statusPage=newStatusPage;
showHiddenInfoStatusMainPage=false;
if(newStatusPage!=StatusPage::commands){
textBrowser->setHtml(getStatusPageHtml(false));
textBrowser->show();
routerCommandsParent->hide();
pageWithBackButton->hide();
}else{
routerCommandsParent->show();
textBrowser->hide();
pageWithBackButton->hide();
updateRouterCommandsButtons();
}
wasSelectingAtStatusMainPage=false;
}
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);}
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);}
void MainWindow::showRestartPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);}
void MainWindow::showQuitPage(){ui->stackedWidget->setCurrentIndex(4);setStatusButtonsVisible(false);}
void MainWindow::setStatusButtonsVisible(bool visible) {
ui->statusButtonsPane->setVisible(visible);
}
// see also: HTTPServer.cpp
QString MainWindow::getStatusPageHtml(bool showHiddenInfo) {
std::stringstream s;
s << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">";
switch (statusPage) {
case main_page: i2p::http::ShowStatus(s, showHiddenInfo);break;
case commands: break;
case local_destinations: i2p::http::ShowLocalDestinations(s);break;
case leasesets: i2p::http::ShowLeasesSets(s); break;
case tunnels: i2p::http::ShowTunnels(s); break;
case transit_tunnels: i2p::http::ShowTransitTunnels(s); break;
case transports: i2p::http::ShowTransports(s); break;
case i2p_tunnels: i2p::http::ShowI2PTunnels(s); break;
case sam_sessions: i2p::http::ShowSAMSessions(s); break;
default: assert(false); break;
}
std::string str = s.str();
return QString::fromStdString(str);
}
void MainWindow::showStatusMainPage() { showStatusPage(StatusPage::main_page); }
void MainWindow::showStatus_commands_Page() { showStatusPage(StatusPage::commands); }
void MainWindow::showStatus_local_destinations_Page() { showStatusPage(StatusPage::local_destinations); }
void MainWindow::showStatus_leasesets_Page() { showStatusPage(StatusPage::leasesets); }
void MainWindow::showStatus_tunnels_Page() { showStatusPage(StatusPage::tunnels); }
void MainWindow::showStatus_transit_tunnels_Page() { showStatusPage(StatusPage::transit_tunnels); }
void MainWindow::showStatus_transports_Page() { showStatusPage(StatusPage::transports); }
void MainWindow::showStatus_i2p_tunnels_Page() { showStatusPage(StatusPage::i2p_tunnels); }
void MainWindow::showStatus_sam_sessions_Page() { showStatusPage(StatusPage::sam_sessions); }
void MainWindow::scheduleStatusPageUpdates() {
statusPageUpdateTimer = new QTimer(this);
connect(statusPageUpdateTimer, SIGNAL(timeout()), this, SLOT(updateStatusPage()));
statusPageUpdateTimer->start(10*1000/*millis*/);
}
void MainWindow::statusHtmlPageMouseReleased() {
if(wasSelectingAtStatusMainPage){
QString selection = textBrowser->textCursor().selectedText();
if(!selection.isEmpty()&&!selection.isNull())return;
}
showHiddenInfoStatusMainPage=!showHiddenInfoStatusMainPage;
textBrowser->setHtml(getStatusPageHtml(showHiddenInfoStatusMainPage));
}
void MainWindow::statusHtmlPageSelectionChanged() {
wasSelectingAtStatusMainPage=true;
}
void MainWindow::updateStatusPage() {
showHiddenInfoStatusMainPage=false;
textBrowser->setHtml(getStatusPageHtml(showHiddenInfoStatusMainPage));
}
//TODO
void MainWindow::resizeEvent(QResizeEvent *event)
@@ -352,6 +521,7 @@ void MainWindow::handleGracefulQuitTimerEvent() {
MainWindow::~MainWindow()
{
qDebug("Destroying main window");
delete statusPageUpdateTimer;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it;
item->deleteLater();
@@ -376,6 +546,9 @@ void MainWindow::initFolderChooser(ConfigOption option, QLineEdit* folderLineEdi
configItems.append(new ComboBoxItem(option, comboBox));
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAllConfigs()));
}*/
void MainWindow::initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox){
configItems.append(new LogDestinationComboBoxItem(option, comboBox));
}
void MainWindow::initLogLevelCombobox(ConfigOption option, QComboBox* comboBox){
configItems.append(new LogLevelComboBoxItem(option, comboBox));
}
@@ -401,7 +574,7 @@ void MainWindow::initUInt16Box(ConfigOption option, QLineEdit* numberLineEdit, Q
configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated));
}
void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){
configItems.append(new BaseStringItem(option, lineEdit));
configItems.append(new BaseStringItem(option, lineEdit, QString()));
}
NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) {
NonGUIOptionItem * retValue;
@@ -430,10 +603,7 @@ void MainWindow::loadAllConfigs(){
LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config);
} else {
config = i2p::fs::DataDirPath("i2pd.conf");
if (!i2p::fs::Exists (config)) {
// use i2pd.conf only if exists
config = ""; /* reset */
}
/*if (!i2p::fs::Exists (config)) {}*/
}
}
@@ -462,16 +632,20 @@ void MainWindow::loadAllConfigs(){
}
/** returns false iff not valid items present and save was aborted */
bool MainWindow::saveAllConfigs(){
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
programOptionsWriterCurrentSection="";
if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file"));
else logOption->optionValue=boost::any(std::string("stdout"));
/*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file"));
else logOption->optionValue=boost::any(std::string("stdout"));*/
daemonOption->optionValue=boost::any(false);
serviceOption->optionValue=boost::any(false);
std::stringstream out;
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
MainWindowItem* item = *it;
if(!item->isValid()) return false;
if(!item->isValid()){
highlightWrongInput(QApplication::tr("Invalid value for")+" "+item->getConfigOption().section+"::"+item->getConfigOption().option+". "+item->getRequirementToBeValid()+" "+cannotSaveSettings, item->getWidgetToFocus());
return false;
}
}
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
@@ -481,9 +655,10 @@ bool MainWindow::saveAllConfigs(){
using namespace std;
QString backup=confpath+"~";
if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
QFile::rename(confpath, backup);//TODO handle errors
if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors
ofstream outfile;
outfile.open(confpath.toStdString());//TODO handle errors
outfile << out.str().c_str();
@@ -506,15 +681,22 @@ void FolderChooserItem::pushButtonReleased() {
}
void BaseStringItem::installListeners(MainWindow *mainWindow) {
QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(saveAllConfigs()));
QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(updated()));
}
void ComboBoxItem::installListeners(MainWindow *mainWindow) {
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(saveAllConfigs()));
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(updated()));
}
void CheckBoxItem::installListeners(MainWindow *mainWindow) {
QObject::connect(checkBox, SIGNAL(stateChanged(int)), mainWindow, SLOT(saveAllConfigs()));
QObject::connect(checkBox, SIGNAL(stateChanged(int)), mainWindow, SLOT(updated()));
}
void MainWindow::updated() {
ui->wrongInputLabel->setVisible(false);
adjustSizesAccordingToWrongLabel();
applyTunnelsUiToConfigs();
saveAllConfigs();
}
void MainWindowItem::installListeners(MainWindow *mainWindow) {}
@@ -526,27 +708,33 @@ void MainWindow::appendTunnelForms(std::string tunnelNameToFocus) {
TunnelConfig* tunconf = it->second;
ServerTunnelConfig* stc = tunconf->asServerTunnelConfig();
if(stc){
ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc);
ServerTunnelPane * tunnelPane=new ServerTunnelPane(&tunnelsPageUpdateListener, stc, ui->wrongInputLabel, ui->wrongInputLabel, this);
int h=tunnelPane->appendServerTunnelForm(stc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h;
qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
tunnelPanes.push_back(tunnelPane);
if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus();
if(name==tunnelNameToFocus){
tunnelPane->getNameLineEdit()->setFocus();
ui->tunnelsScrollArea->ensureWidgetVisible(tunnelPane->getNameLineEdit());
}
continue;
}
ClientTunnelConfig* ctc = tunconf->asClientTunnelConfig();
if(ctc){
ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc);
ClientTunnelPane * tunnelPane=new ClientTunnelPane(&tunnelsPageUpdateListener, ctc, ui->wrongInputLabel, ui->wrongInputLabel, this);
int h=tunnelPane->appendClientTunnelForm(ctc, ui->tunnelsScrollAreaWidgetContents, tunnelPanes.size(), height);
height+=h;
qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
//qDebug() << "tun.height:" << height << "sz:" << tunnelPanes.size();
tunnelPanes.push_back(tunnelPane);
if(name==tunnelNameToFocus)tunnelPane->getNameLineEdit()->setFocus();
if(name==tunnelNameToFocus){
tunnelPane->getNameLineEdit()->setFocus();
ui->tunnelsScrollArea->ensureWidgetVisible(tunnelPane->getNameLineEdit());
}
continue;
}
throw "unknown TunnelConfig subtype";
}
qDebug() << "tun.setting height:" << height;
//qDebug() << "tun.setting height:" << height;
ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, height));
QList<QWidget*> childWidgets = ui->tunnelsScrollAreaWidgetContents->findChildren<QWidget*>();
foreach(QWidget* widget, childWidgets)
@@ -572,6 +760,14 @@ void MainWindow::deleteTunnelForms() {
tunnelPanes.clear();
}
bool MainWindow::applyTunnelsUiToConfigs() {
for(std::list<TunnelPane*>::iterator it = tunnelPanes.begin(); it != tunnelPanes.end(); ++it) {
TunnelPane* tp = *it;
if(!tp->applyDataFromUIToTunnelConfig())return false;
}
return true;
}
void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) {
deleteTunnelForms();
for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) {
@@ -598,12 +794,14 @@ void MainWindow::SaveTunnelsConfig() {
QString backup=tunconfpath+"~";
if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors
QFile::rename(tunconfpath, backup);//TODO handle errors
if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors
ofstream outfile;
outfile.open(tunconfpath.toStdString());//TODO handle errors
outfile << out.str().c_str();
outfile.close();
i2p::client::context.ReloadConfig();
}
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) {
@@ -613,7 +811,7 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol
if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it);
mainWindow->tunnelConfigs[tunConf->getName()]=tunConf;
}
mainWindow->SaveTunnelsConfig();
mainWindow->saveAllConfigs();
}
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){
@@ -631,3 +829,79 @@ void MainWindow::addClientTunnelPushButtonReleased() {
void MainWindow::setI2PController(i2p::qt::Controller* controller_) {
this->i2pController = controller_;
}
void MainWindow::runPeerTest() {
i2p::transport::transports.PeerTest();
}
void MainWindow::enableTransit() {
i2p::context.SetAcceptsTunnels(true);
updateRouterCommandsButtons();
}
void MainWindow::disableTransit() {
i2p::context.SetAcceptsTunnels(false);
updateRouterCommandsButtons();
}
void MainWindow::anchorClickedHandler(const QUrl & link) {
QString debugStr=QString()+"anchorClicked: "+"\""+link.toString()+"\"";
qDebug()<<debugStr;
//QMessageBox::information(this, "", debugStr);
/* /?page=local_destination&b32=xx...xx */
QString str=link.toString();
#define LOCAL_DEST_B32_PREFIX "/?page=local_destination&b32="
static size_t LOCAL_DEST_B32_PREFIX_SZ=QString(LOCAL_DEST_B32_PREFIX).size();
if(str.startsWith(LOCAL_DEST_B32_PREFIX)) {
str = str.right(str.size()-LOCAL_DEST_B32_PREFIX_SZ);
qDebug () << "b32:" << str;
pageWithBackButton->show();
textBrowser->hide();
std::stringstream s;
i2p::http::ShowLocalDestination(s,str.toStdString());
childTextBrowser->setHtml(QString::fromStdString(s.str()));
}
}
void MainWindow::backClickedFromChild() {
showStatusPage(statusPage);
}
void MainWindow::adjustSizesAccordingToWrongLabel() {
if(ui->wrongInputLabel->isVisible()) {
int dh = ui->wrongInputLabel->height()+ui->verticalLayout_7->layout()->spacing();
ui->verticalLayout_7->invalidate();
ui->wrongInputLabel->adjustSize();
ui->stackedWidget->adjustSize();
ui->stackedWidget->setFixedHeight(531-dh);
ui->settingsPage->setFixedHeight(531-dh);
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531-dh));
ui->stackedWidget->setFixedHeight(531-dh);
ui->settingsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
ui->tunnelsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
}else{
ui->verticalLayout_7->invalidate();
ui->wrongInputLabel->adjustSize();
ui->stackedWidget->adjustSize();
ui->stackedWidget->setFixedHeight(531);
ui->settingsPage->setFixedHeight(531);
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531));
ui->stackedWidget->setFixedHeight(531);
ui->settingsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
ui->tunnelsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
}
}
void MainWindow::highlightWrongInput(QString warningText, QWidget* widgetToFocus) {
bool redVisible = ui->wrongInputLabel->isVisible();
ui->wrongInputLabel->setVisible(true);
ui->wrongInputLabel->setText(warningText);
if(!redVisible)adjustSizesAccordingToWrongLabel();
if(widgetToFocus){ui->settingsScrollArea->ensureWidgetVisible(widgetToFocus);widgetToFocus->setFocus();}
showSettingsPage();
}

View File

@@ -24,6 +24,7 @@
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem>
#include "QVBoxLayout"
#include "QUrl"
#ifndef ANDROID
# include <QSystemTrayIcon>
@@ -40,6 +41,7 @@
#include "ServerTunnelPane.h"
#include "ClientTunnelPane.h"
#include "TunnelConfig.h"
#include "textbrowsertweaked1.h"
#include "Config.h"
#include "FS.h"
@@ -53,6 +55,12 @@
#include "DaemonQT.h"
#include "SignatureTypeComboboxFactory.h"
#include "pagewithbackbutton.h"
#include <iostream>
#include "widgetlockregistry.h"
#include "widgetlock.h"
template<typename ValueType>
bool isType(boost::any& a) {
@@ -85,8 +93,13 @@ class MainWindow;
class MainWindowItem : public QObject {
Q_OBJECT
ConfigOption option;
QWidget* widgetToFocus;
QString requirementToBeValid;
public:
MainWindowItem(ConfigOption option_) : option(option_) {}
MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) : option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {}
QWidget* getWidgetToFocus(){return widgetToFocus;}
QString& getRequirementToBeValid() { return requirementToBeValid; }
ConfigOption& getConfigOption() { return option; }
boost::any optionValue;
virtual ~MainWindowItem(){}
virtual void installListeners(MainWindow *mainWindow);
@@ -94,7 +107,7 @@ public:
std::string optName="";
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
optName+=option.option.toStdString();
qDebug() << "loadFromConfigOption[" << optName.c_str() << "]";
//qDebug() << "loadFromConfigOption[" << optName.c_str() << "]";
boost::any programOption;
i2p::config::GetOptionAsAny(optName, programOption);
optionValue=programOption.empty()?boost::any(std::string(""))
@@ -137,7 +150,7 @@ public:
};
class NonGUIOptionItem : public MainWindowItem {
public:
NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_) {};
NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_, nullptr, QString()) {};
virtual ~NonGUIOptionItem(){}
virtual bool isValid() { return true; }
};
@@ -145,7 +158,7 @@ class BaseStringItem : public MainWindowItem {
Q_OBJECT
public:
QLineEdit* lineEdit;
BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_) : MainWindowItem(option_), lineEdit(lineEdit_){};
BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString requirementToBeValid_) : MainWindowItem(option_, lineEdit_, requirementToBeValid_), lineEdit(lineEdit_){};
virtual ~BaseStringItem(){}
virtual void installListeners(MainWindow *mainWindow);
virtual QString toString(){
@@ -167,7 +180,7 @@ class FileOrFolderChooserItem : public BaseStringItem {
public:
QPushButton* browsePushButton;
FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) :
BaseStringItem(option_, lineEdit_), browsePushButton(browsePushButton_) {}
BaseStringItem(option_, lineEdit_, QString()), browsePushButton(browsePushButton_) {}
virtual ~FileOrFolderChooserItem(){}
};
class FileChooserItem : public FileOrFolderChooserItem {
@@ -193,13 +206,29 @@ public:
class ComboBoxItem : public MainWindowItem {
public:
QComboBox* comboBox;
ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_), comboBox(comboBox_){};
ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_,comboBox_,QString()), comboBox(comboBox_){};
virtual ~ComboBoxItem(){}
virtual void installListeners(MainWindow *mainWindow);
virtual void loadFromConfigOption()=0;
virtual void saveToStringStream(std::stringstream& out)=0;
virtual bool isValid() { return true; }
};
class LogDestinationComboBoxItem : public ComboBoxItem {
public:
LogDestinationComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
virtual ~LogDestinationComboBoxItem(){}
virtual void loadFromConfigOption(){
MainWindowItem::loadFromConfigOption();
const char * ld = boost::any_cast<std::string>(optionValue).c_str();
comboBox->setCurrentText(QString(ld));
}
virtual void saveToStringStream(std::stringstream& out){
std::string logDest = comboBox->currentText().toStdString();
optionValue=logDest;
MainWindowItem::saveToStringStream(out);
}
virtual bool isValid() { return true; }
};
class LogLevelComboBoxItem : public ComboBoxItem {
public:
LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
@@ -235,7 +264,7 @@ public:
class CheckBoxItem : public MainWindowItem {
public:
QCheckBox* checkBox;
CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_), checkBox(checkBox_){};
CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_,checkBox_,QString()), checkBox(checkBox_){};
virtual ~CheckBoxItem(){}
virtual void installListeners(MainWindow *mainWindow);
virtual void loadFromConfigOption(){
@@ -251,62 +280,84 @@ public:
class BaseFormattedStringItem : public BaseStringItem {
public:
QString fieldNameTranslated;
BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseStringItem(option_, lineEdit_), fieldNameTranslated(fieldNameTranslated_) {};
BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, QString requirementToBeValid_) :
BaseStringItem(option_, lineEdit_, requirementToBeValid_), fieldNameTranslated(fieldNameTranslated_) {};
virtual ~BaseFormattedStringItem(){}
virtual bool isValid()=0;
};
class IntegerStringItem : public BaseFormattedStringItem {
public:
IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {};
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be a valid integer.")) {};
virtual ~IntegerStringItem(){}
virtual bool isValid(){return true;}
virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toInt(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<int>(optionValue));}
virtual boost::any fromString(QString s){return boost::any(std::stoi(s.toStdString()));}
};
class UShortStringItem : public BaseFormattedStringItem {
public:
UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {};
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned short integer.")) {};
virtual ~UShortStringItem(){}
virtual bool isValid(){return true;}
virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUShort(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<unsigned short>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((unsigned short)std::stoi(s.toStdString()));}
};
class UInt32StringItem : public BaseFormattedStringItem {
public:
UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {};
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 32-bit integer.")) {};
virtual ~UInt32StringItem(){}
virtual bool isValid(){return true;}
virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUInt(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<uint32_t>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((uint32_t)std::stoi(s.toStdString()));}
};
class UInt16StringItem : public BaseFormattedStringItem {
public:
UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {};
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 16-bit integer.")) {};
virtual ~UInt16StringItem(){}
virtual bool isValid(){return true;}
virtual bool isValid(){
auto str=lineEdit->text();
bool ok;
str.toUShort(&ok);
return ok;
}
virtual QString toString(){return QString::number(boost::any_cast<uint16_t>(optionValue));}
virtual boost::any fromString(QString s){return boost::any((uint16_t)std::stoi(s.toStdString()));}
};
class IPAddressStringItem : public BaseFormattedStringItem {
public:
IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_) {};
virtual bool isValid(){return true;}
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be an IPv4 address")) {};
virtual bool isValid(){return true;}//todo
};
class TCPPortStringItem : public UShortStringItem {
public:
TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
UShortStringItem(option_, lineEdit_, fieldNameTranslated_) {};
virtual bool isValid(){return true;}
};
namespace Ui {
class MainWindow;
class MainWindow;
class StatusButtonsForm;
class routerCommandsWidget;
class GeneralSettingsContentsForm;
}
using namespace i2p::client;
@@ -326,13 +377,20 @@ public:
void setI2PController(i2p::qt::Controller* controller_);
void highlightWrongInput(QString warningText, QWidget* widgetToFocus);
//typedef std::function<QString ()> DefaultValueGetter;
//#ifndef ANDROID
// void setVisible(bool visible);
//#endif
private:
enum StatusPage {main_page, commands, local_destinations, leasesets, tunnels, transit_tunnels,
transports, i2p_tunnels, sam_sessions};
private slots:
void updated();
void handleQuitButton();
void handleGracefulQuitButton();
void handleDoRestartButton();
@@ -342,13 +400,37 @@ private slots:
void iconActivated(QSystemTrayIcon::ActivationReason reason);
void toggleVisibilitySlot();
#endif
void showStatusPage();
void scheduleStatusPageUpdates();
void statusHtmlPageMouseReleased();
void statusHtmlPageSelectionChanged();
void updateStatusPage();
void showStatusMainPage();
void showStatus_commands_Page();
void runPeerTest();
void enableTransit();
void disableTransit();
public slots:
void showStatus_local_destinations_Page();
void showStatus_leasesets_Page();
void showStatus_tunnels_Page();
void showStatus_transit_tunnels_Page();
void showStatus_transports_Page();
void showStatus_i2p_tunnels_Page();
void showStatus_sam_sessions_Page();
void showSettingsPage();
void showTunnelsPage();
void showRestartPage();
void showQuitPage();
private:
StatusPage statusPage;
QTimer * statusPageUpdateTimer;
bool wasSelectingAtStatusMainPage;
bool showHiddenInfoStatusMainPage;
void showStatusPage(StatusPage newStatusPage);
#ifndef ANDROID
void createActions();
void createTrayIcon();
@@ -358,26 +440,48 @@ private:
QMenu *trayIconMenu;
#endif
public:
Ui::MainWindow* ui;
Ui::StatusButtonsForm* statusButtonsUI;
Ui::routerCommandsWidget* routerCommandsUI;
Ui::GeneralSettingsContentsForm* uiSettings;
void adjustSizesAccordingToWrongLabel();
bool applyTunnelsUiToConfigs();
private:
int settingsTitleLabelNominalHeight;
TextBrowserTweaked1 * textBrowser;
QWidget * routerCommandsParent;
PageWithBackButton * pageWithBackButton;
TextBrowserTweaked1 * childTextBrowser;
widgetlockregistry widgetlocks;
i2p::qt::Controller* i2pController;
protected:
void updateRouterCommandsButtons();
#ifndef ANDROID
void closeEvent(QCloseEvent *event);
#endif
void resizeEvent(QResizeEvent* event);
void onResize();
void setStatusButtonsVisible(bool visible);
QString getStatusPageHtml(bool showHiddenInfo);
QList<MainWindowItem*> configItems;
NonGUIOptionItem* logOption;
NonGUIOptionItem* daemonOption;
NonGUIOptionItem* serviceOption;
//LogDestinationComboBoxItem* logOption;
FileChooserItem* logFileNameOption;
FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton);
void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton);
//void initCombobox(ConfigOption option, QComboBox* comboBox);
void initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox);
void initLogLevelCombobox(ConfigOption option, QComboBox* comboBox);
void initSignatureTypeCombobox(ConfigOption option, QComboBox* comboBox);
void initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated);
@@ -402,6 +506,11 @@ public slots:
void addServerTunnelPushButtonReleased();
void addClientTunnelPushButtonReleased();
void anchorClickedHandler(const QUrl & link);
void backClickedFromChild();
void logDestinationComboBoxValueChanged(const QString & text);
private:
QString datadir;
QString confpath;
@@ -466,9 +575,9 @@ private:
TunnelConfig* tc=it->second;
tunnelConfigs.erase(it);
delete tc;
SaveTunnelsConfig();
reloadTunnelsConfigAndUI("");
}
saveAllConfigs();
reloadTunnelsConfigAndUI("");
}
std::string GenerateNewTunnelName() {
@@ -503,7 +612,7 @@ private:
destinationPort,
sigType);
SaveTunnelsConfig();
saveAllConfigs();
reloadTunnelsConfigAndUI(name);
}
@@ -542,7 +651,7 @@ private:
isUniqueLocal);
SaveTunnelsConfig();
saveAllConfigs();
reloadTunnelsConfigAndUI(name);
}
@@ -584,13 +693,17 @@ private:
{
// mandatory params
std::string dest;
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
std::cout << "had read tunnel dest: " << dest << std::endl;
}
int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
std::cout << "had read tunnel port: " << port << std::endl;
// optional params
std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
int destinationPort = section.second.get<int>(I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
std::cout << "had read tunnel destinationPort: " << destinationPort << std::endl;
i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
// I2CP
std::map<std::string, std::string> options;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
#include "pagewithbackbutton.h"
#include "QVBoxLayout"
#include "QHBoxLayout"
#include "QPushButton"
PageWithBackButton::PageWithBackButton(QWidget *parent, QWidget* child) : QWidget(parent)
{
QVBoxLayout * layout = new QVBoxLayout();
setLayout(layout);
QWidget * topBar = new QWidget();
QHBoxLayout * topBarLayout = new QHBoxLayout();
topBar->setLayout(topBarLayout);
layout->addWidget(topBar);
layout->addWidget(child);
QPushButton * backButton = new QPushButton(topBar);
backButton->setText("< Back");
topBarLayout->addWidget(backButton);
connect(backButton, SIGNAL(released()), this, SLOT(backReleasedSlot()));
}
void PageWithBackButton::backReleasedSlot() {
emit backReleased();
}

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